summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Harkness <bearbin@gmail.com>2013-11-26 18:21:06 +0100
committerAlexander Harkness <bearbin@gmail.com>2013-11-26 18:21:06 +0100
commit0de95a215f960c51bd7180218c1acef2414ce7d0 (patch)
tree80c80002565be1dc2fa537416ca7e6a1fd3e9da0
parentMerge branch 'master' into foldermove2 (diff)
parentcWorld::SpawnExperienceOrb() now returns the entity ID of the spawned orb. (diff)
downloadcuberite-0de95a215f960c51bd7180218c1acef2414ce7d0.tar
cuberite-0de95a215f960c51bd7180218c1acef2414ce7d0.tar.gz
cuberite-0de95a215f960c51bd7180218c1acef2414ce7d0.tar.bz2
cuberite-0de95a215f960c51bd7180218c1acef2414ce7d0.tar.lz
cuberite-0de95a215f960c51bd7180218c1acef2414ce7d0.tar.xz
cuberite-0de95a215f960c51bd7180218c1acef2414ce7d0.tar.zst
cuberite-0de95a215f960c51bd7180218c1acef2414ce7d0.zip
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua2
-rw-r--r--VC2008/MCServer.vcproj12
-rw-r--r--src/Bindings.cpp44
-rw-r--r--src/Bindings.h2
-rw-r--r--src/ClientHandle.cpp9
-rw-r--r--src/ClientHandle.h2
-rw-r--r--src/Entities/Entity.h1
-rw-r--r--src/Entities/ExpOrb.cpp60
-rw-r--r--src/Entities/ExpOrb.h29
-rw-r--r--src/Mobs/Monster.cpp55
-rw-r--r--src/OSSupport/File.cpp9
-rw-r--r--src/Protocol/Protocol.h2
-rw-r--r--src/Protocol/Protocol125.cpp18
-rw-r--r--src/Protocol/Protocol125.h1
-rw-r--r--src/Protocol/Protocol17x.cpp15
-rw-r--r--src/Protocol/Protocol17x.h1
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp10
-rw-r--r--src/Protocol/ProtocolRecognizer.h1
-rw-r--r--src/World.cpp12
-rw-r--r--src/World.h3
20 files changed, 282 insertions, 6 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index 44e4bb35f..6545c1f9f 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -769,6 +769,7 @@ end
{
etBoat = { Notes = "The entity is a {{cBoat}}" },
etEntity = { Notes = "No further specialization available" },
+ etExpOrb = { Notes = "The entity is a {{cExpOrb}}" },
etFallingBlock = { Notes = "The entity is a {{cFallingBlock}}" },
etMob = { Notes = "The entity is a {{cMonster}} descendant" },
etMonster = { Notes = "The entity is a {{cMonster}} descendant" },
@@ -2075,6 +2076,7 @@ end
{ Params = "{{cItems|Pickups}}, X, Y, Z, SpeedX, SpeedY, SpeedZ", Return = "", Notes = "Spawns the specified pickups at the position specified. All the pickups fly away from the spawn position using the specified speed." },
},
SpawnMob = { Params = "X, Y, Z, {{cMonster|MonsterType}}", Return = "EntityID", Notes = "Spawns the specified type of mob at the specified coords. Returns the EntityID of the creates entity, or -1 on failure. " },
+ SpawnExperienceOrb = { Params = "X, Y, Z, Reward", Return = "EntityID", Notes = "Spawns an {{cExpOrb|experience orb}} at the specified coords, with the given reward" },
SpawnPrimedTNT = { Params = "X, Y, Z, FuseTimeSecs, InitialVelocityCoeff", Return = "", Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse time. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value." },
TryGetHeight = { Params = "BlockX, BlockZ", Return = "IsValid, Height", Notes = "Returns true and height of the highest non-air block if the chunk is loaded, or false otherwise." },
UnloadUnusedChunks = { Params = "", Return = "", Notes = "Unloads chunks that are no longer needed, and are saved. NOTE: This API is deprecated and will be removed soon." },
diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index ff0e328e0..f189da9d7 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -1272,6 +1272,18 @@
>
</File>
<File
+ RelativePath="..\src\Entities\ExpOrb.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\Entities\ExpOrb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\Entities\TNTEntity.cpp"
+ >
+ </File>
+ <File
RelativePath="..\src\Entities\TNTEntity.h"
>
</File>
diff --git a/src/Bindings.cpp b/src/Bindings.cpp
index cbb50a321..7fc9be379 100644
--- a/src/Bindings.cpp
+++ b/src/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 11/23/13 19:57:30.
+** Generated automatically by tolua++-1.0.92 on 11/26/13 15:29:19.
*/
#ifndef __cplusplus
@@ -12589,6 +12589,46 @@ tolua_lerror:
}
#endif //#ifndef TOLUA_DISABLE
+/* method: SpawnExperienceOrb of class cWorld */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_SpawnExperienceOrb00
+static int tolua_AllToLua_cWorld_SpawnExperienceOrb00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,4,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,5,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,6,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0);
+ double a_X = ((double) tolua_tonumber(tolua_S,2,0));
+ double a_Y = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_Z = ((double) tolua_tonumber(tolua_S,4,0));
+ int a_Reward = ((int) tolua_tonumber(tolua_S,5,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SpawnExperienceOrb'", NULL);
+#endif
+ {
+ int tolua_ret = (int) self->SpawnExperienceOrb(a_X,a_Y,a_Z,a_Reward);
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SpawnExperienceOrb'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: SpawnPrimedTNT of class cWorld */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_SpawnPrimedTNT00
static int tolua_AllToLua_cWorld_SpawnPrimedTNT00(lua_State* tolua_S)
@@ -30430,6 +30470,7 @@ 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,"etExpOrb",cEntity::etExpOrb);
tolua_constant(tolua_S,"etMob",cEntity::etMob);
tolua_function(tolua_S,"GetEntityType",tolua_AllToLua_cEntity_GetEntityType00);
tolua_function(tolua_S,"IsPlayer",tolua_AllToLua_cEntity_IsPlayer00);
@@ -30801,6 +30842,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"SetBlockMeta",tolua_AllToLua_cWorld_SetBlockMeta01);
tolua_function(tolua_S,"SpawnItemPickups",tolua_AllToLua_cWorld_SpawnItemPickups00);
tolua_function(tolua_S,"SpawnItemPickups",tolua_AllToLua_cWorld_SpawnItemPickups01);
+ tolua_function(tolua_S,"SpawnExperienceOrb",tolua_AllToLua_cWorld_SpawnExperienceOrb00);
tolua_function(tolua_S,"SpawnPrimedTNT",tolua_AllToLua_cWorld_SpawnPrimedTNT00);
tolua_function(tolua_S,"DigBlock",tolua_AllToLua_cWorld_DigBlock00);
tolua_function(tolua_S,"SendBlockTo",tolua_AllToLua_cWorld_SendBlockTo00);
diff --git a/src/Bindings.h b/src/Bindings.h
index bc8589293..240ceec30 100644
--- a/src/Bindings.h
+++ b/src/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 11/23/13 19:57:31.
+** Generated automatically by tolua++-1.0.92 on 11/26/13 15:29:20.
*/
/* Exported function */
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index daf09d4ea..b3e12ce77 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -1885,6 +1885,15 @@ void cClientHandle::SendExperience(void)
+void cClientHandle::SendExperienceOrb(const cExpOrb & a_ExpOrb)
+{
+ m_Protocol->SendExperienceOrb(a_ExpOrb);
+}
+
+
+
+
+
void cClientHandle::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
{
m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch);
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index b887bb11a..b3550110d 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -25,6 +25,7 @@ class cChunkDataSerializer;
class cInventory;
class cMonster;
class cPawn;
+class cExpOrb;
class cPickup;
class cPlayer;
class cProtocol;
@@ -121,6 +122,7 @@ public:
void SendPlayerSpawn (const cPlayer & a_Player);
void SendRespawn (void);
void SendExperience (void);
+ void SendExperienceOrb (const cExpOrb & a_ExpOrb);
void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch); // a_Src coords are Block * 8
void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data);
void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock);
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index dafda7826..de5f176ae 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -74,6 +74,7 @@ public:
etBoat,
etTNT,
etProjectile,
+ etExpOrb,
// Common variations
etMob = etMonster, // DEPRECATED, use etMonster instead!
diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp
new file mode 100644
index 000000000..1e5ee00ce
--- /dev/null
+++ b/src/Entities/ExpOrb.cpp
@@ -0,0 +1,60 @@
+#include "Globals.h"
+
+#include "ExpOrb.h"
+#include "Player.h"
+#include "../ClientHandle.h"
+
+
+cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward) :
+ cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98),
+ m_Reward(a_Reward)
+{
+}
+
+
+
+
+
+cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward) :
+ cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98),
+ m_Reward(a_Reward)
+{
+}
+
+
+
+
+
+void cExpOrb::SpawnOn(cClientHandle & a_Client)
+{
+ a_Client.SendExperienceOrb(*this);
+ m_bDirtyPosition = false;
+ m_bDirtySpeed = false;
+ m_bDirtyOrientation = false;
+ m_bDirtyHead = false;
+}
+
+
+
+
+
+void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ cPlayer * a_ClosestPlayer(m_World->FindClosestPlayer(Vector3f(GetPosition()), 4));
+ if (a_ClosestPlayer)
+ {
+ Vector3f a_PlayerPos(a_ClosestPlayer->GetPosition());
+ Vector3f a_Distance(a_PlayerPos - GetPosition());
+ if (a_Distance.Length() < 0.1f)
+ {
+ a_ClosestPlayer->DeltaExperience(m_Reward);
+ a_ClosestPlayer->SendExperience();
+ Destroy(true);
+ }
+ a_Distance.y = 0;
+ a_Distance.Normalize();
+ a_Distance *= 3;
+ SetSpeedX( a_Distance.x );
+ SetSpeedZ( a_Distance.z );
+ }
+} \ No newline at end of file
diff --git a/src/Entities/ExpOrb.h b/src/Entities/ExpOrb.h
new file mode 100644
index 000000000..a062eedd3
--- /dev/null
+++ b/src/Entities/ExpOrb.h
@@ -0,0 +1,29 @@
+
+#pragma once
+
+#include "Entity.h"
+
+
+
+
+
+class cExpOrb :
+ public cEntity
+{
+ typedef cExpOrb super;
+
+public:
+
+ cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward);
+ cExpOrb(const Vector3d & a_Pos, int a_Reward);
+
+ // Override functions
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void SpawnOn(cClientHandle & a_Client) override;
+
+ // cExpOrb functions
+ int GetReward(void) const { return m_Reward; }
+
+protected:
+ int m_Reward;
+} ; \ No newline at end of file
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 8a5717e27..091623c8a 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -7,6 +7,7 @@
#include "../ClientHandle.h"
#include "../World.h"
#include "../Entities/Player.h"
+#include "../Entities/ExpOrb.h"
#include "../Defines.h"
#include "../MonsterConfig.h"
#include "../MersenneTwister.h"
@@ -258,6 +259,60 @@ void cMonster::KilledBy(cEntity * a_Killer)
{
m_World->BroadcastSoundEffect(m_SoundDeath, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f);
}
+ int Reward;
+ switch (m_MobType)
+ {
+ // Animals
+ case cMonster::mtChicken:
+ case cMonster::mtCow:
+ case cMonster::mtHorse:
+ case cMonster::mtPig:
+ case cMonster::mtSheep:
+ case cMonster::mtSquid:
+ case cMonster::mtMooshroom:
+ case cMonster::mtOcelot:
+ case cMonster::mtWolf:
+ {
+ Reward = m_World->GetTickRandomNumber(2) + 1;
+ }
+
+ // Monsters
+ case cMonster::mtCaveSpider:
+ case cMonster::mtCreeper:
+ case cMonster::mtEnderman:
+ case cMonster::mtGhast:
+ case cMonster::mtSilverfish:
+ case cMonster::mtSkeleton:
+ case cMonster::mtSpider:
+ case cMonster::mtWitch:
+ case cMonster::mtZombie:
+ case cMonster::mtZombiePigman:
+ case cMonster::mtSlime:
+ case cMonster::mtMagmaCube:
+ {
+ Reward = 6 + (m_World->GetTickRandomNumber(2));
+ }
+ case cMonster::mtBlaze:
+ {
+ Reward = 10;
+ }
+
+ // Bosses
+ case cMonster::mtEnderDragon:
+ {
+ Reward = 12000;
+ }
+ case cMonster::mtWither:
+ {
+ Reward = 50;
+ }
+
+ default:
+ {
+ Reward = 0;
+ }
+ }
+ m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), Reward);
m_DestroyTimer = 0;
}
diff --git a/src/OSSupport/File.cpp b/src/OSSupport/File.cpp
index 274aa52da..9f7c0d439 100644
--- a/src/OSSupport/File.cpp
+++ b/src/OSSupport/File.cpp
@@ -394,13 +394,14 @@ AStringVector cFile::GetFolderContents(const AString & a_Folder)
DIR * dp;
struct dirent *dirp;
- if (*a_Directory == 0)
+ AString Folder = a_Folder;
+ if (Folder.empty())
{
- a_Directory = ".";
+ Folder = ".";
}
- if ((dp = opendir(a_Directory)) == NULL)
+ if ((dp = opendir(Folder.c_str())) == NULL)
{
- LOGERROR("Error (%i) opening directory \"%s\"\n", errno, a_Directory );
+ LOGERROR("Error (%i) opening directory \"%s\"\n", errno, Folder.c_str());
}
else
{
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 542060ece..9d8183361 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -16,6 +16,7 @@
+class cExpOrb;
class cPlayer;
class cEntity;
class cWindow;
@@ -86,6 +87,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
virtual void SendRespawn (void) = 0;
virtual void SendExperience (void) = 0;
+ virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) = 0; // a_Src coords are Block * 8
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0;
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index 54be65b12..b1dd17ea1 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -17,6 +17,7 @@ Documentation:
#include "../World.h"
#include "ChunkDataSerializer.h"
#include "../Entities/Entity.h"
+#include "../Entities/ExpOrb.h"
#include "../Mobs/Monster.h"
#include "../Entities/Pickup.h"
#include "../Entities/Player.h"
@@ -72,6 +73,7 @@ enum
PACKET_ENT_STATUS = 0x26,
PACKET_ATTACH_ENTITY = 0x27,
PACKET_METADATA = 0x28,
+ PACKET_SPAWN_EXPERIENCE_ORB = 0x1A,
PACKET_EXPERIENCE = 0x2b,
PACKET_PRE_CHUNK = 0x32,
PACKET_MAP_CHUNK = 0x33,
@@ -705,6 +707,22 @@ void cProtocol125::SendExperience(void)
+void cProtocol125::SendExperienceOrb(const cExpOrb & a_ExpOrb)
+{
+ cCSLock Lock(m_CSPacket);
+ WriteByte(PACKET_SPAWN_EXPERIENCE_ORB);
+ WriteInt(a_ExpOrb.GetUniqueID());
+ WriteInt((int) a_ExpOrb.GetPosX());
+ WriteInt((int) a_ExpOrb.GetPosY());
+ WriteInt((int) a_ExpOrb.GetPosZ());
+ WriteShort(a_ExpOrb.GetReward());
+ Flush();
+}
+
+
+
+
+
void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
{
// Not needed in this protocol version
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index c5f44c818..5a9218f5b 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -63,6 +63,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
+ virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index ae1df7395..746e1c127 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -17,6 +17,7 @@ Implements the 1.7.x protocol classes:
#include "../World.h"
#include "../WorldStorage/FastNBT.h"
#include "../StringCompression.h"
+#include "../Entities/ExpOrb.h"
#include "../Entities/Minecart.h"
#include "../Entities/FallingBlock.h"
#include "../Entities/Pickup.h"
@@ -609,6 +610,20 @@ void cProtocol172::SendExperience (void)
+void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
+{
+ cPacketizer Pkt(*this, 0x11);
+ Pkt.WriteVarInt(a_ExpOrb.GetUniqueID());
+ Pkt.WriteInt((int) a_ExpOrb.GetPosX());
+ Pkt.WriteInt((int) a_ExpOrb.GetPosY());
+ Pkt.WriteInt((int) a_ExpOrb.GetPosZ());
+ Pkt.WriteShort(a_ExpOrb.GetReward());
+}
+
+
+
+
+
void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8
{
cPacketizer Pkt(*this, 0x29); // Sound Effect packet
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 449727854..6b897fd57 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -73,6 +73,7 @@ public:
virtual void SendRespawn (void) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
virtual void SendExperience (void) override;
+ virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 64bd83075..489149d74 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -476,6 +476,16 @@ void cProtocolRecognizer::SendExperience(void)
+void cProtocolRecognizer::SendExperienceOrb(const cExpOrb & a_ExpOrb)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendExperienceOrb(a_ExpOrb);
+}
+
+
+
+
+
void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
{
ASSERT(m_Protocol != NULL);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 03f48fb35..9ca0c1c88 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -98,6 +98,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
+ virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
diff --git a/src/World.cpp b/src/World.cpp
index 96b08a8ec..fb8ee0cb3 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -13,6 +13,7 @@
#include "OSSupport/Timer.h"
// Entities (except mobs):
+#include "Entities/ExpOrb.h"
#include "Entities/Pickup.h"
#include "Entities/Player.h"
#include "Entities/TNTEntity.h"
@@ -1561,6 +1562,17 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
+int cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward)
+{
+ cExpOrb * ExpOrb = new cExpOrb(a_X, a_Y, a_Z, a_Reward);
+ ExpOrb->Initialize(this);
+ return ExpOrb->GetUniqueID();
+}
+
+
+
+
+
void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec, double a_InitialVelocityCoeff)
{
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTimeInSec);
diff --git a/src/World.h b/src/World.h
index d10aa3b78..284e96bbb 100644
--- a/src/World.h
+++ b/src/World.h
@@ -353,6 +353,9 @@ public:
/// Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified:
void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false);
+ /// Spawns an experience orb at the given location with the given reward. It returns the UniqueID of the spawned experience orb.
+ int SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward);
+
/// Spawns a new primed TNT entity at the specified block coords and specified fuse duration. Initial velocity is given based on the relative coefficient provided
void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec, double a_InitialVelocityCoeff = 1);