From 5db6213f34318031ece7e2a6765f69564b671891 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 8 Oct 2013 19:20:49 +0100 Subject: Initial Metadata Commit [SEE DESC] + Pigs, Minecarts, Sheep, Skeletons, Slimes, Villagers, Wolves, and Horses have metadata + Base code on taming wolves, shearing sheep, and taming horses + Sheep and horses have different colours when spawned --- VC2008/MCServer.vcproj | 4 + source/Entities/Entity.h | 63 ++++++++++++ source/Entities/Minecart.cpp | 58 ++++++++++- source/Entities/Minecart.h | 13 ++- source/Mobs/Horse.cpp | 95 ++++++++++++++++- source/Mobs/Horse.h | 19 +++- source/Mobs/Magmacube.h | 1 + source/Mobs/Pig.cpp | 49 ++++++++- source/Mobs/Pig.h | 7 ++ source/Mobs/Sheep.cpp | 28 ++++- source/Mobs/Sheep.h | 16 ++- source/Mobs/Skeleton.cpp | 5 +- source/Mobs/Skeleton.h | 8 +- source/Mobs/Slime.cpp | 2 - source/Mobs/Slime.h | 1 + source/Mobs/Villager.cpp | 22 +++- source/Mobs/Villager.h | 10 +- source/Mobs/Wolf.cpp | 79 +++++++++++++++ source/Mobs/Wolf.h | 22 +++- source/Protocol/Protocol125.cpp | 220 +++++++++++++++++++++++++++++++++++----- source/Protocol/Protocol125.h | 7 +- source/Protocol/Protocol132.cpp | 3 +- source/World.cpp | 77 ++++++++------ 23 files changed, 714 insertions(+), 95 deletions(-) create mode 100644 source/Mobs/Wolf.cpp diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index c1c2593bf..cf1bb5b77 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1139,6 +1139,10 @@ RelativePath="..\source\Mobs\Wither.h" > + + diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h index a2c99d2a0..764c5a64b 100644 --- a/source/Entities/Entity.h +++ b/source/Entities/Entity.h @@ -71,6 +71,13 @@ public: ENTITY_STATUS_WOLF_SHAKING = 8, ENTITY_STATUS_EATING_ACCEPTED = 9, 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 @@ -333,6 +340,62 @@ public: virtual bool IsRiding (void) const {return false; } virtual bool IsSprinting(void) const {return false; } virtual bool IsRclking (void) const {return false; } + virtual bool IsInvisible(void) const {return false; } + + // Ageables + Tameables + virtual bool IsBabby (void) const {return false; } + virtual bool IsSitting (void) const {return false; } + virtual bool IsTame (void) const {return false; } + + // Creepers + virtual bool IsCharged (void) const {return false; } + virtual bool IsBlowing (void) const {return false; } + + // Furnace Minecarts & Minecarts + virtual int LastDamage (void) const {return 0; } + virtual bool IsFueled (void) const {return false; } + + // Bat + virtual bool IsHanging (void) const {return false; } + + // Pig + virtual bool IsSaddled (void) const {return false; } + + // TESTIFICATE + virtual int GetVilType(void) const {return 0; } + + // Zombie + virtual bool IsVillager(void) const {return false; } + virtual bool IsConvert (void) const {return false; } + + // Ghast + virtual bool IsCharging(void) const {return false; } + + // Arrow + virtual bool IsCritical(void) const {return false; } + + // Wolf + virtual bool IsAngry (void) const {return false; } + virtual bool IsBegging (void) const {return false; } + virtual int GetCollar (void) const {return 0; } + + // Sheep + virtual int GetFurColor(void) const {return 0; } + virtual bool IsSheared (void) const {return false; } + + // Enderman + virtual BLOCKTYPE CarriedBlock (void) const {return E_BLOCK_AIR; } + virtual NIBBLETYPE CarriedMeta (void) const {return 0; } + virtual bool IsScream (void) const {return false; } + + // Skeleton || Wither Skeleton + virtual bool IsWither (void) const {return false; } + + // Witch + virtual bool IsNosey (void) const {return false; } + + // Slimes and Magma cubes + virtual int GetSize (void) const {return 1; } // tolua_end diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp index a2f1e5593..1711e296f 100644 --- a/source/Entities/Minecart.cpp +++ b/source/Entities/Minecart.cpp @@ -16,7 +16,8 @@ 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), - m_Payload(a_Payload) + m_Payload(a_Payload), + m_LastDamage(0) { SetMass(20.f); SetMaxHealth(6); @@ -344,11 +345,51 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) void cMinecart::DoTakeDamage(TakeDamageInfo & TDI) { + m_LastDamage = TDI.FinalDamage; super::DoTakeDamage(TDI); + m_World->BroadcastEntityMetadata(*this); + if (GetHealth() <= 0) { 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(0, 1, 0)); + break; + } + case mpHopper: + { + Drops.push_back(cItem(0, 1, 0)); + break; + } + default: + { + ASSERT(!"Unhandled minecart type when spawning pickup!"); + return; + } + } + + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ()); } } @@ -434,7 +475,8 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player) // cMinecartWithFurnace: 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) { } @@ -444,8 +486,16 @@ cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) : void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player) { - // Try to power the furnace with whatever the player is holding - // TODO + if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + + m_IsFueled = true; + m_World->BroadcastEntityMetadata(*this); + } } diff --git a/source/Entities/Minecart.h b/source/Entities/Minecart.h index 0152f5dfc..f974ea76a 100644 --- a/source/Entities/Minecart.h +++ b/source/Entities/Minecart.h @@ -50,16 +50,19 @@ public: // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) 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; - + int LastDamage(void) const { return m_LastDamage; } + void HandleRailPhysics(float a_Dt, cChunk & a_Chunk); ePayload GetPayload(void) const { return m_Payload; } protected: ePayload m_Payload; cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z); + + int m_LastDamage; + } ; @@ -127,6 +130,12 @@ public: // cEntity overrides: virtual void OnRightClicked(cPlayer & a_Player) override; + bool IsFueled (void) const { return m_IsFueled; } + +private: + + bool m_IsFueled; + } ; diff --git a/source/Mobs/Horse.cpp b/source/Mobs/Horse.cpp index 05ac73c15..50eab33cc 100644 --- a/source/Mobs/Horse.cpp +++ b/source/Mobs/Horse.cpp @@ -2,13 +2,26 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Horse.h" +#include "../World.h" +#include "../Entities/Player.h" -cHorse::cHorse(void) : - super("Horse", 100, "mob.horse.hit", "mob.horse.death", 1.4, 1.6) +cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : + super("Horse", 100, "mob.horse.hit", "mob.horse.death", 1.4, 1.6), + m_bIsChested(false), + m_bIsEating(false), + m_bIsRearing(false), + m_bIsMouthOpen(false), + m_bIsTame(false), + m_Type(Type), + m_Color(Color), + m_Style(Style), + m_Armour(0), + m_TimesToTame(TameTimes), + m_TameAttemptTimes(0) { } @@ -16,6 +29,84 @@ 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) && (m_World->GetTickRandomNumber(15) == 6)) + { + m_bIsRearing = false; + } + + 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) { AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER); diff --git a/source/Mobs/Horse.h b/source/Mobs/Horse.h index ea6e441bd..d950ff1bf 100644 --- a/source/Mobs/Horse.h +++ b/source/Mobs/Horse.h @@ -13,11 +13,28 @@ class cHorse : typedef cPassiveMonster super; public: - cHorse(void); + cHorse(int Type, int Color, int Style, int TameTimes); CLASS_PROTODEF(cHorse); 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 IsChested (void) const {return m_bIsChested; } + 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 GetHType (void) const {return m_Type; } + int GetHColor (void) const {return m_Color; } + int GetHStyle (void) const {return m_Style; } + int GetHArmour (void) const {return m_Armour;} + +private: + + bool m_bIsChested, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame; + int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes; + } ; diff --git a/source/Mobs/Magmacube.h b/source/Mobs/Magmacube.h index 80a1d0701..130952970 100644 --- a/source/Mobs/Magmacube.h +++ b/source/Mobs/Magmacube.h @@ -19,6 +19,7 @@ public: CLASS_PROTODEF(cMagmaCube); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + int GetSize(void) const { return m_Size; } protected: diff --git a/source/Mobs/Pig.cpp b/source/Mobs/Pig.cpp index 9df2c2571..cd18c087f 100644 --- a/source/Mobs/Pig.cpp +++ b/source/Mobs/Pig.cpp @@ -2,13 +2,16 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Pig.h" +#include "../Entities/Player.h" +#include "../World.h" 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); + } +} + + + + + diff --git a/source/Mobs/Pig.h b/source/Mobs/Pig.h index ae790ac2f..4fd0d8db8 100644 --- a/source/Mobs/Pig.h +++ b/source/Mobs/Pig.h @@ -18,6 +18,13 @@ public: CLASS_PROTODEF(cPig); 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; + } ; diff --git a/source/Mobs/Sheep.cpp b/source/Mobs/Sheep.cpp index 2f371f384..440c5c2b9 100644 --- a/source/Mobs/Sheep.cpp +++ b/source/Mobs/Sheep.cpp @@ -3,15 +3,17 @@ #include "Sheep.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), 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); + } +} + + + + diff --git a/source/Mobs/Sheep.h b/source/Mobs/Sheep.h index 369fc78c5..8293a2c05 100644 --- a/source/Mobs/Sheep.h +++ b/source/Mobs/Sheep.h @@ -13,14 +13,20 @@ class cSheep : typedef cPassiveMonster super; public: - cSheep(void); + cSheep(int a_Color); - bool m_IsSheared; - NIBBLETYPE m_WoolColor; // Uses E_META_WOOL_ constants for colors - CLASS_PROTODEF(cSheep); - + 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; + } ; diff --git a/source/Mobs/Skeleton.cpp b/source/Mobs/Skeleton.cpp index 10dad4065..6297b867c 100644 --- a/source/Mobs/Skeleton.cpp +++ b/source/Mobs/Skeleton.cpp @@ -8,8 +8,9 @@ -cSkeleton::cSkeleton(void) : - super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8) +cSkeleton::cSkeleton(bool IsWither) : + super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8), + m_bIsWither(IsWither) { SetBurnsInDaylight(true); } diff --git a/source/Mobs/Skeleton.h b/source/Mobs/Skeleton.h index d0a2da490..7a4af7e22 100644 --- a/source/Mobs/Skeleton.h +++ b/source/Mobs/Skeleton.h @@ -13,11 +13,17 @@ class cSkeleton : typedef cAggressiveMonster super; public: - cSkeleton(); + cSkeleton(bool IsWither); CLASS_PROTODEF(cSkeleton); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + bool IsWither(void) const { return m_bIsWither; }; + +private: + + bool m_bIsWither; + } ; diff --git a/source/Mobs/Slime.cpp b/source/Mobs/Slime.cpp index b209ac869..7a9487a06 100644 --- a/source/Mobs/Slime.cpp +++ b/source/Mobs/Slime.cpp @@ -3,8 +3,6 @@ #include "Slime.h" -// TODO: Implement sized slimes - diff --git a/source/Mobs/Slime.h b/source/Mobs/Slime.h index 88136ff32..782c3113f 100644 --- a/source/Mobs/Slime.h +++ b/source/Mobs/Slime.h @@ -19,6 +19,7 @@ public: CLASS_PROTODEF(cSlime); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + int GetSize(void) const { return m_Size; } protected: diff --git a/source/Mobs/Villager.cpp b/source/Mobs/Villager.cpp index 98e5276e1..cb50d8cfc 100644 --- a/source/Mobs/Villager.cpp +++ b/source/Mobs/Villager.cpp @@ -2,16 +2,34 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Villager.h" +#include "../World.h" -cVillager::cVillager(void) : - super("Villager", 120, "", "", 0.6, 1.8) +cVillager::cVillager(int Type) : + super("Villager", 120, "", "", 0.6, 1.8), + m_Type(Type) { } + +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); + } + } +} + + + + diff --git a/source/Mobs/Villager.h b/source/Mobs/Villager.h index 92267a979..5fcb519dd 100644 --- a/source/Mobs/Villager.h +++ b/source/Mobs/Villager.h @@ -13,9 +13,17 @@ class cVillager : typedef cPassiveMonster super; public: - cVillager(); + cVillager(int Type); CLASS_PROTODEF(cVillager); + + virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; + int GetVilType(void) const { return m_Type; } + +private: + + int m_Type; + } ; diff --git a/source/Mobs/Wolf.cpp b/source/Mobs/Wolf.cpp new file mode 100644 index 000000000..e76f991dc --- /dev/null +++ b/source/Mobs/Wolf.cpp @@ -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); +} + + + + diff --git a/source/Mobs/Wolf.h b/source/Mobs/Wolf.h index 405df80a6..98074ba11 100644 --- a/source/Mobs/Wolf.h +++ b/source/Mobs/Wolf.h @@ -13,13 +13,25 @@ class cWolf : typedef cPassiveAggressiveMonster super; public: - 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) - { - } + cWolf(void); 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; + } ; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 54bd28c9f..89b2c15ec 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -343,8 +343,9 @@ void cProtocol125::SendEntityMetadata(const cEntity & a_Entity) cCSLock Lock(m_CSPacket); WriteByte(PACKET_METADATA); WriteInt (a_Entity.GetUniqueID()); - AString MetaData = GetEntityMetaData(a_Entity); - SendData(MetaData.data(), MetaData.size()); + + WriteMetadata(a_Entity); + Flush(); } @@ -710,8 +711,7 @@ void cProtocol125::SendSpawnMob(const cMonster & a_Mob) WriteByte (0); WriteByte (0); WriteByte (0); - AString MetaData = GetEntityMetaData(a_Mob); - SendData (MetaData.data(), MetaData.size()); + WriteMetadata(a_Mob); Flush(); } @@ -1614,48 +1614,212 @@ int cProtocol125::ParseItem(cItem & a_Item) -AString cProtocol125::GetEntityMetaData(const cEntity & a_Entity) +void cProtocol125::WriteMetadata(const cEntity & a_Entity) { - // We should send all the metadata here - 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; -} + // Common Metadata + Byte CommonMetadata = 0; - - - -char cProtocol125::GetEntityMetadataFlags(const cEntity & a_Entity) -{ - char Flags = 0; if (a_Entity.IsOnFire()) { - Flags |= 1; + CommonMetadata |= 0x1; } if (a_Entity.IsCrouched()) { - Flags |= 2; + CommonMetadata |= 0x2; } if (a_Entity.IsRiding()) { - Flags |= 4; + CommonMetadata |= 0x4; } if (a_Entity.IsSprinting()) { - Flags |= 8; + CommonMetadata |= 0x8; } if (a_Entity.IsRclking()) { - Flags |= 16; + CommonMetadata |= 0x16; + } + if (a_Entity.IsInvisible()) + { + CommonMetadata |= 0x32; + } + + WriteByte(0x0); + WriteByte(CommonMetadata); + + // Common Metadata End + // Specific Entity Metadata + + 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))) * a_Entity.LastDamage()) * 4 ); + WriteByte(0x52); + WriteInt(1); // Shaking direction, doesn't seem to affect anything + WriteByte(0x73); + WriteFloat((float)(a_Entity.LastDamage() + 10)); // Damage taken / shake effect multiplyer + } + else if (a_Entity.IsA("cCreeper")) + { + WriteByte(0x10); + WriteByte(a_Entity.IsBlowing() ? 1 : -1); // Blowing up? + WriteByte(0x11); + WriteByte(a_Entity.IsCharged() ? 1 : 0); // Lightning-charged? + } + else if (a_Entity.IsA("cMinecartWithFurnace")) + { + WriteByte(0x10); + WriteByte(a_Entity.IsFueled() ? 1 : 0); // Fueled? + } + else if (a_Entity.IsA("cBat")) + { + WriteByte(0x10); + WriteByte(a_Entity.IsHanging() ? 1 : 0); // Upside down? + } + else if (a_Entity.IsA("cPig")) + { + WriteByte(0x10); + WriteByte(a_Entity.IsSaddled() ? 1 : 0); // Saddled? + } + else if (a_Entity.IsA("cVillager")) + { + WriteByte(0x50); + WriteInt(a_Entity.GetVilType()); // What sort of TESTIFICATE? + } + else if (a_Entity.IsA("cZombie")) + { + WriteByte(0xC); + WriteByte(a_Entity.IsBabby() ? 1 : 0); // Babby zombie? + WriteByte(0xD); + WriteByte(a_Entity.IsVillZomb() ? 1 : 0); // Converted zombie? + WriteByte(0xE); + WriteByte(a_Entity.IsConvert() ? 1 : 0); // Converted-but-converting-back zombllager? + } + else if (a_Entity.IsA("cGhast")) + { + WriteByte(0x10); + WriteByte(a_Entity.IsCharging()); // About to eject un flamé-bol? :P + } + else if (a_Entity.IsA("cArrowEntity")) + { + WriteByte(0x10); + WriteByte(a_Entity.IsCritical() ? 1 : 0); // Critical hitting arrow? + } + else if (a_Entity.IsA("cWolf")) + { + Byte WolfStatus = 0; + if (a_Entity.IsSitting()) + { + WolfStatus |= 0x1; + } + if (a_Entity.IsAngry()) + { + WolfStatus |= 0x2; + } + if (a_Entity.IsTame()) + { + WolfStatus |= 0x4; + } + WriteByte(0x10); + WriteByte(WolfStatus); + + WriteByte(0x72); + WriteFloat((float)(a_Entity.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way) + WriteByte(0x13); + WriteByte(a_Entity.IsBegging() ? 1 : 0); // Ultra cute mode? + } + else if (a_Entity.IsA("cSheep")) + { + // [1](1111) + // [] = Is sheared? () = Color, from 0 to 15 + + WriteByte(0x10); + Byte SheepMetadata = 0; + SheepMetadata = a_Entity.GetFurColor(); // Fur colour + + if (a_Entity.IsSheared()) // Is sheared? + { + SheepMetadata |= 0x16; + } + WriteByte(SheepMetadata); + } + else if (a_Entity.IsA("cEnderman")) + { + WriteByte(0x10); + WriteByte(a_Entity.CarriedBlock()); // Stolen block + WriteByte(0x11); + WriteByte(a_Entity.CarriedMeta()); // Stolen metea + WriteByte(0x12); + WriteByte(a_Entity.IsScream() ? 1 : 0); // I HATE YER FACE, I SCWEAM AT YER FACE + } + else if (a_Entity.IsA("cSkeleton")) + { + WriteByte(0xD); + WriteByte(a_Entity.IsWither() ? 1 : 0); // It's a skeleton, but it's not + } + else if (a_Entity.IsA("cWitch")) + { + WriteByte(0x15); + WriteByte(a_Entity.IsNosey() ? 1 : 0); // Drinking-nose: like Squidward + } + else if ((a_Entity.IsA("cSlime")) || (a_Entity.IsA("cMagmaCube"))) + { + WriteByte(0x10); + WriteByte(a_Entity.GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + } + else if (a_Entity.IsA("cHorse")) + { + int Flags = 0; + if (a_Entity.IsTame()) + { + Flags |= 0x2; + } + if (a_Entity.IsSaddled()) + { + Flags |= 0x4; + } + if (a_Entity.IsChested()) + { + Flags |= 0x8; + } + if (a_Entity.IsBabby()) + { + Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer + } + if (a_Entity.IsEating()) + { + Flags |= 0x20; + } + if (a_Entity.IsRearing()) + { + Flags |= 0x40; + } + if (a_Entity.IsMthOpen()) + { + Flags |= 0x80; + } + WriteByte(0x50); + WriteInt(Flags); + + WriteByte(0x13); + WriteByte(a_Entity.GetHType()); // Type of horse (donkey, chestnut, etc.) + + WriteByte(0x54); + int Appearance = 0; + Appearance = a_Entity.GetHColor(); // Mask FF + Appearance |= a_Entity.GetHStyle() * 256; // Mask FF00, so multiply by 256 + WriteInt(Appearance); + + WriteByte(0x56); + WriteInt(a_Entity.GetHArmour()); // Horshey armour } - return Flags; + + // End Specific Metadata + // End Metadata Packet + + WriteByte(0x7f); } diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h index c5c8cd1a0..7b493881b 100644 --- a/source/Protocol/Protocol125.h +++ b/source/Protocol/Protocol125.h @@ -142,11 +142,8 @@ protected: /// Parses one item, "slot" as the protocol wiki calls it, from m_ReceivedData; returns the usual ParsePacket() codes virtual int ParseItem(cItem & a_Item); - /// Returns the entity metadata representation - AString GetEntityMetaData(const cEntity & a_Entity); - - /// Returns the entity common metadata, index 0 (generic flags) - char GetEntityMetadataFlags(const cEntity & a_Entity); + /// Writes the entity metadata + void WriteMetadata(const cEntity & a_Entity); } ; diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp index a06eb0b8b..63b838b70 100644 --- a/source/Protocol/Protocol132.cpp +++ b/source/Protocol/Protocol132.cpp @@ -416,8 +416,7 @@ void cProtocol132::SendSpawnMob(const cMonster & a_Mob) WriteShort ((short)(a_Mob.GetSpeedX() * 400)); WriteShort ((short)(a_Mob.GetSpeedY() * 400)); WriteShort ((short)(a_Mob.GetSpeedZ() * 400)); - AString MetaData = GetEntityMetaData(a_Mob); - SendData (MetaData.data(), MetaData.size()); + WriteMetadata(a_Mob); Flush(); } diff --git a/source/World.cpp b/source/World.cpp index 606ef0787..784df49f3 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -2571,40 +2571,53 @@ bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ) int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) { cMonster * Monster = NULL; + + int SlSize = GetTickRandomNumber(2) + 1; // 1 .. 3 - Slime + int ShColor = GetTickRandomNumber(15); // 0 .. 15 - Sheep + bool SkType = GetDimension() == biNether; // Skeleton + int VilType = GetTickRandomNumber(5); // 0 .. 5 - Villager + + 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 - int Size = GetTickRandomNumber(2) + 1; // 1 .. 3 + if ((HseType == 5) || (HseType == 6) || (HseType == 7)) { HseType = 0; } // 5,6,7 = 0 because little chance of getting 0 with TickRand switch (a_MonsterType) { - case cMonster::mtBat: Monster = new cBat(); break; - case cMonster::mtBlaze: Monster = new cBlaze(); break; - case cMonster::mtCaveSpider: Monster = new cCavespider(); break; - case cMonster::mtChicken: Monster = new cChicken(); break; - case cMonster::mtCow: Monster = new cCow(); break; - case cMonster::mtCreeper: Monster = new cCreeper(); break; - case cMonster::mtEnderman: Monster = new cEnderman(); break; - case cMonster::mtEnderDragon: Monster = new cEnderDragon(); break; - case cMonster::mtGhast: Monster = new cGhast(); break; - case cMonster::mtGiant: Monster = new cGiant(); break; - case cMonster::mtHorse: Monster = new cHorse(); break; - case cMonster::mtIronGolem: Monster = new cIronGolem(); break; - case cMonster::mtMagmaCube: Monster = new cMagmaCube(Size); break; - case cMonster::mtMooshroom: Monster = new cMooshroom(); break; - case cMonster::mtOcelot: Monster = new cOcelot(); break; - case cMonster::mtPig: Monster = new cPig(); break; - case cMonster::mtSheep: Monster = new cSheep(); break; - case cMonster::mtSilverfish: Monster = new cSilverfish(); break; - case cMonster::mtSkeleton: Monster = new cSkeleton(); break; - case cMonster::mtSlime: Monster = new cSlime(Size); break; - case cMonster::mtSnowGolem: Monster = new cSnowGolem(); break; - case cMonster::mtSpider: Monster = new cSpider(); break; - case cMonster::mtSquid: Monster = new cSquid(); break; - case cMonster::mtVillager: Monster = new cVillager(); break; - case cMonster::mtWitch: Monster = new cWitch(); break; - case cMonster::mtWither: Monster = new cWither(); break; - case cMonster::mtWolf: Monster = new cWolf(); break; - case cMonster::mtZombie: Monster = new cZombie(); break; - case cMonster::mtZombiePigman: Monster = new cZombiePigman(); break; + case cMonster::mtBat: Monster = new cBat(); break; + case cMonster::mtBlaze: Monster = new cBlaze(); break; + case cMonster::mtCaveSpider: Monster = new cCavespider(); break; + case cMonster::mtChicken: Monster = new cChicken(); break; + case cMonster::mtCow: Monster = new cCow(); break; + case cMonster::mtCreeper: Monster = new cCreeper(); break; + case cMonster::mtEnderman: Monster = new cEnderman(); break; + case cMonster::mtEnderDragon: Monster = new cEnderDragon(); break; + case cMonster::mtGhast: Monster = new cGhast(); break; + case cMonster::mtGiant: Monster = new cGiant(); break; + case cMonster::mtHorse: + { + Monster = new cHorse(HseType, HseColor, HseStyle, HseTameTimes); break; + } + case cMonster::mtIronGolem: Monster = new cIronGolem(); break; + case cMonster::mtMagmaCube: Monster = new cMagmaCube(SlSize); break; + case cMonster::mtMooshroom: Monster = new cMooshroom(); break; + case cMonster::mtOcelot: Monster = new cOcelot(); break; + case cMonster::mtPig: Monster = new cPig(); break; + case cMonster::mtSheep: Monster = new cSheep(ShColor); break; + case cMonster::mtSilverfish: Monster = new cSilverfish(); break; + case cMonster::mtSkeleton: Monster = new cSkeleton(SkType); break; + case cMonster::mtSlime: Monster = new cSlime(SlSize); break; + case cMonster::mtSnowGolem: Monster = new cSnowGolem(); break; + case cMonster::mtSpider: Monster = new cSpider(); break; + case cMonster::mtSquid: Monster = new cSquid(); break; + case cMonster::mtVillager: Monster = new cVillager(VilType); break; + case cMonster::mtWitch: Monster = new cWitch(); break; + case cMonster::mtWither: Monster = new cWither(); break; + case cMonster::mtWolf: Monster = new cWolf(); break; + case cMonster::mtZombie: Monster = new cZombie(); break; + case cMonster::mtZombiePigman: Monster = new cZombiePigman(); break; default: { @@ -2624,7 +2637,11 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp delete Monster; return -1; } + 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); return Monster->GetUniqueID(); } -- cgit v1.2.3 From 7401fc000dca2a3ff3ce61776f84e5c2d8eb1868 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 8 Oct 2013 22:21:55 +0100 Subject: Initial round of fixes * Fixed intentional misspelling of baby! :D * Better chested horse bool name * Fixed some weird continuity issues with my recent changes not being pushed up initially * Fixed derpy hexadecimal values --- source/Entities/Entity.h | 44 +++++++++++++++++++++++++---------------- source/Mobs/Horse.cpp | 2 +- source/Mobs/Horse.h | 6 +++--- source/Protocol/Protocol125.cpp | 8 ++++---- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h index 764c5a64b..fdc047cf9 100644 --- a/source/Entities/Entity.h +++ b/source/Entities/Entity.h @@ -343,7 +343,7 @@ public: virtual bool IsInvisible(void) const {return false; } // Ageables + Tameables - virtual bool IsBabby (void) const {return false; } + virtual bool IsBaby (void) const {return false; } virtual bool IsSitting (void) const {return false; } virtual bool IsTame (void) const {return false; } @@ -356,46 +356,56 @@ public: virtual bool IsFueled (void) const {return false; } // Bat - virtual bool IsHanging (void) const {return false; } + virtual bool IsHanging (void) const {return false; } // Pig - virtual bool IsSaddled (void) const {return false; } + virtual bool IsSaddled (void) const {return false; } // TESTIFICATE - virtual int GetVilType(void) const {return 0; } + virtual int GetVilType (void) const {return 0; } // Zombie - virtual bool IsVillager(void) const {return false; } - virtual bool IsConvert (void) const {return false; } + virtual bool IsVillZomb (void) const {return false; } + virtual bool IsConvert (void) const {return false; } // Ghast - virtual bool IsCharging(void) const {return false; } + virtual bool IsCharging (void) const {return false; } // Arrow - virtual bool IsCritical(void) const {return false; } + virtual bool IsCritical (void) const {return false; } // Wolf - virtual bool IsAngry (void) const {return false; } - virtual bool IsBegging (void) const {return false; } - virtual int GetCollar (void) const {return 0; } + virtual bool IsAngry (void) const {return false; } + virtual bool IsBegging (void) const {return false; } + virtual int GetCollar (void) const {return 0; } // Sheep - virtual int GetFurColor(void) const {return 0; } - virtual bool IsSheared (void) const {return false; } + virtual int GetFurColor (void) const {return 0; } + virtual bool IsSheared (void) const {return false; } // Enderman virtual BLOCKTYPE CarriedBlock (void) const {return E_BLOCK_AIR; } virtual NIBBLETYPE CarriedMeta (void) const {return 0; } - virtual bool IsScream (void) const {return false; } + virtual bool IsScream (void) const {return false; } // Skeleton || Wither Skeleton - virtual bool IsWither (void) const {return false; } + virtual bool IsWither (void) const {return false; } // Witch - virtual bool IsNosey (void) const {return false; } + virtual bool IsNosey (void) const {return false; } // Slimes and Magma cubes - virtual int GetSize (void) const {return 1; } + virtual int GetSize (void) const {return 1; } + + // Horsheys + virtual bool IsChested (void) const {return false; } + virtual bool IsEating (void) const {return false; } + virtual bool IsRearing (void) const {return false; } + virtual bool IsMthOpen (void) const {return false; } + virtual int GetHType (void) const {return 0; } + virtual int GetHColor (void) const {return 0; } + virtual int GetHStyle (void) const {return 0; } + virtual int GetHArmour (void) const {return 0; } // tolua_end diff --git a/source/Mobs/Horse.cpp b/source/Mobs/Horse.cpp index 50eab33cc..ec6154d26 100644 --- a/source/Mobs/Horse.cpp +++ b/source/Mobs/Horse.cpp @@ -11,7 +11,7 @@ cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : super("Horse", 100, "mob.horse.hit", "mob.horse.death", 1.4, 1.6), - m_bIsChested(false), + m_bHasChest(false), m_bIsEating(false), m_bIsRearing(false), m_bIsMouthOpen(false), diff --git a/source/Mobs/Horse.h b/source/Mobs/Horse.h index d950ff1bf..bca2e5327 100644 --- a/source/Mobs/Horse.h +++ b/source/Mobs/Horse.h @@ -1,7 +1,7 @@ #pragma once -#include "AggressiveMonster.h" +#include "PassiveMonster.h" @@ -20,7 +20,7 @@ public: 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 IsChested (void) const {return m_bIsChested; } + 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; } @@ -32,7 +32,7 @@ public: private: - bool m_bIsChested, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame; + bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame; int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes; } ; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 89b2c15ec..e2309c295 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -1638,11 +1638,11 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) } if (a_Entity.IsRclking()) { - CommonMetadata |= 0x16; + CommonMetadata |= 0x10; } if (a_Entity.IsInvisible()) { - CommonMetadata |= 0x32; + CommonMetadata |= 0x20; } WriteByte(0x0); @@ -1691,7 +1691,7 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) else if (a_Entity.IsA("cZombie")) { WriteByte(0xC); - WriteByte(a_Entity.IsBabby() ? 1 : 0); // Babby zombie? + WriteByte(a_Entity.IsBaby() ? 1 : 0); // Babby zombie? WriteByte(0xD); WriteByte(a_Entity.IsVillZomb() ? 1 : 0); // Converted zombie? WriteByte(0xE); @@ -1784,7 +1784,7 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) { Flags |= 0x8; } - if (a_Entity.IsBabby()) + if (a_Entity.IsBaby()) { Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer } -- cgit v1.2.3 From fe6fa23a97421af3d02b9faf92b8df2f73abb556 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 9 Oct 2013 21:02:59 +0100 Subject: Second round of fixes * Implemented suggestions --- source/Entities/Entity.h | 67 +--------------------------- source/Entities/Minecart.cpp | 4 +- source/Entities/Minecart.h | 2 +- source/Mobs/Bat.h | 2 + source/Mobs/Creeper.cpp | 21 ++++++++- source/Mobs/Creeper.h | 9 ++++ source/Mobs/Enderman.cpp | 5 ++- source/Mobs/Enderman.h | 11 +++++ source/Mobs/Ghast.h | 2 + source/Mobs/Horse.cpp | 1 + source/Mobs/Horse.h | 4 +- source/Mobs/Monster.h | 6 +++ source/Mobs/Witch.h | 2 + source/Mobs/Zombie.cpp | 6 ++- source/Mobs/Zombie.h | 10 ++++- source/Protocol/Protocol125.cpp | 98 ++++++++++++++++++++++++++--------------- source/World.cpp | 2 +- 17 files changed, 140 insertions(+), 112 deletions(-) diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h index fdc047cf9..07bc84937 100644 --- a/source/Entities/Entity.h +++ b/source/Entities/Entity.h @@ -334,78 +334,13 @@ public: // 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 IsCrouched (void) const {return false; } virtual bool IsRiding (void) const {return false; } virtual bool IsSprinting(void) const {return false; } virtual bool IsRclking (void) const {return false; } virtual bool IsInvisible(void) const {return false; } - - // Ageables + Tameables - virtual bool IsBaby (void) const {return false; } - virtual bool IsSitting (void) const {return false; } - virtual bool IsTame (void) const {return false; } - - // Creepers - virtual bool IsCharged (void) const {return false; } - virtual bool IsBlowing (void) const {return false; } - - // Furnace Minecarts & Minecarts - virtual int LastDamage (void) const {return 0; } - virtual bool IsFueled (void) const {return false; } - - // Bat - virtual bool IsHanging (void) const {return false; } - - // Pig - virtual bool IsSaddled (void) const {return false; } - - // TESTIFICATE - virtual int GetVilType (void) const {return 0; } - - // Zombie - virtual bool IsVillZomb (void) const {return false; } - virtual bool IsConvert (void) const {return false; } - - // Ghast - virtual bool IsCharging (void) const {return false; } - - // Arrow - virtual bool IsCritical (void) const {return false; } - - // Wolf - virtual bool IsAngry (void) const {return false; } - virtual bool IsBegging (void) const {return false; } - virtual int GetCollar (void) const {return 0; } - - // Sheep - virtual int GetFurColor (void) const {return 0; } - virtual bool IsSheared (void) const {return false; } - - // Enderman - virtual BLOCKTYPE CarriedBlock (void) const {return E_BLOCK_AIR; } - virtual NIBBLETYPE CarriedMeta (void) const {return 0; } - virtual bool IsScream (void) const {return false; } - - // Skeleton || Wither Skeleton - virtual bool IsWither (void) const {return false; } - - // Witch - virtual bool IsNosey (void) const {return false; } - - // Slimes and Magma cubes - virtual int GetSize (void) const {return 1; } - - // Horsheys - virtual bool IsChested (void) const {return false; } - virtual bool IsEating (void) const {return false; } - virtual bool IsRearing (void) const {return false; } - virtual bool IsMthOpen (void) const {return false; } - virtual int GetHType (void) const {return 0; } - virtual int GetHColor (void) const {return 0; } - virtual int GetHStyle (void) const {return 0; } - virtual int GetHArmour (void) const {return 0; } // tolua_end diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp index 1711e296f..4787f9157 100644 --- a/source/Entities/Minecart.cpp +++ b/source/Entities/Minecart.cpp @@ -374,12 +374,12 @@ void cMinecart::DoTakeDamage(TakeDamageInfo & TDI) } case mpTNT: { - Drops.push_back(cItem(0, 1, 0)); + Drops.push_back(cItem(E_ITEM_MINECART_WITH_TNT, 1, 0)); break; } case mpHopper: { - Drops.push_back(cItem(0, 1, 0)); + Drops.push_back(cItem(E_ITEM_MINECART_WITH_HOPPER, 1, 0)); break; } default: diff --git a/source/Entities/Minecart.h b/source/Entities/Minecart.h index f974ea76a..b1b48be4e 100644 --- a/source/Entities/Minecart.h +++ b/source/Entities/Minecart.h @@ -51,8 +51,8 @@ public: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override; virtual void DoTakeDamage(TakeDamageInfo & TDI) override; - int LastDamage(void) const { return m_LastDamage; } + int LastDamage(void) const { return m_LastDamage; } void HandleRailPhysics(float a_Dt, cChunk & a_Chunk); ePayload GetPayload(void) const { return m_Payload; } diff --git a/source/Mobs/Bat.h b/source/Mobs/Bat.h index 8e4cde29f..7aaec361b 100644 --- a/source/Mobs/Bat.h +++ b/source/Mobs/Bat.h @@ -20,6 +20,8 @@ public: } CLASS_PROTODEF(cBat); + + bool IsHanging(void) const {return false; } } ; diff --git a/source/Mobs/Creeper.cpp b/source/Mobs/Creeper.cpp index 9b1b68b79..b41b05f42 100644 --- a/source/Mobs/Creeper.cpp +++ b/source/Mobs/Creeper.cpp @@ -2,13 +2,16 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Creeper.h" +#include "../World.h" 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); +} + + + + diff --git a/source/Mobs/Creeper.h b/source/Mobs/Creeper.h index c1d46f462..c3d4edeae 100644 --- a/source/Mobs/Creeper.h +++ b/source/Mobs/Creeper.h @@ -18,6 +18,15 @@ public: CLASS_PROTODEF(cCreeper); 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; + } ; diff --git a/source/Mobs/Enderman.cpp b/source/Mobs/Enderman.cpp index 1dc47876f..04c1a60e1 100644 --- a/source/Mobs/Enderman.cpp +++ b/source/Mobs/Enderman.cpp @@ -9,7 +9,10 @@ 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.5) + super("Enderman", 58, "mob.endermen.hit", "mob.endermen.death", 0.5, 2.5), + m_bIsScreaming(false), + CarriedBlock(E_BLOCK_AIR), + CarriedMeta(0) { } diff --git a/source/Mobs/Enderman.h b/source/Mobs/Enderman.h index c4f4ee364..32e40e70b 100644 --- a/source/Mobs/Enderman.h +++ b/source/Mobs/Enderman.h @@ -18,6 +18,17 @@ public: CLASS_PROTODEF(cEnderman); 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; + } ; diff --git a/source/Mobs/Ghast.h b/source/Mobs/Ghast.h index f9b60dfcf..a2adc21b9 100644 --- a/source/Mobs/Ghast.h +++ b/source/Mobs/Ghast.h @@ -18,6 +18,8 @@ public: CLASS_PROTODEF(cGhast); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + + bool IsCharging(void) const {return false; } } ; diff --git a/source/Mobs/Horse.cpp b/source/Mobs/Horse.cpp index ec6154d26..caa1a3deb 100644 --- a/source/Mobs/Horse.cpp +++ b/source/Mobs/Horse.cpp @@ -16,6 +16,7 @@ cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : m_bIsRearing(false), m_bIsMouthOpen(false), m_bIsTame(false), + m_bIsSaddled(false), m_Type(Type), m_Color(Color), m_Style(Style), diff --git a/source/Mobs/Horse.h b/source/Mobs/Horse.h index bca2e5327..bf39c8b13 100644 --- a/source/Mobs/Horse.h +++ b/source/Mobs/Horse.h @@ -20,6 +20,8 @@ public: 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; } @@ -32,7 +34,7 @@ public: private: - bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame; + 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; } ; diff --git a/source/Mobs/Monster.h b/source/Mobs/Monster.h index b2676f5b1..d784f2eec 100644 --- a/source/Mobs/Monster.h +++ b/source/Mobs/Monster.h @@ -113,6 +113,11 @@ public: /// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick 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 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 HandleDaylightBurning(cChunk & a_Chunk); + } ; // tolua_export diff --git a/source/Mobs/Witch.h b/source/Mobs/Witch.h index ce0b49deb..4e637beea 100644 --- a/source/Mobs/Witch.h +++ b/source/Mobs/Witch.h @@ -18,6 +18,8 @@ public: CLASS_PROTODEF(cWitch); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + + bool IsAngry(void) const {return ((m_EMState == ATTACKING) || (m_EMState == CHASING)); } } ; diff --git a/source/Mobs/Zombie.cpp b/source/Mobs/Zombie.cpp index 9b238baef..f495fe5ee 100644 --- a/source/Mobs/Zombie.cpp +++ b/source/Mobs/Zombie.cpp @@ -8,8 +8,10 @@ -cZombie::cZombie(void) : - super("Zombie", 54, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8) +cZombie::cZombie(bool IsVillagerZombie) : + super("Zombie", 54, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8), + m_bIsConverting(false), + m_bIsVillagerZombie(IsVillagerZombie) { SetBurnsInDaylight(true); } diff --git a/source/Mobs/Zombie.h b/source/Mobs/Zombie.h index 4835a53c4..148b1121e 100644 --- a/source/Mobs/Zombie.h +++ b/source/Mobs/Zombie.h @@ -12,11 +12,19 @@ class cZombie : typedef cAggressiveMonster super; public: - cZombie(void); + cZombie(bool IsVillagerZombie); CLASS_PROTODEF(cZombie); 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; + } ; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index e2309c295..0f5f3a616 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -24,8 +24,27 @@ Documentation: #include "../UI/Window.h" #include "../Root.h" #include "../Server.h" + +#include "../Entities/ProjectileEntity.h" +#include "../Entities/Minecart.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" + @@ -1655,70 +1674,70 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) { 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))) * a_Entity.LastDamage()) * 4 ); + WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((cMinecart &)a_Entity).LastDamage()) * 4 ); WriteByte(0x52); WriteInt(1); // Shaking direction, doesn't seem to affect anything WriteByte(0x73); - WriteFloat((float)(a_Entity.LastDamage() + 10)); // Damage taken / shake effect multiplyer + WriteFloat((float)(((cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer } else if (a_Entity.IsA("cCreeper")) { WriteByte(0x10); - WriteByte(a_Entity.IsBlowing() ? 1 : -1); // Blowing up? + WriteByte(((cCreeper &)a_Entity).IsBlowing() ? 1 : -1); // Blowing up? WriteByte(0x11); - WriteByte(a_Entity.IsCharged() ? 1 : 0); // Lightning-charged? + WriteByte(((cCreeper &)a_Entity).IsCharged() ? 1 : 0); // Lightning-charged? } else if (a_Entity.IsA("cMinecartWithFurnace")) { WriteByte(0x10); - WriteByte(a_Entity.IsFueled() ? 1 : 0); // Fueled? + WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled? } else if (a_Entity.IsA("cBat")) { WriteByte(0x10); - WriteByte(a_Entity.IsHanging() ? 1 : 0); // Upside down? + WriteByte(((const cBat &)a_Entity).IsHanging() ? 1 : 0); // Upside down? } else if (a_Entity.IsA("cPig")) { WriteByte(0x10); - WriteByte(a_Entity.IsSaddled() ? 1 : 0); // Saddled? + WriteByte(((const cPig &)a_Entity).IsSaddled() ? 1 : 0); // Saddled? } else if (a_Entity.IsA("cVillager")) { WriteByte(0x50); - WriteInt(a_Entity.GetVilType()); // What sort of TESTIFICATE? + WriteInt(((const cVillager &)a_Entity).GetVilType()); // What sort of TESTIFICATE? } else if (a_Entity.IsA("cZombie")) { WriteByte(0xC); - WriteByte(a_Entity.IsBaby() ? 1 : 0); // Babby zombie? + WriteByte(((const cZombie &)a_Entity).IsBaby() ? 1 : 0); // Babby zombie? WriteByte(0xD); - WriteByte(a_Entity.IsVillZomb() ? 1 : 0); // Converted zombie? + WriteByte(((const cZombie &)a_Entity).IsVillagerZombie() ? 1 : 0); // Converted zombie? WriteByte(0xE); - WriteByte(a_Entity.IsConvert() ? 1 : 0); // Converted-but-converting-back zombllager? + WriteByte(((const cZombie &)a_Entity).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? } else if (a_Entity.IsA("cGhast")) { WriteByte(0x10); - WriteByte(a_Entity.IsCharging()); // About to eject un flamé-bol? :P + WriteByte(((const cGhast &)a_Entity).IsCharging()); // About to eject un flamé-bol? :P } else if (a_Entity.IsA("cArrowEntity")) { WriteByte(0x10); - WriteByte(a_Entity.IsCritical() ? 1 : 0); // Critical hitting arrow? + WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow? } else if (a_Entity.IsA("cWolf")) { Byte WolfStatus = 0; - if (a_Entity.IsSitting()) + if (((const cWolf &)a_Entity).IsSitting()) { WolfStatus |= 0x1; } - if (a_Entity.IsAngry()) + if (((const cWolf &)a_Entity).IsAngry()) { WolfStatus |= 0x2; } - if (a_Entity.IsTame()) + if (((const cWolf &)a_Entity).IsTame()) { WolfStatus |= 0x4; } @@ -1728,7 +1747,7 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) WriteByte(0x72); WriteFloat((float)(a_Entity.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way) WriteByte(0x13); - WriteByte(a_Entity.IsBegging() ? 1 : 0); // Ultra cute mode? + WriteByte(((const cWolf &)a_Entity).IsBegging() ? 1 : 0); // Ultra cute mode? } else if (a_Entity.IsA("cSheep")) { @@ -1737,9 +1756,9 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) WriteByte(0x10); Byte SheepMetadata = 0; - SheepMetadata = a_Entity.GetFurColor(); // Fur colour + SheepMetadata = ((const cSheep &)a_Entity).GetFurColor(); // Fur colour - if (a_Entity.IsSheared()) // Is sheared? + if (((const cSheep &)a_Entity).IsSheared()) // Is sheared? { SheepMetadata |= 0x16; } @@ -1748,55 +1767,62 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) else if (a_Entity.IsA("cEnderman")) { WriteByte(0x10); - WriteByte(a_Entity.CarriedBlock()); // Stolen block + WriteByte((Byte)(((cEnderman &)a_Entity).GetCarriedBlock())); // Block that he stole from your house WriteByte(0x11); - WriteByte(a_Entity.CarriedMeta()); // Stolen metea + WriteByte((Byte)(((cEnderman &)a_Entity).GetCarriedMeta())); // Meta of block that he stole from your house WriteByte(0x12); - WriteByte(a_Entity.IsScream() ? 1 : 0); // I HATE YER FACE, I SCWEAM AT YER FACE + WriteByte(((cEnderman &)a_Entity).IsScreaming() ? 1 : 0); // Screaming at your face? } else if (a_Entity.IsA("cSkeleton")) { WriteByte(0xD); - WriteByte(a_Entity.IsWither() ? 1 : 0); // It's a skeleton, but it's not + WriteByte(((const cSkeleton &)a_Entity).IsWither() ? 1 : 0); // It's a skeleton, but it's not } else if (a_Entity.IsA("cWitch")) { WriteByte(0x15); - WriteByte(a_Entity.IsNosey() ? 1 : 0); // Drinking-nose: like Squidward + WriteByte(((cWitch &)a_Entity).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything } else if ((a_Entity.IsA("cSlime")) || (a_Entity.IsA("cMagmaCube"))) { WriteByte(0x10); - WriteByte(a_Entity.GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + if (a_Entity.IsA("cSlime")) + { + WriteByte(((const cSlime &)a_Entity).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + } + else + { + WriteByte(((const cMagmaCube &)a_Entity).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + } } else if (a_Entity.IsA("cHorse")) { int Flags = 0; - if (a_Entity.IsTame()) + if (((const cHorse &)a_Entity).IsTame()) { Flags |= 0x2; } - if (a_Entity.IsSaddled()) + if (((const cHorse &)a_Entity).IsSaddled()) { Flags |= 0x4; } - if (a_Entity.IsChested()) + if (((const cHorse &)a_Entity).IsChested()) { Flags |= 0x8; } - if (a_Entity.IsBaby()) + if (((const cHorse &)a_Entity).IsBaby()) { Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer } - if (a_Entity.IsEating()) + if (((const cHorse &)a_Entity).IsEating()) { Flags |= 0x20; } - if (a_Entity.IsRearing()) + if (((const cHorse &)a_Entity).IsRearing()) { Flags |= 0x40; } - if (a_Entity.IsMthOpen()) + if (((const cHorse &)a_Entity).IsMthOpen()) { Flags |= 0x80; } @@ -1804,16 +1830,16 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) WriteInt(Flags); WriteByte(0x13); - WriteByte(a_Entity.GetHType()); // Type of horse (donkey, chestnut, etc.) + WriteByte(((const cHorse &)a_Entity).GetHType()); // Type of horse (donkey, chestnut, etc.) WriteByte(0x54); int Appearance = 0; - Appearance = a_Entity.GetHColor(); // Mask FF - Appearance |= a_Entity.GetHStyle() * 256; // Mask FF00, so multiply by 256 + Appearance = ((const cHorse &)a_Entity).GetHColor(); // Mask FF + Appearance |= ((const cHorse &)a_Entity).GetHStyle() * 256; // Mask FF00, so multiply by 256 WriteInt(Appearance); WriteByte(0x56); - WriteInt(a_Entity.GetHArmour()); // Horshey armour + WriteInt(((const cHorse &)a_Entity).GetHArmour()); // Horshey armour } // End Specific Metadata diff --git a/source/World.cpp b/source/World.cpp index 784df49f3..6346a7cb8 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -2616,7 +2616,7 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp case cMonster::mtWitch: Monster = new cWitch(); break; case cMonster::mtWither: Monster = new cWither(); 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; default: -- cgit v1.2.3 From d7b2c534fd2e272c328b176432c922fd11a7cd85 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 11 Oct 2013 00:41:54 +0100 Subject: Third round of fixes * Split WriteMetadata into three functions for common, entity, and mob * Edited a few mob sizes to Vanilla values --- source/Mobs/Bat.h | 3 +- source/Mobs/Cavespider.cpp | 3 +- source/Mobs/Enderman.cpp | 3 +- source/Mobs/Ocelot.h | 3 +- source/Mobs/Silverfish.h | 3 +- source/Protocol/Protocol125.cpp | 157 ++++++++++++++++++++++------------------ source/Protocol/Protocol125.h | 10 ++- source/Protocol/Protocol132.cpp | 6 +- 8 files changed, 106 insertions(+), 82 deletions(-) diff --git a/source/Mobs/Bat.h b/source/Mobs/Bat.h index 7aaec361b..0b50e06cd 100644 --- a/source/Mobs/Bat.h +++ b/source/Mobs/Bat.h @@ -14,8 +14,7 @@ class cBat : public: 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.7, 0.7) + super("Bat", 65, "mob.bat.hurt", "mob.bat.death", 0.5, 0.9) { } diff --git a/source/Mobs/Cavespider.cpp b/source/Mobs/Cavespider.cpp index 569aadcc4..2d50b391a 100644 --- a/source/Mobs/Cavespider.cpp +++ b/source/Mobs/Cavespider.cpp @@ -9,8 +9,7 @@ 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.9, 0.6) + super("Cavespider", 59, "mob.spider.say", "mob.spider.death", 0.7, 0.5) { } diff --git a/source/Mobs/Enderman.cpp b/source/Mobs/Enderman.cpp index 04c1a60e1..c0ea3d6aa 100644 --- a/source/Mobs/Enderman.cpp +++ b/source/Mobs/Enderman.cpp @@ -8,8 +8,7 @@ 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.5), + super("Enderman", 58, "mob.endermen.hit", "mob.endermen.death", 0.5, 2.9), m_bIsScreaming(false), CarriedBlock(E_BLOCK_AIR), CarriedMeta(0) diff --git a/source/Mobs/Ocelot.h b/source/Mobs/Ocelot.h index 98ea224e2..6d24c5672 100644 --- a/source/Mobs/Ocelot.h +++ b/source/Mobs/Ocelot.h @@ -14,8 +14,7 @@ class cOcelot : public: 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.9, 0.5) + super("Ocelot", 98, "mob.cat.hitt", "mob.cat.hitt", 0.6, 0.8) { } diff --git a/source/Mobs/Silverfish.h b/source/Mobs/Silverfish.h index 7d675a9c0..d632ac169 100644 --- a/source/Mobs/Silverfish.h +++ b/source/Mobs/Silverfish.h @@ -14,8 +14,7 @@ class cSilverfish : public: 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.9, 0.3) + super("Silverfish", 60, "mob.silverfish.hit", "mob.silverfish.kill", 0.3, 0.7) { } diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 0f5f3a616..96a4e57ff 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -363,7 +363,16 @@ void cProtocol125::SendEntityMetadata(const cEntity & a_Entity) WriteByte(PACKET_METADATA); WriteInt (a_Entity.GetUniqueID()); - WriteMetadata(a_Entity); + WriteCommonMetadata(a_Entity); + if (a_Entity.IsMob()) + { + WriteMobMetadata(((const cMonster &)a_Entity)); + } + else + { + WriteEntityMetadata(a_Entity); + } + WriteByte(0x7f); Flush(); } @@ -730,7 +739,11 @@ void cProtocol125::SendSpawnMob(const cMonster & a_Mob) WriteByte (0); WriteByte (0); WriteByte (0); - WriteMetadata(a_Mob); + + WriteCommonMetadata(a_Mob); + WriteMobMetadata(a_Mob); + WriteByte(0x7f); + Flush(); } @@ -1633,10 +1646,8 @@ int cProtocol125::ParseItem(cItem & a_Item) -void cProtocol125::WriteMetadata(const cEntity & a_Entity) +void cProtocol125::WriteCommonMetadata(const cEntity & a_Entity) { - // Common Metadata - Byte CommonMetadata = 0; if (a_Entity.IsOnFire()) @@ -1666,78 +1677,91 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) WriteByte(0x0); WriteByte(CommonMetadata); +} + + - // Common Metadata End - // Specific Entity Metadata + +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))) * ((cMinecart &)a_Entity).LastDamage()) * 4 ); + 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)(((cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer + WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer + + if (a_Entity.IsA("cMinecartWithFurnace")) + { + WriteByte(0x10); + WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled? + } } - else if (a_Entity.IsA("cCreeper")) +} + + + + + +void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) +{ + if (a_Mob.GetMobType() == E_META_SPAWN_EGG_CREEPER) { WriteByte(0x10); - WriteByte(((cCreeper &)a_Entity).IsBlowing() ? 1 : -1); // Blowing up? + WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up? WriteByte(0x11); - WriteByte(((cCreeper &)a_Entity).IsCharged() ? 1 : 0); // Lightning-charged? - } - else if (a_Entity.IsA("cMinecartWithFurnace")) - { - WriteByte(0x10); - WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled? + WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged? } - else if (a_Entity.IsA("cBat")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_BAT) { WriteByte(0x10); - WriteByte(((const cBat &)a_Entity).IsHanging() ? 1 : 0); // Upside down? + WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? } - else if (a_Entity.IsA("cPig")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_PIG) { WriteByte(0x10); - WriteByte(((const cPig &)a_Entity).IsSaddled() ? 1 : 0); // Saddled? + WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? } - else if (a_Entity.IsA("cVillager")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_VILLAGER) { WriteByte(0x50); - WriteInt(((const cVillager &)a_Entity).GetVilType()); // What sort of TESTIFICATE? + WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? } - else if (a_Entity.IsA("cZombie")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_ZOMBIE) { WriteByte(0xC); - WriteByte(((const cZombie &)a_Entity).IsBaby() ? 1 : 0); // Babby zombie? + WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie? WriteByte(0xD); - WriteByte(((const cZombie &)a_Entity).IsVillagerZombie() ? 1 : 0); // Converted zombie? + WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie? WriteByte(0xE); - WriteByte(((const cZombie &)a_Entity).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? + WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? } - else if (a_Entity.IsA("cGhast")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_GHAST) { WriteByte(0x10); - WriteByte(((const cGhast &)a_Entity).IsCharging()); // About to eject un flamé-bol? :P + WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P } - else if (a_Entity.IsA("cArrowEntity")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_ARROW) { WriteByte(0x10); - WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow? + WriteByte(((const cArrowEntity &)a_Mob).IsCritical() ? 1 : 0); // Critical hitting arrow? } - else if (a_Entity.IsA("cWolf")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_WOLF) { Byte WolfStatus = 0; - if (((const cWolf &)a_Entity).IsSitting()) + if (((const cWolf &)a_Mob).IsSitting()) { WolfStatus |= 0x1; } - if (((const cWolf &)a_Entity).IsAngry()) + if (((const cWolf &)a_Mob).IsAngry()) { WolfStatus |= 0x2; } - if (((const cWolf &)a_Entity).IsTame()) + if (((const cWolf &)a_Mob).IsTame()) { WolfStatus |= 0x4; } @@ -1745,84 +1769,84 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) WriteByte(WolfStatus); WriteByte(0x72); - WriteFloat((float)(a_Entity.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way) + WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way) WriteByte(0x13); - WriteByte(((const cWolf &)a_Entity).IsBegging() ? 1 : 0); // Ultra cute mode? + WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode? } - else if (a_Entity.IsA("cSheep")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SHEEP) { // [1](1111) // [] = Is sheared? () = Color, from 0 to 15 WriteByte(0x10); Byte SheepMetadata = 0; - SheepMetadata = ((const cSheep &)a_Entity).GetFurColor(); // Fur colour + SheepMetadata = ((const cSheep &)a_Mob).GetFurColor(); // Fur colour - if (((const cSheep &)a_Entity).IsSheared()) // Is sheared? + if (((const cSheep &)a_Mob).IsSheared()) // Is sheared? { SheepMetadata |= 0x16; } WriteByte(SheepMetadata); } - else if (a_Entity.IsA("cEnderman")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_ENDERMAN) { WriteByte(0x10); - WriteByte((Byte)(((cEnderman &)a_Entity).GetCarriedBlock())); // Block that he stole from your house + WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house WriteByte(0x11); - WriteByte((Byte)(((cEnderman &)a_Entity).GetCarriedMeta())); // Meta of block that he stole from your house + WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house WriteByte(0x12); - WriteByte(((cEnderman &)a_Entity).IsScreaming() ? 1 : 0); // Screaming at your face? + WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face? } - else if (a_Entity.IsA("cSkeleton")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SKELETON) { WriteByte(0xD); - WriteByte(((const cSkeleton &)a_Entity).IsWither() ? 1 : 0); // It's a skeleton, but it's not + WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not } - else if (a_Entity.IsA("cWitch")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_WITCH) { WriteByte(0x15); - WriteByte(((cWitch &)a_Entity).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything + WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything } - else if ((a_Entity.IsA("cSlime")) || (a_Entity.IsA("cMagmaCube"))) + else if ((a_Mob.GetMobType() == E_META_SPAWN_EGG_SLIME) || (a_Mob.GetMobType() == E_META_SPAWN_EGG_MAGMA_CUBE)) { WriteByte(0x10); - if (a_Entity.IsA("cSlime")) + if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SLIME) { - WriteByte(((const cSlime &)a_Entity).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + WriteByte(((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME } else { - WriteByte(((const cMagmaCube &)a_Entity).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + WriteByte(((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME } } - else if (a_Entity.IsA("cHorse")) + else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_HORSE) { int Flags = 0; - if (((const cHorse &)a_Entity).IsTame()) + if (((const cHorse &)a_Mob).IsTame()) { Flags |= 0x2; } - if (((const cHorse &)a_Entity).IsSaddled()) + if (((const cHorse &)a_Mob).IsSaddled()) { Flags |= 0x4; } - if (((const cHorse &)a_Entity).IsChested()) + if (((const cHorse &)a_Mob).IsChested()) { Flags |= 0x8; } - if (((const cHorse &)a_Entity).IsBaby()) + 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_Entity).IsEating()) + if (((const cHorse &)a_Mob).IsEating()) { Flags |= 0x20; } - if (((const cHorse &)a_Entity).IsRearing()) + if (((const cHorse &)a_Mob).IsRearing()) { Flags |= 0x40; } - if (((const cHorse &)a_Entity).IsMthOpen()) + if (((const cHorse &)a_Mob).IsMthOpen()) { Flags |= 0x80; } @@ -1830,22 +1854,17 @@ void cProtocol125::WriteMetadata(const cEntity & a_Entity) WriteInt(Flags); WriteByte(0x13); - WriteByte(((const cHorse &)a_Entity).GetHType()); // Type of horse (donkey, chestnut, etc.) + WriteByte(((const cHorse &)a_Mob).GetHType()); // Type of horse (donkey, chestnut, etc.) WriteByte(0x54); int Appearance = 0; - Appearance = ((const cHorse &)a_Entity).GetHColor(); // Mask FF - Appearance |= ((const cHorse &)a_Entity).GetHStyle() * 256; // Mask FF00, so multiply by 256 + Appearance = ((const cHorse &)a_Mob).GetHColor(); // Mask FF + Appearance |= ((const cHorse &)a_Mob).GetHStyle() * 256; // Mask FF00, so multiply by 256 WriteInt(Appearance); WriteByte(0x56); - WriteInt(((const cHorse &)a_Entity).GetHArmour()); // Horshey armour + WriteInt(((const cHorse &)a_Mob).GetHArmour()); // Horshey armour } - - // End Specific Metadata - // End Metadata Packet - - WriteByte(0x7f); } diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h index 7b493881b..ae198780c 100644 --- a/source/Protocol/Protocol125.h +++ b/source/Protocol/Protocol125.h @@ -142,8 +142,14 @@ protected: /// Parses one item, "slot" as the protocol wiki calls it, from m_ReceivedData; returns the usual ParsePacket() codes virtual int ParseItem(cItem & a_Item); - /// Writes the entity metadata - void WriteMetadata(const cEntity & a_Entity); + /// Writes the COMMON entity metadata + void WriteCommonMetadata(const cEntity & a_Entity); + + /// Writes normal entity metadata + void WriteEntityMetadata(const cEntity & a_Entity); + + /// Writes mobile entity metadata + void WriteMobMetadata(const cMonster & a_Mob); } ; diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp index 63b838b70..53159a3b3 100644 --- a/source/Protocol/Protocol132.cpp +++ b/source/Protocol/Protocol132.cpp @@ -416,7 +416,11 @@ void cProtocol132::SendSpawnMob(const cMonster & a_Mob) WriteShort ((short)(a_Mob.GetSpeedX() * 400)); WriteShort ((short)(a_Mob.GetSpeedY() * 400)); WriteShort ((short)(a_Mob.GetSpeedZ() * 400)); - WriteMetadata(a_Mob); + + WriteCommonMetadata(a_Mob); + WriteMobMetadata(a_Mob); + WriteByte(0x7f); + Flush(); } -- cgit v1.2.3 From ee2df34d03313ecf98110384559f46f00a05978b Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 11 Oct 2013 01:00:16 +0100 Subject: Fourth round of fixes * Switchified WriteMobMetadata * Renamed Horse functions to be better --- source/Mobs/Horse.h | 20 +-- source/Protocol/Protocol125.cpp | 268 +++++++++++++++++++++------------------- 2 files changed, 153 insertions(+), 135 deletions(-) diff --git a/source/Mobs/Horse.h b/source/Mobs/Horse.h index bf39c8b13..d80678845 100644 --- a/source/Mobs/Horse.h +++ b/source/Mobs/Horse.h @@ -21,16 +21,16 @@ public: 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 GetHType (void) const {return m_Type; } - int GetHColor (void) const {return m_Color; } - int GetHStyle (void) const {return m_Style; } - int GetHArmour (void) const {return m_Armour;} + 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: diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 96a4e57ff..6d6101fb2 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -1709,161 +1709,179 @@ void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity) void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) { - if (a_Mob.GetMobType() == E_META_SPAWN_EGG_CREEPER) + switch (a_Mob.GetMobType()) { - WriteByte(0x10); - WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up? - WriteByte(0x11); - WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_BAT) - { - WriteByte(0x10); - WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_PIG) - { - WriteByte(0x10); - WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_VILLAGER) - { - WriteByte(0x50); - WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_ZOMBIE) - { - 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? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_GHAST) - { - WriteByte(0x10); - WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_ARROW) - { - WriteByte(0x10); - WriteByte(((const cArrowEntity &)a_Mob).IsCritical() ? 1 : 0); // Critical hitting arrow? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_WOLF) - { - Byte WolfStatus = 0; - if (((const cWolf &)a_Mob).IsSitting()) + case E_META_SPAWN_EGG_CREEPER: { - WolfStatus |= 0x1; + 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; } - if (((const cWolf &)a_Mob).IsAngry()) + case E_META_SPAWN_EGG_BAT: { - WolfStatus |= 0x2; + WriteByte(0x10); + WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? + break; } - if (((const cWolf &)a_Mob).IsTame()) + case E_META_SPAWN_EGG_PIG: { - WolfStatus |= 0x4; + WriteByte(0x10); + WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? + break; } - 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? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SHEEP) - { - // [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? + case E_META_SPAWN_EGG_VILLAGER: { - SheepMetadata |= 0x16; + WriteByte(0x50); + WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? + break; } - WriteByte(SheepMetadata); - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_ENDERMAN) - { - 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? - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SKELETON) - { - WriteByte(0xD); - WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_WITCH) - { - WriteByte(0x15); - WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything - } - else if ((a_Mob.GetMobType() == E_META_SPAWN_EGG_SLIME) || (a_Mob.GetMobType() == E_META_SPAWN_EGG_MAGMA_CUBE)) - { - WriteByte(0x10); - if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SLIME) + case E_META_SPAWN_EGG_ZOMBIE: { - WriteByte(((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + 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; } - else + case E_META_SPAWN_EGG_GHAST: { - WriteByte(((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME + WriteByte(0x10); + WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P + break; } - } - else if (a_Mob.GetMobType() == E_META_SPAWN_EGG_HORSE) - { - int Flags = 0; - if (((const cHorse &)a_Mob).IsTame()) + case E_META_SPAWN_EGG_ARROW: { - Flags |= 0x2; + WriteByte(0x10); + WriteByte(((const cArrowEntity &)a_Mob).IsCritical() ? 1 : 0); // Critical hitting arrow? + break; } - if (((const cHorse &)a_Mob).IsSaddled()) + case E_META_SPAWN_EGG_WOLF: { - Flags |= 0x4; + 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; } - if (((const cHorse &)a_Mob).IsChested()) + case E_META_SPAWN_EGG_SHEEP: { - Flags |= 0x8; + // [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; } - if (((const cHorse &)a_Mob).IsBaby()) + case E_META_SPAWN_EGG_ENDERMAN: { - Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer + 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; } - if (((const cHorse &)a_Mob).IsEating()) + case E_META_SPAWN_EGG_SKELETON: { - Flags |= 0x20; + WriteByte(0xD); + WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not + break; } - if (((const cHorse &)a_Mob).IsRearing()) + case E_META_SPAWN_EGG_WITCH: { - Flags |= 0x40; + WriteByte(0x15); + WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything + break; } - if (((const cHorse &)a_Mob).IsMthOpen()) + case E_META_SPAWN_EGG_SLIME: + case E_META_SPAWN_EGG_MAGMA_CUBE: { - Flags |= 0x80; + WriteByte(0x10); + if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SLIME) + { + 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; } - WriteByte(0x50); - WriteInt(Flags); + case E_META_SPAWN_EGG_HORSE: + { + 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).GetHType()); // Type of horse (donkey, chestnut, etc.) + WriteByte(0x13); + WriteByte(((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.) - WriteByte(0x54); - int Appearance = 0; - Appearance = ((const cHorse &)a_Mob).GetHColor(); // Mask FF - Appearance |= ((const cHorse &)a_Mob).GetHStyle() * 256; // Mask FF00, so multiply by 256 - WriteInt(Appearance); + 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).GetHArmour()); // Horshey armour + WriteByte(0x56); + WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour + break; + } } } -- cgit v1.2.3 From e2aaf202abf9d677b84efeb376f55ee976b52b8d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 11 Oct 2013 20:57:22 +0100 Subject: Fifth round of fixes * Enumerated Villager spawning --- source/Mobs/Villager.cpp | 4 ++-- source/Mobs/Villager.h | 15 +++++++++++++-- source/World.cpp | 10 +++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/source/Mobs/Villager.cpp b/source/Mobs/Villager.cpp index cb50d8cfc..97d6dc3ca 100644 --- a/source/Mobs/Villager.cpp +++ b/source/Mobs/Villager.cpp @@ -8,9 +8,9 @@ -cVillager::cVillager(int Type) : +cVillager::cVillager(eVillagerType VillagerType) : super("Villager", 120, "", "", 0.6, 1.8), - m_Type(Type) + m_Type(VillagerType) { } diff --git a/source/Mobs/Villager.h b/source/Mobs/Villager.h index 5fcb519dd..86888d9eb 100644 --- a/source/Mobs/Villager.h +++ b/source/Mobs/Villager.h @@ -13,12 +13,23 @@ class cVillager : typedef cPassiveMonster super; public: - cVillager(int Type); + + enum eVillagerType + { + VILLAGER_TYPE_FARMER = 0, + VILLAGER_TYPE_LIBRARIAN = 1, + VILLAGER_TYPE_PRIEST = 2, + VILLAGER_TYPE_BLACKSMITH = 3, + VILLAGER_TYPE_BUTCHER = 4, + VILLAGER_TYPE_GENERIC = 5 + } ; + + cVillager(eVillagerType VillagerType); CLASS_PROTODEF(cVillager); virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; - int GetVilType(void) const { return m_Type; } + int GetVilType(void) const { return m_Type; } private: diff --git a/source/World.cpp b/source/World.cpp index 6346a7cb8..da9466bf8 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -2575,13 +2575,14 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp int SlSize = GetTickRandomNumber(2) + 1; // 1 .. 3 - Slime int ShColor = GetTickRandomNumber(15); // 0 .. 15 - Sheep bool SkType = GetDimension() == biNether; // Skeleton - int VilType = GetTickRandomNumber(5); // 0 .. 5 - Villager + + int VilType = GetTickRandomNumber(6); // 0 .. 5 - 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) @@ -2612,7 +2613,10 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp case cMonster::mtSnowGolem: Monster = new cSnowGolem(); break; case cMonster::mtSpider: Monster = new cSpider(); break; case cMonster::mtSquid: Monster = new cSquid(); break; - case cMonster::mtVillager: Monster = new cVillager(VilType); break; + case cMonster::mtVillager: + { + Monster = new cVillager((cVillager::eVillagerType)VilType); break; + } case cMonster::mtWitch: Monster = new cWitch(); break; case cMonster::mtWither: Monster = new cWither(); break; case cMonster::mtWolf: Monster = new cWolf(); break; -- cgit v1.2.3 From 327abdd10daad7bb49fde185f1f5aee60a98ec1c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 11 Oct 2013 21:33:56 +0100 Subject: Sixth round of fixes * Made horse rearing time fixed instead of random --- source/Mobs/Horse.cpp | 11 ++++++++--- source/Mobs/Horse.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/source/Mobs/Horse.cpp b/source/Mobs/Horse.cpp index caa1a3deb..46e7969cc 100644 --- a/source/Mobs/Horse.cpp +++ b/source/Mobs/Horse.cpp @@ -22,7 +22,8 @@ cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : m_Style(Style), m_Armour(0), m_TimesToTame(TameTimes), - m_TameAttemptTimes(0) + m_TameAttemptTimes(0), + m_RearTickCount(0) { } @@ -70,9 +71,13 @@ void cHorse::Tick(float a_Dt, cChunk & a_Chunk) } } - if ((m_bIsRearing) && (m_World->GetTickRandomNumber(15) == 6)) + if (m_bIsRearing) { - m_bIsRearing = false; + if (m_RearTickCount == 20) + { + m_bIsRearing = false; + } + else { m_RearTickCount++;} } m_World->BroadcastEntityMetadata(*this); diff --git a/source/Mobs/Horse.h b/source/Mobs/Horse.h index d80678845..be0c23f9b 100644 --- a/source/Mobs/Horse.h +++ b/source/Mobs/Horse.h @@ -35,7 +35,7 @@ public: 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; + int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount; } ; -- cgit v1.2.3 From 058faa74d2ff0a1332bf153c75922289b625a2de Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 12 Oct 2013 23:13:09 +0200 Subject: APIDump: Documented the webserver vs world threads. This fixes #12. --- MCServer/Plugins/APIDump/WebWorldThreads.html | 60 ++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/MCServer/Plugins/APIDump/WebWorldThreads.html b/MCServer/Plugins/APIDump/WebWorldThreads.html index 1a593ad8d..a77209b0b 100644 --- a/MCServer/Plugins/APIDump/WebWorldThreads.html +++ b/MCServer/Plugins/APIDump/WebWorldThreads.html @@ -1,8 +1,64 @@ -Webserver vs World threads +MCServer - Webserver vs World threads + + -This is a temporary test + +

Webserver vs World threads

+

+This article will explain the threading issues that arise between the webserver and world threads are of concern to plugin authors.

+

+Generally, plugins that provide webadmin pages should be quite careful about their interactions. Most operations on MCServer objects requires synchronization, that MCServer provides automatically and transparently to plugins - when a block is written, the chunkmap is locked, or when an entity is being manipulated, the entity list is locked. Each plugin also has a mutex lock, so that only one thread at a time may be executing plugin code.

+

+This locking can be a source of deadlocks for plugins that are not written carefully.

+ +

Example scenario

+

Consider the following example. A plugin provides a webadmin page that allows the admin to kick players off the server. When the admin presses the "Kick" button, the plugin calls cWorld:DoWithPlayer() with a callback to kick the player. Everything seems to be working fine now.

+

+A new feature is developed in the plugin, now the plugin adds a new in-game command so that the admins can kick players while they're playing the game. The plugin registers a command callback with cPluginManager.AddCommand(). Now there are problems bound to happen.

+

+Suppose that two admins are in, one is using the webadmin and the other is in-game. Both try to kick a player at the same time. The webadmin locks the plugin, so that it can execute the plugin code, but right at this moment the OS switches threads. The world thread locks the world so that it can access the list of in-game commands, receives the in-game command, it tries to lock the plugin. The plugin is already locked, so the world thread is put on hold. After a while, the webadmin thread is woken up again and continues processing. It tries to lock the world so that it can traverse the playerlist, but the lock is already held by the world thread. Now both threads are holding one lock each and trying to grab the other lock, and are therefore deadlocked.

+ +

How to avoid the deadlock

+

+There are two main ways to avoid such a deadlock. The first approach is using tasks: Everytime you need to execute a task inside a world, instead of executing it, queue it, using cWorld:QueueTask(). This handy utility can will call the given function inside the world's TickThread, thus eliminating the deadlock, because now there's only one thread. However, this approach will not let you get data back. You cannot query the player list, or the entities, or anything - because when the task runs, the webadmin page has already been served to the browser.

+

+To accommodate this, you'll need to use the second approach - preparing and caching data in the tick thread, possibly using callbacks. This means that the plugin will have global variables that will store the data, and update those variables when the data changes; then the webserver thread will only read those variables, instead of calling the world functions. For example, if a webpage was to display the list of currently connected players, the plugin should maintain a global variable, g_WorldPlayers, which would be a table of worlds, each item being a list of currently connected players. The webadmin handler would read this variable and create the page from it; the plugin would use HOOK_PLAYER_JOINED and HOOK_DISCONNECT to update the variable.

+ +

What to avoid

+

+Now that we know what the danger is and how to avoid it, how do we know if our code is susceptible?

+

+The general rule of thumb is to avoid calling any functions that read or write lists of things in the webserver thread. This means most ForEach() and DoWith() functions. Only cRoot:ForEachWorld() is safe - because the list of worlds is not expected to change, so it is not guarded by a mutex. Getting and setting world's blocks is, naturally, unsafe, as is calling other plugins, or creating entities.

+ +

Example

+The Core has the facility to kick players using the web interface. It used the following code for the kicking (inside the webadmin handler): +
+local KickPlayerName = Request.Params["players-kick"]
+local FoundPlayerCallback = function(Player)
+  if (Player:GetName() == KickPlayerName) then
+    Player:GetClientHandle():Kick("You were kicked from the game!")
+  end
+end
+cRoot:Get():FindAndDoWithPlayer(KickPlayerName, FoundPlayerCallback)
+
+The cRoot:FindAndDoWithPlayer() is unsafe and could have caused a deadlock. The new solution is queue a task; but since we don't know in which world the player is, we need to queue the task to all worlds: +
+cRoot:Get():ForEachWorld(    -- For each world...
+  function(World)
+    World:QueueTask(         -- ... queue a task...
+      function(a_World)
+        a_World:DoWithPlayer(KickPlayerName,  -- ... to walk the playerlist...
+          function (a_Player)
+            a_Player:GetClientHandle():Kick("You were kicked from the game!")  -- ... and kick the player
+          end
+        )
+      end
+    )
+  end
+)
+
\ No newline at end of file -- cgit v1.2.3 From 33e1ba42406395321dbb377b7f15d8a564366b23 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 12 Oct 2013 23:49:55 +0200 Subject: Added 1.7 biome constants. --- source/BlockID.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ source/ChunkDef.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/source/BlockID.cpp b/source/BlockID.cpp index 0c1cb3265..7c3fa0b8e 100644 --- a/source/BlockID.cpp +++ b/source/BlockID.cpp @@ -307,6 +307,48 @@ EMCSBiome StringToBiome(const AString & a_BiomeString) {biExtremeHillsEdge, "ExtremeHillsEdge"}, {biJungle, "Jungle"}, {biJungleHills, "JungleHills"}, + + // Release 1.7 biomes: + {biJungleEdge, "JungleEdge"}, + {biDeepOcean, "DeepOcean"}, + {biStoneBeach, "StoneBeach"}, + {biColdBeach, "ColdBeach"}, + {biBirchForest, "BirchForest"}, + {biBirchForestHills, "BirchForestHills"}, + {biRoofedForest, "RoofedForest"}, + {biColdTaiga, "ColdTaiga"}, + {biColdTaigaHills, "ColdTaigaHills"}, + {biMegaTaiga, "MegaTaiga"}, + {biMegaTaigaHills, "MegaTaigaHills"}, + {biExtremeHillsPlus, "ExtremeHillsPlus"}, + {biSavanna, "Savanna"}, + {biSavannaPlateau, "SavannaPlateau"}, + {biMesa, "Mesa"}, + {biMesaPlateauF, "MesaPlateauF"}, + {biMesaPlateau, "MesaPlateau"}, + + // Release 1.7 variants: + {biSunflowerPlains, "SunflowerPlains"}, + {biDesertM, "DesertM"}, + {biExtremeHillsM, "ExtremeHillsM"}, + {biFlowerForest, "FlowerForest"}, + {biTaigaM, "TaigaM"}, + {biSwamplandM, "SwamplandM"}, + {biIcePlainsSpikes, "IcePlainsSpikes"}, + {biJungleM, "JungleM"}, + {biJungleEdgeM, "JungleEdgeM"}, + {biBirchForestM, "BirchForestM"}, + {biBirchForestHillsM, "BirchForestHillsM"}, + {biRoofedForestM, "RoofedForestM"}, + {biColdTaigaM, "ColdTaigaM"}, + {biMegaSpruceTaiga, "MegaSpruceTaiga"}, + {biMegaSpruceTaigaHills, "MegaSpruceTaigaHills"}, + {biExtremeHillsPlusM, "ExtremeHillsPlusM"}, + {biSavannaM, "SavannaM"}, + {biSavannaPlateauM, "SavannaPlateauM"}, + {biMesaBryce, "MesaBryce"}, + {biMesaPlateauFM, "MesaPlateauFM"}, + {biMesaPlateauM, "MesaPlateauM"}, } ; for (int i = 0; i < ARRAYCOUNT(BiomeMap); i++) diff --git a/source/ChunkDef.h b/source/ChunkDef.h index 4cc2d15b0..9db88f293 100644 --- a/source/ChunkDef.h +++ b/source/ChunkDef.h @@ -93,9 +93,54 @@ enum EMCSBiome biJungle = 21, biJungleHills = 22, - // Automatically capture the maximum biome value into biMaxBiome: + // Release 1.7 biomes: + biJungleEdge = 23, + biDeepOcean = 24, + biStoneBeach = 25, + biColdBeach = 26, + biBirchForest = 27, + biBirchForestHills = 28, + biRoofedForest = 29, + biColdTaiga = 30, + biColdTaigaHills = 31, + biMegaTaiga = 32, + biMegaTaigaHills = 33, + biExtremeHillsPlus = 34, + biSavanna = 35, + biSavannaPlateau = 36, + biMesa = 37, + biMesaPlateauF = 38, + biMesaPlateau = 39, + + // Automatically capture the maximum consecutive biome value into biMaxBiome: biNumBiomes, // True number of biomes, since they are zero-based - biMaxBiome = biNumBiomes - 1 // The maximum biome value + biMaxBiome = biNumBiomes - 1, // The maximum biome value + + // Add this number to the biomes to get the variant + biVariant = 128, + + // Release 1.7 biome variants: + biSunflowerPlains = 129, + biDesertM = 130, + biExtremeHillsM = 131, + biFlowerForest = 132, + biTaigaM = 133, + biSwamplandM = 134, + biIcePlainsSpikes = 140, + biJungleM = 149, + biJungleEdgeM = 151, + biBirchForestM = 155, + biBirchForestHillsM = 156, + biRoofedForestM = 157, + biColdTaigaM = 158, + biMegaSpruceTaiga = 160, + biMegaSpruceTaigaHills = 161, + biExtremeHillsPlusM = 162, + biSavannaM = 163, + biSavannaPlateauM = 164, + biMesaBryce = 165, + biMesaPlateauFM = 166, + biMesaPlateauM = 167, } ; // tolua_end -- cgit v1.2.3 From d0acb37aedb280f0589275ace342ea6565f80aaa Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 12 Oct 2013 23:05:15 +0100 Subject: Seventh round of fixes * Fixed arrows not critical-effecting because they were in MOBS! (derp) * Used cMonster::mtXX as per xoft's suggestions --- source/Protocol/Protocol125.cpp | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 6d6101fb2..4730c3dfc 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -1701,6 +1701,12 @@ void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity) WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled? } } + else if (a_Entity.IsA("cArrowEntity")); + { + WriteByte(0x10); + WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow? + } + } @@ -1711,7 +1717,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) { switch (a_Mob.GetMobType()) { - case E_META_SPAWN_EGG_CREEPER: + case cMonster::mtCreeper: { WriteByte(0x10); WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up? @@ -1719,25 +1725,25 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged? break; } - case E_META_SPAWN_EGG_BAT: + case cMonster::mtBat: { WriteByte(0x10); WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? break; } - case E_META_SPAWN_EGG_PIG: + case cMonster::mtPig: { WriteByte(0x10); WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? break; } - case E_META_SPAWN_EGG_VILLAGER: + case cMonster::mtVillager: { WriteByte(0x50); WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? break; } - case E_META_SPAWN_EGG_ZOMBIE: + case cMonster::mtZombie: { WriteByte(0xC); WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie? @@ -1747,19 +1753,13 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? break; } - case E_META_SPAWN_EGG_GHAST: + case cMonster::mtGhast: { WriteByte(0x10); WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P break; } - case E_META_SPAWN_EGG_ARROW: - { - WriteByte(0x10); - WriteByte(((const cArrowEntity &)a_Mob).IsCritical() ? 1 : 0); // Critical hitting arrow? - break; - } - case E_META_SPAWN_EGG_WOLF: + case cMonster::mtWolf: { Byte WolfStatus = 0; if (((const cWolf &)a_Mob).IsSitting()) @@ -1783,7 +1783,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode? break; } - case E_META_SPAWN_EGG_SHEEP: + case cMonster::mtSheep: { // [1](1111) // [] = Is sheared? () = Color, from 0 to 15 @@ -1799,7 +1799,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(SheepMetadata); break; } - case E_META_SPAWN_EGG_ENDERMAN: + case cMonster::mtEnderman: { WriteByte(0x10); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house @@ -1809,23 +1809,23 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face? break; } - case E_META_SPAWN_EGG_SKELETON: + case cMonster::mtSkeleton: { WriteByte(0xD); WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not break; } - case E_META_SPAWN_EGG_WITCH: + case cMonster::mtWitch: { WriteByte(0x15); WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything break; } - case E_META_SPAWN_EGG_SLIME: - case E_META_SPAWN_EGG_MAGMA_CUBE: + case cMonster::mtSlime: + case cMonster::mtMagmaCube: { WriteByte(0x10); - if (a_Mob.GetMobType() == E_META_SPAWN_EGG_SLIME) + if (a_Mob.GetMobType() == cMonster::mtSlime) { WriteByte(((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME } @@ -1835,7 +1835,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) } break; } - case E_META_SPAWN_EGG_HORSE: + case cMonster::mtHorse: { int Flags = 0; if (((const cHorse &)a_Mob).IsTame()) -- cgit v1.2.3 From d8d2f35e9dd354fba14f8d6512e818d18d2066c2 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 13 Oct 2013 12:47:55 +0100 Subject: Eight round of fixes * Changed IsA() to *long if statement* - Removed deprecated values in Entity.h - to blazes with the plugins! * Renamed villager type enumerations to be LESS SHOUTY and more vt-y + Use vtMax for World.cpp testificate spawning --- source/Bindings.cpp | 5 ----- source/Entities/Entity.h | 21 ++++++++------------- source/Mobs/Monster.cpp | 2 +- source/Mobs/Villager.h | 13 +++++++------ source/Protocol/Protocol125.cpp | 5 ++--- source/World.cpp | 2 +- 6 files changed, 19 insertions(+), 29 deletions(-) diff --git a/source/Bindings.cpp b/source/Bindings.cpp index a08985144..ae2082511 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -29494,11 +29494,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_constant(tolua_S,"etBoat",cEntity::etBoat); tolua_constant(tolua_S,"etTNT",cEntity::etTNT); tolua_constant(tolua_S,"etProjectile",cEntity::etProjectile); - tolua_constant(tolua_S,"etMob",cEntity::etMob); - tolua_constant(tolua_S,"eEntityType_Entity",cEntity::eEntityType_Entity); - tolua_constant(tolua_S,"eEntityType_Player",cEntity::eEntityType_Player); - tolua_constant(tolua_S,"eEntityType_Pickup",cEntity::eEntityType_Pickup); - tolua_constant(tolua_S,"eEntityType_Mob",cEntity::eEntityType_Mob); tolua_function(tolua_S,"GetEntityType",tolua_AllToLua_cEntity_GetEntityType00); tolua_function(tolua_S,"IsPlayer",tolua_AllToLua_cEntity_IsPlayer00); tolua_function(tolua_S,"IsPickup",tolua_AllToLua_cEntity_IsPickup00); diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h index 07bc84937..064275c06 100644 --- a/source/Entities/Entity.h +++ b/source/Entities/Entity.h @@ -102,13 +102,6 @@ public: etBoat, etTNT, etProjectile, - - // DEPRECATED older constants, left over for compatibility reasons (plugins) - etMob = etMonster, // DEPRECATED, use etMonster instead! - eEntityType_Entity = etEntity, - eEntityType_Player = etPlayer, - eEntityType_Pickup = etPickup, - eEntityType_Mob = etMob, } ; // tolua_end @@ -123,12 +116,14 @@ public: eEntityType GetEntityType(void) const { return m_EntityType; } - bool IsPlayer (void) const { return (m_EntityType == etPlayer); } - bool IsPickup (void) const { return (m_EntityType == etPickup); } - bool IsMob (void) const { return (m_EntityType == etMob); } - bool IsMinecart(void) const { return (m_EntityType == etMinecart); } - bool IsBoat (void) const { return (m_EntityType == etBoat); } - bool IsTNT (void) const { return (m_EntityType == etTNT); } + bool IsPlayer (void) const { return (m_EntityType == etPlayer); } + bool IsPickup (void) const { return (m_EntityType == etPickup); } + 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 IsBoat (void) const { return (m_EntityType == etBoat); } + 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) virtual bool IsA(const char * a_ClassName) const; diff --git a/source/Mobs/Monster.cpp b/source/Mobs/Monster.cpp index 76b9414f7..334229a42 100644 --- a/source/Mobs/Monster.cpp +++ b/source/Mobs/Monster.cpp @@ -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) - : super(etMob, a_Width, a_Height) + : super(etMonster, a_Width, a_Height) , m_Target(NULL) , m_AttackRate(3) , idle_interval(0) diff --git a/source/Mobs/Villager.h b/source/Mobs/Villager.h index 86888d9eb..4cd9aaa8e 100644 --- a/source/Mobs/Villager.h +++ b/source/Mobs/Villager.h @@ -16,12 +16,13 @@ public: enum eVillagerType { - VILLAGER_TYPE_FARMER = 0, - VILLAGER_TYPE_LIBRARIAN = 1, - VILLAGER_TYPE_PRIEST = 2, - VILLAGER_TYPE_BLACKSMITH = 3, - VILLAGER_TYPE_BUTCHER = 4, - VILLAGER_TYPE_GENERIC = 5 + vtFarmer = 0, + vtLibrarian = 1, + vtPriest = 2, + vtBlacksmith = 3, + vtButcher = 4, + vtGeneric = 5, + vtMax } ; cVillager(eVillagerType VillagerType); diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 4730c3dfc..62863cd48 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -1695,18 +1695,17 @@ void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity) WriteByte(0x73); WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer - if (a_Entity.IsA("cMinecartWithFurnace")) + if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace) { WriteByte(0x10); WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled? } } - else if (a_Entity.IsA("cArrowEntity")); + else if ((a_Entity.IsProjectile() && ((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow)); { WriteByte(0x10); WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow? } - } diff --git a/source/World.cpp b/source/World.cpp index da9466bf8..92098bd8b 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -2576,7 +2576,7 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp int ShColor = GetTickRandomNumber(15); // 0 .. 15 - Sheep bool SkType = GetDimension() == biNether; // Skeleton - int VilType = GetTickRandomNumber(6); // 0 .. 5 - Villager + 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.) -- cgit v1.2.3 From 455d33963ff3907c1fae5650416cdc67a6f1607e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 13 Oct 2013 14:13:15 +0200 Subject: Re-added the cWorld:GetSignLines() to the API. Somehow this got lost somewhere. --- source/ManualBindings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index 4242db46a..e6605ddb0 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -2096,6 +2096,7 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>); tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo); tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta); + tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines); tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask); tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines); tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight); -- cgit v1.2.3 From efb7d4fd3e9d20facf6a5b3d41bee8ca3d894bbc Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 13 Oct 2013 20:29:57 +0200 Subject: Fixed WebAdmin's request parameters. Also added doxycomments on what they really contain. --- source/HTTPServer/HTTPFormParser.cpp | 12 ++++++++++++ source/HTTPServer/HTTPFormParser.h | 17 +++++++++++------ source/WebAdmin.cpp | 13 ++++++++++++- source/WebAdmin.h | 6 ++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/source/HTTPServer/HTTPFormParser.cpp b/source/HTTPServer/HTTPFormParser.cpp index 7db7b4e6d..596db424e 100644 --- a/source/HTTPServer/HTTPFormParser.cpp +++ b/source/HTTPServer/HTTPFormParser.cpp @@ -52,6 +52,18 @@ cHTTPFormParser::cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callba +cHTTPFormParser::cHTTPFormParser(eKind a_Kind, const char * a_Data, int a_Size, cCallbacks & a_Callbacks) : + m_Callbacks(a_Callbacks), + m_Kind(a_Kind), + m_IsValid(true) +{ + Parse(a_Data, a_Size); +} + + + + + void cHTTPFormParser::Parse(const char * a_Data, int a_Size) { if (!m_IsValid) diff --git a/source/HTTPServer/HTTPFormParser.h b/source/HTTPServer/HTTPFormParser.h index b92ef9d3c..a554ca5a4 100644 --- a/source/HTTPServer/HTTPFormParser.h +++ b/source/HTTPServer/HTTPFormParser.h @@ -26,6 +26,13 @@ class cHTTPFormParser : public cMultipartParser::cCallbacks { public: + enum eKind + { + fpkURL, ///< The form has been transmitted as parameters to a GET request + fpkFormUrlEncoded, ///< The form has been POSTed or PUT, with Content-Type of "application/x-www-form-urlencoded" + fpkMultipart, ///< The form has been POSTed or PUT, with Content-Type of "multipart/form-data" + } ; + class cCallbacks { public: @@ -40,8 +47,12 @@ public: } ; + /// Creates a parser that is tied to a request and notifies of various events using a callback mechanism cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callbacks); + /// Creates a parser with the specified content type that reads data from a string + cHTTPFormParser(eKind a_Kind, const char * a_Data, int a_Size, cCallbacks & a_Callbacks); + /// Adds more data into the parser, as the request body is received void Parse(const char * a_Data, int a_Size); @@ -54,12 +65,6 @@ public: static bool HasFormData(const cHTTPRequest & a_Request); protected: - enum eKind - { - fpkURL, ///< The form has been transmitted as parameters to a GET request - fpkFormUrlEncoded, ///< The form has been POSTed or PUT, with Content-Type of "application/x-www-form-urlencoded" - fpkMultipart, ///< The form has been POSTed or PUT, with Content-Type of "multipart/form-data" - }; /// The callbacks to call for incoming file data cCallbacks & m_Callbacks; diff --git a/source/WebAdmin.cpp b/source/WebAdmin.cpp index 08817139a..daec2f925 100644 --- a/source/WebAdmin.cpp +++ b/source/WebAdmin.cpp @@ -185,8 +185,19 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque HTTPfd.Name = itr->first; TemplateRequest.Request.FormData[itr->first] = HTTPfd; TemplateRequest.Request.PostParams[itr->first] = itr->second; - TemplateRequest.Request.Params[itr->first] = itr->second; } // for itr - Data->m_Form[] + + // Parse the URL into individual params: + size_t idxQM = a_Request.GetURL().find('?'); + if (idxQM != AString::npos) + { + cHTTPFormParser URLParams(cHTTPFormParser::fpkURL, a_Request.GetURL().c_str() + idxQM + 1, a_Request.GetURL().length() - idxQM - 1, *Data); + URLParams.Finish(); + for (cHTTPFormParser::const_iterator itr = URLParams.begin(), end = URLParams.end(); itr != end; ++itr) + { + TemplateRequest.Request.Params[itr->first] = itr->second; + } // for itr - URLParams[] + } } // Try to get the template from the Lua template script diff --git a/source/WebAdmin.h b/source/WebAdmin.h index 16b5dd4dc..72c77ddfb 100644 --- a/source/WebAdmin.h +++ b/source/WebAdmin.h @@ -56,8 +56,14 @@ struct HTTPRequest AString Path; AString Username; // tolua_end + + /// Parameters given in the URL, after the questionmark StringStringMap Params; // >> EXPORTED IN MANUALBINDINGS << + + /// Parameters posted as a part of a form - either in the URL (GET method) or in the body (POST method) StringStringMap PostParams; // >> EXPORTED IN MANUALBINDINGS << + + /// Same as PostParams FormDataMap FormData; // >> EXPORTED IN MANUALBINDINGS << } ; // tolua_export -- cgit v1.2.3 From 18bbe82f30af5f0ebb0b4789f386f5179ec56f2b Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 13 Oct 2013 22:19:13 +0200 Subject: WebAdmin honors the [WebAdmin].Enable setting. This fixes #234. --- source/WebAdmin.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/WebAdmin.cpp b/source/WebAdmin.cpp index daec2f925..316513f11 100644 --- a/source/WebAdmin.cpp +++ b/source/WebAdmin.cpp @@ -79,8 +79,14 @@ bool cWebAdmin::Init(void) return false; } - AString PortsIPv4 = m_IniFile.GetValue("WebAdmin", "Port", "8080"); - AString PortsIPv6 = m_IniFile.GetValue("WebAdmin", "PortsIPv6", ""); + if (!m_IniFile.GetValueSetB("WebAdmin", "Enabled", true)) + { + // WebAdmin is disabled, bail out faking a success + return true; + } + + AString PortsIPv4 = m_IniFile.GetValueSet("WebAdmin", "Port", "8080"); + AString PortsIPv6 = m_IniFile.GetValueSet("WebAdmin", "PortsIPv6", ""); if (!m_HTTPServer.Initialize(PortsIPv4, PortsIPv6)) { -- cgit v1.2.3 From 9d7e638aa2f0aa2528c3bf230b791159a62354e6 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 09:00:28 +0200 Subject: APIDump: Documented HOOK_CHUNK_AVAILABLE. --- MCServer/Plugins/APIDump/APIDesc.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index dc04d3e81..de25dd761 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2136,6 +2136,27 @@ end; the second value is not provided, the original message is used. ]], }, -- HOOK_CHAT + + HOOK_CHUNK_AVAILABLE = + { + CalledWhen = "A chunk has just been added to world, either generated or loaded. ", + DefaultFnName = "OnChunkAvailable", -- also used as pagename + Desc = [[ + This hook is called after a chunk is either generated or loaded from the disk. The chunk is + already available for manipulation using the {{cWorld}} API. This is a notification-only callback, + there is no behavior that plugins could override. + ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "The world to which the chunk belongs" }, + { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, + { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, + }, + Returns = [[ + If the function returns false or no value, the next plugin's callback is called. If the function + returns true, no other callback is called for this event. + ]], + }, -- HOOK_CHUNK_AVAILABLE }, -- Hooks[] -- cgit v1.2.3 From 26fbefdcbf55d881cc28d43da24192f5d4fb8e9f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 09:03:54 +0200 Subject: APIDump: The undocumented hooks template now has 8 params. This allows for easier copypasting, hooks with less than 9 params don't need an extra copy-paste for a new param entry. --- MCServer/Plugins/APIDump/main.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MCServer/Plugins/APIDump/main.lua b/MCServer/Plugins/APIDump/main.lua index 3827668e3..b4208d208 100644 --- a/MCServer/Plugins/APIDump/main.lua +++ b/MCServer/Plugins/APIDump/main.lua @@ -330,6 +330,13 @@ function DumpAPIHtml() f:write("\t\t\tDesc = [[]],\n"); f:write("\t\t\tParams =\n\t\t\t{\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); f:write("\t\t\tReturns = [[]],\n"); f:write("\t\t}, -- " .. hook .. "\n"); end -- cgit v1.2.3 From 23b4aa48201783dc26816d9df58c3cf66ce2737b Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 09:10:33 +0200 Subject: APIDump: Documented HOOK_CHUNK_GENERATED. --- MCServer/Plugins/APIDump/APIDesc.lua | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index de25dd761..03d90a8fb 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2157,6 +2157,32 @@ end; returns true, no other callback is called for this event. ]], }, -- HOOK_CHUNK_AVAILABLE + + HOOK_CHUNK_GENERATED = + { + CalledWhen = "After a chunk was generated. Notification only.", + DefaultFnName = "OnChunkGenerated", -- also used as pagename + Desc = [[ + This hook is called when world generator finished its work on a chunk. The chunk data has already + been generated and is about to be stored in the {{cWorld|world}}. A plugin may provide some + last-minute finishing touches to the generated data. Note that the chunk is not yet stored in the + world, so regular {{cWorld}} block API will not work! Instead, use the {{cChunkDesc}} object + received as the parameter. + ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "The world to which the chunk will be added" }, + { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, + { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, + { Name = "ChunkDesc", Type = "{{cChunkDesc}}", Notes = "Generated chunk data. Plugins may still modify the chunk data contained." }, + }, + Returns = [[ + If the plugin returns false or no value, MCServer will call other plugins' callbacks for this event. + If a plugin returns true, no other callback is called for this event.

+

+ In either case, MCServer will then store the data from ChunkDesc as the chunk's contents in the world. + ]], + }, -- HOOK_CHUNK_GENERATED }, -- Hooks[] -- cgit v1.2.3 From 8f5ed6511a958a1ed66cbbdfd5939f224475bb05 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 09:30:13 +0200 Subject: APIDump: Added example to HOOK_CHUNK_GENERATED. --- MCServer/Plugins/APIDump/APIDesc.lua | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 03d90a8fb..586c3ae03 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2182,6 +2182,43 @@ end;

In either case, MCServer will then store the data from ChunkDesc as the chunk's contents in the world. ]], + CodeExamples = + { + { + Title = "Generate emerald ore", + Desc = "This example callback function generates one block of emerald ore in each chunk, under the condition that the randomly chosen location is in an ExtremeHills biome.", + Code = [[ +function OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc) + -- Generate a psaudorandom value that is always the same for the same X/Z pair, but is otherwise random enough: + -- This is actually similar to how MCServer does its noise functions + local PseudoRandom = (a_ChunkX * 57 + a_ChunkZ) * 57 + 19785486 + PseudoRandom = PseudoRandom * 8192 + PseudoRandom; + PseudoRandom = ((PseudoRandom * (PseudoRandom * PseudoRandom * 15731 + 789221) + 1376312589) % 0x7fffffff; + PseudoRandom = PseudoRandom / 7; + + -- Based on the PseudoRandom value, choose a location for the ore: + local OreX = PseudoRandom % 16; + local OreY = 2 + ((PseudoRandom / 16) % 20); + local OreZ = (PseudoRandom / 320) % 16; + + -- Check if the location is in ExtremeHills: + if (a_ChunkDesc:GetBiome(OreX, OreZ) ~= biExtremeHills) then + return false; + end + + -- Only replace allowed blocks with the ore: + local CurrBlock = a_ChunDesc:GetBlockType(OreX, OreY, OreZ); + if ( + (CurrBlock == E_BLOCK_STONE) or + (CurrBlock == E_BLOCK_DIRT) or + (CurrBlock == E_BLOCK_GRAVEL) + ) then + a_ChunkDesc:SetBlockTypeMeta(OreX, OreY, OreZ, E_BLOCK_EMERALD_ORE, 0); + end +end; + ]], + }, + } , -- CodeExamples }, -- HOOK_CHUNK_GENERATED }, -- Hooks[] -- cgit v1.2.3 From 42b65c164d0979494dd7bfea214434f912c2f4e3 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 09:32:55 +0200 Subject: APIDump: Fixed undocumented hook param generator. --- MCServer/Plugins/APIDump/main.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/MCServer/Plugins/APIDump/main.lua b/MCServer/Plugins/APIDump/main.lua index b4208d208..87583be0e 100644 --- a/MCServer/Plugins/APIDump/main.lua +++ b/MCServer/Plugins/APIDump/main.lua @@ -329,14 +329,15 @@ function DumpAPIHtml() f:write("\t\t\tDefaultFnName = \"On\", -- also used as pagename\n"); f:write("\t\t\tDesc = [[]],\n"); f:write("\t\t\tParams =\n\t\t\t{\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); - f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n\t\t\t},\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); + f:write("\t\t\t},\n"); f:write("\t\t\tReturns = [[]],\n"); f:write("\t\t}, -- " .. hook .. "\n"); end -- cgit v1.2.3 From fb209757f0ad3c19f2925af00ac323236fd86741 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 09:41:06 +0200 Subject: APIDump: Documented HOOK_CHUNK_GENERATING. --- MCServer/Plugins/APIDump/APIDesc.lua | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 586c3ae03..578d6aeab 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2167,7 +2167,9 @@ end; been generated and is about to be stored in the {{cWorld|world}}. A plugin may provide some last-minute finishing touches to the generated data. Note that the chunk is not yet stored in the world, so regular {{cWorld}} block API will not work! Instead, use the {{cChunkDesc}} object - received as the parameter. + received as the parameter.

+

+ See also the {{OnChunkGenerating|HOOK_CHUNK_GENERATING}} hook. ]], Params = { @@ -2220,6 +2222,36 @@ end; }, } , -- CodeExamples }, -- HOOK_CHUNK_GENERATED + + HOOK_CHUNK_GENERATING = + { + CalledWhen = "A chunk is about to be generated. Plugin can override the built-in generator.", + DefaultFnName = "OnChunkGenerating", -- also used as pagename + Desc = [[ + This hook is called before the world generator starts generating a chunk. The plugin may provide + some or all parts of the generation, by-passing the built-in generator. The function is given access + to the {{cChunkDesc|ChunkDesc}} object representing the contents of the chunk. It may override parts + of the built-in generator by using the object's SetUseDefaultXXX(false) functions. After all + the callbacks for a chunk have been processed, the server will generate the chunk based on the + {{cChunkDesc|ChunkDesc}} description - those parts that are set for generating (by default + everything) are generated, the rest are read from the ChunkDesc object.

+

+ See also the {{OnChunkGenerated|HOOK_CHUNK_GENERATED}} hook. + ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "The world to which the chunk will be added" }, + { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, + { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, + { Name = "ChunkDesc", Type = "{{cChunkDesc}}", Notes = "Generated chunk data." }, + }, + Returns = [[ + If this function returns true, the server will not call any other plugin with the same chunk. If + this function returns false, the server will call the rest of the plugins with the same chunk, + possibly overwriting the ChunkDesc's contents. + ]], + }, -- HOOK_CHUNK_GENERATING + }, -- Hooks[] -- cgit v1.2.3 From 37ea7ec0c1e9b278a53d0cc1485e216099ea1eee Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 15:46:01 +0200 Subject: APIDump: Documented HOOK_CHUNK_UNLOADED. --- MCServer/Plugins/APIDump/APIDesc.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 578d6aeab..6be0b6887 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2252,6 +2252,28 @@ end; ]], }, -- HOOK_CHUNK_GENERATING + HOOK_CHUNK_UNLOADED = + { + CalledWhen = "A chunk has been unloaded from the memory.", + DefaultFnName = "OnChunkUnloaded", -- also used as pagename + Desc = [[ + This hook is called when a chunk is unloaded from the memory. Though technically still in memory, + the plugin should behave as if the chunk was already not present. In particular, {{cWorld}} block + API should not be used in the area of the specified chunk. + ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "The world from which the chunk is unloading" }, + { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, + { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, + }, + Returns = [[ + If the function returns false or no value, the next plugin's callback is called. If the function + returns true, no other callback is called for this event. There is no behavior that plugins could + override. + ]], + }, -- HOOK_CHUNK_UNLOADED + }, -- Hooks[] -- cgit v1.2.3 From 0b71b3bd141816869eb19b3a9841a8d16f5e4be9 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 15:50:11 +0200 Subject: APIDump: Documented HOOK_CHUNK_UNLOADING. --- MCServer/Plugins/APIDump/APIDesc.lua | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 6be0b6887..013b3c69e 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2274,6 +2274,29 @@ end; ]], }, -- HOOK_CHUNK_UNLOADED + HOOK_CHUNK_UNLOADING = + { + CalledWhen = " A chunk is about to be unloaded from the memory. Plugins may refuse the unload.", + DefaultFnName = "OnChunkUnloading", -- also used as pagename + Desc = [[ + MCServer calls this function when a chunk is about to be unloaded from the memory. A plugin may + force MCServer to keep the chunk in memory by returning true.

+

+ FIXME: The return value should be used only for event propagation stopping, not for the actual + decision whether to unload. + ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "The world from which the chunk is unloading" }, + { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, + { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, + }, + Returns = [[ + If the function returns false or no value, the next plugin's callback is called and finally MCServer + unloads the chunk. If the function returns true, no other callback is called for this event and the + chunk is left in the memory. + ]], + }, -- HOOK_CHUNK_UNLOADING }, -- Hooks[] -- cgit v1.2.3 From c8702e15bbced0a655d08761ea9173950445238c Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 15:53:41 +0200 Subject: APIDump: Documented HOOK_COLLECTING_PICKUP. --- MCServer/Plugins/APIDump/APIDesc.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 013b3c69e..6044b0a0a 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2297,6 +2297,33 @@ end; chunk is left in the memory. ]], }, -- HOOK_CHUNK_UNLOADING + + HOOK_COLLECTING_PICKUP = + { + CalledWhen = "Player is about to collect a pickup. Plugin can refuse / override behavior. ", + DefaultFnName = "OnCollectingPickup", -- also used as pagename + Desc = [[ + This hook is called when a player is about to collect a pickup. Plugins may refuse the action.

+

+ Pickup collection happens within the world tick, so if the collecting is refused, it will be tried + again in the next world tick, as long as the player is within reach of the pickup.

+

+ FIXME: There is no OnCollectedPickup() callback.

+

+ FIXME: This callback is called even if the pickup doesn't fit into the player's inventory.

+ ]], + Params = + { + { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who's collecting the pickup" }, + { Name = "Pickup", Type = "{{cPickup}}", Notes = "The pickup being collected" }, + }, + Returns = [[ + If the function returns false or no value, MCServer calls other plugins' callbacks and finally the + pickup is collected. If the function returns true, no other plugins are called for this event and + the pickup is not collected. + ]], + }, -- HOOK_COLLECTING_PICKUP + }, -- Hooks[] -- cgit v1.2.3 From f546a0e180cf153ed53ea0fc083f7954901e15e6 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:02:32 +0200 Subject: APIDump: Documented HOOK_CRAFTING_NO_RECIPE. --- MCServer/Plugins/APIDump/APIDesc.lua | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 6044b0a0a..adc3a9835 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2324,6 +2324,32 @@ end; ]], }, -- HOOK_COLLECTING_PICKUP + HOOK_CRAFTING_NO_RECIPE = + { + CalledWhen = " No built-in crafting recipe is found. Plugin may provide a recipe.", + DefaultFnName = "OnCraftingNoRecipe", -- also used as pagename + Desc = [[ + This callback is called when a player places items in their {{cCraftingGrid|crafting grid}} and + MCServer cannot find a built-in {{cCraftingRecipe|recipe}} for the combination. Plugins may provide + a recipe for the ingredients given. + ]], + Params = + { + { Name = "Player", Type = "{{cPlayer}}", Notes = "The player whose crafting is reported in this hook" }, + { Name = "Grid", Type = "{{cCraftingGrid}}", Notes = "Contents of the player's crafting grid" }, + { Name = "Recipe", Type = "{{cCraftingRecipe}}", Notes = "The recipe that will be used (can be filled by plugins)" }, + }, + Returns = [[ + If the function returns false or no value, no recipe will be used. If the function returns true, no + other plugin will have their callback called for this event and MCServer will use the crafting + recipe in Recipe.

+

+ FIXME: To allow plugins give suggestions and overwrite other plugins' suggestions, we should change + the behavior with returning false, so that the recipe will still be used, but fill the recipe with + empty values by default. + ]], + }, -- HOOK_CRAFTING_NO_RECIPE + }, -- Hooks[] -- cgit v1.2.3 From ca285563d95d34ab8c9c57b9de948216c073d6c2 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:04:43 +0200 Subject: APIDump: Fixed info missing from cCraftingRecipe. --- MCServer/Plugins/APIDump/APIDesc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index adc3a9835..35d50a861 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -546,7 +546,7 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(), Desc = [[ This class is used to represent a crafting recipe, either a built-in one, or one created dynamically in a plugin. It is used only as a parameter for {{OnCraftingNoRecipe|OnCraftingNoRecipe}}, {{OnPostCrafting|OnPostCrafting}} and {{OnPreCrafting|OnPreCrafting}} hooks. Plugins may use it to inspect or modify a crafting recipe that a player views in their crafting window, either at a crafting table or the survival inventory screen.

-

Internally, the class contains a {{cItem|cItem}} for the result. +

Internally, the class contains a {{cCraftingGrid}} for the ingredients and a {{cItem}} for the result. ]], Functions = { -- cgit v1.2.3 From 56bc94139d1982ec2a3f779bd8d66eab64ddca1c Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:12:32 +0200 Subject: APIDump: Documented HOOK_DISCONNECT. --- MCServer/Plugins/APIDump/APIDesc.lua | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 35d50a861..7530c3857 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2350,6 +2350,32 @@ end; ]], }, -- HOOK_CRAFTING_NO_RECIPE + HOOK_DISCONNECT = + { + CalledWhen = "A player has explicitly disconnected.", + DefaultFnName = "OnDisconnect", -- also used as pagename + Desc = [[ + This hook is called when a client sends the disconnect packet and is about to be disconnected from + the server.

+

+ Note that this callback is not called if the client drops the connection or is kicked by the + server.

+

+ FIXME: There is no callback for "client destroying" that would be called in all circumstances.

+ ]], + Params = + { + { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has disconnected" }, + { Name = "Reason", Type = "string", Notes = "The reason that the client has sent in the disconnect packet" }, + }, + Returns = [[ + If the function returns false or no value, MCServer calls other plugins' callbacks for this event + and finally broadcasts a disconnect message to the player's world. If the function returns true, no + other plugins are called for this event and the disconnect message is not broadcast. In either case, + the player is disconnected. + ]], + }, -- HOOK_DISCONNECT + }, -- Hooks[] -- cgit v1.2.3 From 66d8c1b3067efc2893b9db3cc434cadc769382cc Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:13:39 +0200 Subject: APIDump: Updated the template for undocumented hooks. --- MCServer/Plugins/APIDump/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MCServer/Plugins/APIDump/main.lua b/MCServer/Plugins/APIDump/main.lua index 87583be0e..8c07144f2 100644 --- a/MCServer/Plugins/APIDump/main.lua +++ b/MCServer/Plugins/APIDump/main.lua @@ -327,7 +327,7 @@ function DumpAPIHtml() f:write("\t\t" .. hook .. " =\n\t\t{\n"); f:write("\t\t\tCalledWhen = \"\",\n"); f:write("\t\t\tDefaultFnName = \"On\", -- also used as pagename\n"); - f:write("\t\t\tDesc = [[]],\n"); + f:write("\t\t\tDesc = [[\n\t\t\t\t\n\t\t\t]],\n"); f:write("\t\t\tParams =\n\t\t\t{\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); @@ -338,7 +338,7 @@ function DumpAPIHtml() f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t},\n"); - f:write("\t\t\tReturns = [[]],\n"); + f:write("\t\t\tReturns = [[\n\t\t\t\t\n\t\t\t]],\n"); f:write("\t\t}, -- " .. hook .. "\n"); end end -- cgit v1.2.3 From 112e96ae9b17156cb18192421728a538ed0c51e4 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:20:32 +0200 Subject: APIDump: Documented HOOK_EXECUTE_COMMAND. --- MCServer/Plugins/APIDump/APIDesc.lua | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 7530c3857..e49c09ec8 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2376,6 +2376,31 @@ end; ]], }, -- HOOK_DISCONNECT + HOOK_EXECUTE_COMMAND = + { + CalledWhen = "A player executes an in-game command, or the admin issues a console command. Note that built-in console commands are exempt to this hook - they are always performed and the hook is not called.", + DefaultFnName = "OnExecuteCommand", -- also used as pagename + Desc = [[ + A plugin may implement a callback for this hook to intercept both in-game commands executed by the + players and console commands executed by the server admin. The function is called for every in-game + command sent from any player and for those server console commands that are not built in in the + server.

+

+ If the command is in-game, the first parameter to the hook function is the {{cPlayer|player}} who's + executing the command. If the command comes from the server console, the first parameter is nil. + ]], + Params = + { + { Name = "Player", Type = "{{cPlayer}}", Notes = "For in-game commands, the player who has sent the message. For console commands, nil" }, + { Name = "Command", Type = "table of strings", Notes = "The command and its parameters, broken into a table by spaces" }, + }, + Returns = [[ + If the plugin returns true, the command will be blocked and none of the remaining hook handlers will + be called. If the plugin returns false, MCServer calls all the remaining hook handlers and finally + the command will be executed. + ]], + }, -- HOOK_EXECUTE_COMMAND + }, -- Hooks[] -- cgit v1.2.3 From 211b03a87082c3a99c171326afd79163274d663c Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:43:39 +0200 Subject: APIDump: Documented HOOK_EXPLODED. --- MCServer/Plugins/APIDump/APIDesc.lua | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index e49c09ec8..0ef93b400 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2401,6 +2401,49 @@ end; ]], }, -- HOOK_EXECUTE_COMMAND + HOOK_EXPLODED = + { + CalledWhen = "An explosion has happened", + DefaultFnName = "OnExploded", -- also used as pagename + Desc = [[ + This hook is called after an explosion has been processed in a world.

+

+ See also {{OnHookExploding|HOOK_EXPLODING}} for a similar hook called before the explosion.

+

+ The explosion carries with it the type of its source - whether it's a creeper exploding, or TNT, + etc. It also carries the identification of the actual source. The exact type of the identification + depends on the source kind: + + + + + + + + + + + + +
SourceSourceData TypeNotes
esPrimedTNT{{cTNTEntity}}An exploding primed TNT entity
esCreeper{{cCreeper}}An exploding creeper or charged creeper
esBed{{Vector3i}}A bed exploding in the Nether or in the End. The bed coords are given.
esEnderCrystal{{Vector3i}}An ender crystal exploding upon hit. The block coords are given.
esGhastFireball{{cGhastFireballEntity}}A ghast fireball hitting ground or an {{cEntity|entity}}.
esWitherSkullBlackTBDA black wither skull hitting ground or an {{cEntity|entity}}.
esWitherSkullBlueTBDA blue wither skull hitting ground or an {{cEntity|entity}}.
esWitherBirthTBDA wither boss being created
esOtherTBDAny other previously unspecified type.
esPluginobjectAn explosion created by a plugin. The plugin may specify any kind of data.

+ ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "The world where the explosion happened" }, + { Name = "ExplosionSize", Type = "number", Notes = "The relative explosion size" }, + { Name = "CanCauseFire", Type = "bool", Notes = "True if the explosion has turned random air blocks to fire (such as a ghast fireball)" }, + { Name = "X", Type = "number", Notes = "X-coord of the explosion center" }, + { Name = "Y", Type = "number", Notes = "Y-coord of the explosion center" }, + { Name = "Z", Type = "number", Notes = "Z-coord of the explosion center" }, + { Name = "Source", Type = "eExplosionSource", Notes = "Source of the explosion. See the table above." }, + { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the table above." }, + }, + Returns = [[ + If the function returns false or no value, the next plugin's callback is called. If the function + returns true, no other callback is called for this event. There is no overridable behaviour. + ]], + }, -- HOOK_EXPLODED + }, -- Hooks[] -- cgit v1.2.3 From c360849fa0fe016adb8186f09a862090b3858b06 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:53:13 +0200 Subject: APIDump: Documented HOOK_EXPLODING. --- MCServer/Plugins/APIDump/APIDesc.lua | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 0ef93b400..871b04543 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2444,6 +2444,50 @@ end; ]], }, -- HOOK_EXPLODED + HOOK_EXPLODING = + { + CalledWhen = "An explosion is about to be processed", + DefaultFnName = "OnExploding", -- also used as pagename + Desc = [[ + This hook is called before an explosion has been processed in a world.

+

+ See also {{OnHookExploded|HOOK_EXPLODED}} for a similar hook called after the explosion.

+

+ The explosion carries with it the type of its source - whether it's a creeper exploding, or TNT, + etc. It also carries the identification of the actual source. The exact type of the identification + depends on the source kind: + + + + + + + + + + + + +
SourceSourceData TypeNotes
esPrimedTNT{{cTNTEntity}}An exploding primed TNT entity
esCreeper{{cCreeper}}An exploding creeper or charged creeper
esBed{{Vector3i}}A bed exploding in the Nether or in the End. The bed coords are given.
esEnderCrystal{{Vector3i}}An ender crystal exploding upon hit. The block coords are given.
esGhastFireball{{cGhastFireballEntity}}A ghast fireball hitting ground or an {{cEntity|entity}}.
esWitherSkullBlackTBDA black wither skull hitting ground or an {{cEntity|entity}}.
esWitherSkullBlueTBDA blue wither skull hitting ground or an {{cEntity|entity}}.
esWitherBirthTBDA wither boss being created
esOtherTBDAny other previously unspecified type.
esPluginobjectAn explosion created by a plugin. The plugin may specify any kind of data.

+ ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "The world where the explosion happens" }, + { Name = "ExplosionSize", Type = "number", Notes = "The relative explosion size" }, + { Name = "CanCauseFire", Type = "bool", Notes = "True if the explosion will turn random air blocks to fire (such as a ghast fireball)" }, + { Name = "X", Type = "number", Notes = "X-coord of the explosion center" }, + { Name = "Y", Type = "number", Notes = "Y-coord of the explosion center" }, + { Name = "Z", Type = "number", Notes = "Z-coord of the explosion center" }, + { Name = "Source", Type = "eExplosionSource", Notes = "Source of the explosion. See the table above." }, + { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the table above." }, + }, + Returns = [[ + If the function returns false or no value, the next plugin's callback is called, and finally + MCServer will process the explosion - destroy blocks and push + hurt entities. If the function + returns true, no other callback is called for this event and the explosion will not occur. + ]], + }, -- HOOK_EXPLODING + }, -- Hooks[] -- cgit v1.2.3 From 5c24d5acd7adcfa5a0bd121275f54b7d67505afb Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 14 Oct 2013 16:59:45 +0200 Subject: APIDump: Documented HOOK_HANDSHAKE. --- MCServer/Plugins/APIDump/APIDesc.lua | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 871b04543..12665888b 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2488,6 +2488,29 @@ end; ]], }, -- HOOK_EXPLODING + HOOK_HANDSHAKE = + { + CalledWhen = "A client is connecting.", + DefaultFnName = "OnHandshake", -- also used as pagename + Desc = [[ + This hook is called when a client sends the Handshake packet. At this stage, only the client IP and + (unverified) username are known. Plugins may refuse access to the server based on this + information.

+

+ Note that the username is not authenticated - the authentication takes place only after this hook is + processed. + ]], + Params = + { + { Name = "Client", Type = "{{cClientHandle}}", Notes = "The client handle representing the connection. Note that there's no {{cPlayer}} object for this client yet." }, + { Name = "UserName", Type = "string", Notes = "The username presented in the packet. Note that this username is unverified." }, + }, + Returns = [[ + If the function returns false, the user is let in to the server. If the function returns true, no + other plugin's callback is called, the user is kicked and the connection is closed. + ]], + }, -- HOOK_HANDSHAKE + }, -- Hooks[] -- cgit v1.2.3