summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua18
-rw-r--r--VC2008/MCServer.vcproj8
-rw-r--r--source/AllToLua.pkg3
-rw-r--r--source/Bindings.cpp993
-rw-r--r--source/Bindings.h2
-rw-r--r--source/BlockID.h4
-rw-r--r--source/BlockTracer.h4
-rw-r--r--source/ClientHandle.cpp8
-rw-r--r--source/Entities/Entity.cpp49
-rw-r--r--source/Entities/Entity.h5
-rw-r--r--source/Entities/FallingBlock.cpp14
-rw-r--r--source/Entities/FallingBlock.h1
-rw-r--r--source/Entities/Minecart.cpp14
-rw-r--r--source/Entities/Minecart.h1
-rw-r--r--source/Entities/Pickup.cpp14
-rw-r--r--source/Entities/Pickup.h2
-rw-r--r--source/Entities/Player.cpp44
-rw-r--r--source/Entities/Player.h15
-rw-r--r--source/Entities/ProjectileEntity.cpp296
-rw-r--r--source/Entities/ProjectileEntity.h102
-rw-r--r--source/Entities/TNTEntity.cpp14
-rw-r--r--source/Entities/TNTEntity.h1
-rw-r--r--source/Items/ItemBow.h80
-rw-r--r--source/Items/ItemHandler.cpp22
-rw-r--r--source/Items/ItemHandler.h9
-rw-r--r--source/LineBlockTracer.cpp11
-rw-r--r--source/LineBlockTracer.h3
-rw-r--r--source/ManualBindings.cpp6
-rw-r--r--source/Vector3d.h13
-rw-r--r--source/World.cpp28
-rw-r--r--source/World.h4
-rw-r--r--source/WorldStorage/NBTChunkSerializer.cpp67
-rw-r--r--source/WorldStorage/NBTChunkSerializer.h2
-rw-r--r--source/WorldStorage/WSSAnvil.cpp51
-rw-r--r--source/WorldStorage/WSSAnvil.h1
35 files changed, 1529 insertions, 380 deletions
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 599b8a3a3..be16e3465 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -45,6 +45,7 @@ function Initialize(Plugin)
PluginManager:BindCommand("/spidey", "debuggers", HandleSpideyCmd, "- Shoots a line of web blocks until it hits non-air");
PluginManager:BindCommand("/ench", "debuggers", HandleEnchCmd, "- Provides an instant dummy enchantment window");
PluginManager:BindCommand("/fs", "debuggers", HandleFoodStatsCmd, "- Turns regular foodstats message on or off");
+ PluginManager:BindCommand("/arr", "debuggers", HandleArrowCmd, "- Creates an arrow going away from the player");
-- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
@@ -794,6 +795,7 @@ function HandleEnchCmd(a_Split, a_Player)
Wnd:SetProperty(0, 10);
Wnd:SetProperty(1, 15);
Wnd:SetProperty(2, 25);
+ return true;
end
@@ -802,6 +804,22 @@ end
function HandleFoodStatsCmd(a_Split, a_Player)
g_ShowFoodStats = not(g_ShowFoodStats);
+ return true;
+end
+
+
+
+
+
+function HandleArrowCmd(a_Split, a_Player)
+ local World = a_Player:GetWorld();
+ local Pos = a_Player:GetEyePosition();
+ local Speed = a_Player:GetLookVector();
+ Speed:Normalize();
+ Pos = Pos + Speed;
+
+ World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkArrow, a_Player, Speed * 10);
+ return true;
end
diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index 686eba48a..fb82c3520 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -1160,6 +1160,10 @@
>
</File>
<File
+ RelativePath="..\source\Entities\ProjectileEntity.cpp"
+ >
+ </File>
+ <File
RelativePath="..\source\Entities\ProjectileEntity.h"
>
</File>
@@ -2236,6 +2240,10 @@
>
</File>
<File
+ RelativePath="..\source\Items\ItemBow.h"
+ >
+ </File>
+ <File
RelativePath="..\source\Items\ItemBrewingStand.h"
>
</File>
diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg
index 98c58ed0a..8d87be307 100644
--- a/source/AllToLua.pkg
+++ b/source/AllToLua.pkg
@@ -27,6 +27,8 @@ $cfile "ClientHandle.h"
$cfile "Entities/Entity.h"
$cfile "Entities/Pawn.h"
$cfile "Entities/Player.h"
+$cfile "Entities/Pickup.h"
+$cfile "Entities/ProjectileEntity.h"
$cfile "PluginManager.h"
$cfile "Plugin.h"
$cfile "PluginLua.h"
@@ -45,7 +47,6 @@ $cfile "BlockEntities/DropperEntity.h"
$cfile "BlockEntities/FurnaceEntity.h"
$cfile "WebAdmin.h"
$cfile "WebPlugin.h"
-$cfile "Entities/Pickup.h"
$cfile "Root.h"
$cfile "Vector3f.h"
$cfile "Vector3d.h"
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index a9964b1a1..af3e83dda 100644
--- a/source/Bindings.cpp
+++ b/source/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 08/27/13 08:55:56.
+** Generated automatically by tolua++-1.0.92 on 08/30/13 14:30:24.
*/
#ifndef __cplusplus
@@ -27,6 +27,8 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
#include "Entities/Entity.h"
#include "Entities/Pawn.h"
#include "Entities/Player.h"
+#include "Entities/Pickup.h"
+#include "Entities/ProjectileEntity.h"
#include "PluginManager.h"
#include "Plugin.h"
#include "PluginLua.h"
@@ -45,7 +47,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
#include "BlockEntities/FurnaceEntity.h"
#include "WebAdmin.h"
#include "WebPlugin.h"
-#include "Entities/Pickup.h"
#include "Root.h"
#include "Vector3f.h"
#include "Vector3d.h"
@@ -203,47 +204,49 @@ static int tolua_collect_Vector3d (lua_State* tolua_S)
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"TakeDamageInfo");
+ tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cCraftingRecipe");
tolua_usertype(tolua_S,"cPlugin");
+ tolua_usertype(tolua_S,"cMonster");
tolua_usertype(tolua_S,"cStringMap");
tolua_usertype(tolua_S,"cItemGrid");
tolua_usertype(tolua_S,"cBlockArea");
tolua_usertype(tolua_S,"cEnchantments");
tolua_usertype(tolua_S,"cLuaWindow");
- tolua_usertype(tolua_S,"cServer");
+ tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cRoot");
- tolua_usertype(tolua_S,"cDropperEntity");
+ tolua_usertype(tolua_S,"cWindow");
tolua_usertype(tolua_S,"std::vector<cIniFile::key>");
- tolua_usertype(tolua_S,"cMonster");
+ tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"std::vector<std::string>");
- tolua_usertype(tolua_S,"cWindow");
+ tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cClientHandle");
tolua_usertype(tolua_S,"cChunkDesc");
tolua_usertype(tolua_S,"cFurnaceRecipe");
- tolua_usertype(tolua_S,"cCraftingGrid");
- tolua_usertype(tolua_S,"cChatColor");
- tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cTracer");
+ tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"Vector3i");
- tolua_usertype(tolua_S,"cInventory");
+ tolua_usertype(tolua_S,"cWorld");
+ tolua_usertype(tolua_S,"cEntity");
+ tolua_usertype(tolua_S,"cCraftingRecipes");
tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"Vector3f");
- tolua_usertype(tolua_S,"cCraftingRecipes");
+ tolua_usertype(tolua_S,"cArrowEntity");
tolua_usertype(tolua_S,"cDropSpenserEntity");
- tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"cWebPlugin");
+ tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"cChestEntity");
tolua_usertype(tolua_S,"cDispenserEntity");
- tolua_usertype(tolua_S,"cWebAdmin");
+ tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"cBlockEntity");
- tolua_usertype(tolua_S,"cCriticalSection");
+ tolua_usertype(tolua_S,"cItemGrid::cListener");
tolua_usertype(tolua_S,"HTTPTemplateRequest");
- tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"HTTPRequest");
tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cFurnaceEntity");
+ tolua_usertype(tolua_S,"cDropperEntity");
tolua_usertype(tolua_S,"cLineBlockTracer");
tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cIniFile");
@@ -253,8 +256,8 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cPlayer");
tolua_usertype(tolua_S,"cGroupManager");
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
- tolua_usertype(tolua_S,"cEntity");
- tolua_usertype(tolua_S,"cItemGrid::cListener");
+ tolua_usertype(tolua_S,"cCriticalSection");
+ tolua_usertype(tolua_S,"cProjectileEntity");
tolua_usertype(tolua_S,"cPluginLua");
tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"Vector3d");
@@ -9358,6 +9361,595 @@ static int tolua_AllToLua_cPlayer_IsSubmerged00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: new of class cPickup */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_new00
+static int tolua_AllToLua_cPickup_new00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cPickup",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_isvaluenil(tolua_S,5,&tolua_err) || !tolua_isusertype(tolua_S,5,"const cItem",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,6,1,&tolua_err) ||
+ !tolua_isnumber(tolua_S,7,1,&tolua_err) ||
+ !tolua_isnumber(tolua_S,8,1,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,9,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ int a_MicroPosX = ((int) tolua_tonumber(tolua_S,2,0));
+ int a_MicroPosY = ((int) tolua_tonumber(tolua_S,3,0));
+ int a_MicroPosZ = ((int) tolua_tonumber(tolua_S,4,0));
+ const cItem* a_Item = ((const cItem*) tolua_tousertype(tolua_S,5,0));
+ float a_SpeedX = ((float) tolua_tonumber(tolua_S,6,0.f));
+ float a_SpeedY = ((float) tolua_tonumber(tolua_S,7,0.f));
+ float a_SpeedZ = ((float) tolua_tonumber(tolua_S,8,0.f));
+ {
+ cPickup* tolua_ret = (cPickup*) Mtolua_new((cPickup)(a_MicroPosX,a_MicroPosY,a_MicroPosZ,*a_Item,a_SpeedX,a_SpeedY,a_SpeedZ));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPickup");
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cPickup */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_new00_local
+static int tolua_AllToLua_cPickup_new00_local(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cPickup",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_isvaluenil(tolua_S,5,&tolua_err) || !tolua_isusertype(tolua_S,5,"const cItem",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,6,1,&tolua_err) ||
+ !tolua_isnumber(tolua_S,7,1,&tolua_err) ||
+ !tolua_isnumber(tolua_S,8,1,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,9,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ int a_MicroPosX = ((int) tolua_tonumber(tolua_S,2,0));
+ int a_MicroPosY = ((int) tolua_tonumber(tolua_S,3,0));
+ int a_MicroPosZ = ((int) tolua_tonumber(tolua_S,4,0));
+ const cItem* a_Item = ((const cItem*) tolua_tousertype(tolua_S,5,0));
+ float a_SpeedX = ((float) tolua_tonumber(tolua_S,6,0.f));
+ float a_SpeedY = ((float) tolua_tonumber(tolua_S,7,0.f));
+ float a_SpeedZ = ((float) tolua_tonumber(tolua_S,8,0.f));
+ {
+ cPickup* tolua_ret = (cPickup*) Mtolua_new((cPickup)(a_MicroPosX,a_MicroPosY,a_MicroPosZ,*a_Item,a_SpeedX,a_SpeedY,a_SpeedZ));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPickup");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetItem of class cPickup */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_GetItem00
+static int tolua_AllToLua_cPickup_GetItem00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cPickup",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cPickup* self = (cPickup*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetItem'", NULL);
+#endif
+ {
+ cItem& tolua_ret = (cItem&) self->GetItem();
+ tolua_pushusertype(tolua_S,(void*)&tolua_ret,"cItem");
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetItem'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: CollectedBy of class cPickup */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_CollectedBy00
+static int tolua_AllToLua_cPickup_CollectedBy00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cPickup",0,&tolua_err) ||
+ !tolua_isusertype(tolua_S,2,"cPlayer",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cPickup* self = (cPickup*) tolua_tousertype(tolua_S,1,0);
+ cPlayer* a_Dest = ((cPlayer*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'CollectedBy'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->CollectedBy(a_Dest);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'CollectedBy'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetAge of class cPickup */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_GetAge00
+static int tolua_AllToLua_cPickup_GetAge00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cPickup",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cPickup* self = (const cPickup*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetAge'", NULL);
+#endif
+ {
+ int tolua_ret = (int) self->GetAge();
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetAge'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsCollected of class cPickup */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_IsCollected00
+static int tolua_AllToLua_cPickup_IsCollected00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cPickup",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cPickup* self = (const cPickup*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsCollected'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsCollected();
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'IsCollected'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetProjectileKind of class cProjectileEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cProjectileEntity_GetProjectileKind00
+static int tolua_AllToLua_cProjectileEntity_GetProjectileKind00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cProjectileEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cProjectileEntity* self = (const cProjectileEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetProjectileKind'", NULL);
+#endif
+ {
+ cProjectileEntity::eKind tolua_ret = (cProjectileEntity::eKind) self->GetProjectileKind();
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetProjectileKind'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetCreator of class cProjectileEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cProjectileEntity_GetCreator00
+static int tolua_AllToLua_cProjectileEntity_GetCreator00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cProjectileEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cProjectileEntity* self = (cProjectileEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetCreator'", NULL);
+#endif
+ {
+ cEntity* tolua_ret = (cEntity*) self->GetCreator();
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cEntity");
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetCreator'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetMCAClassName of class cProjectileEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cProjectileEntity_GetMCAClassName00
+static int tolua_AllToLua_cProjectileEntity_GetMCAClassName00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cProjectileEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cProjectileEntity* self = (const cProjectileEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetMCAClassName'", NULL);
+#endif
+ {
+ AString tolua_ret = (AString) self->GetMCAClassName();
+ tolua_pushcppstring(tolua_S,(const char*)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetMCAClassName'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsInGround of class cProjectileEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cProjectileEntity_IsInGround00
+static int tolua_AllToLua_cProjectileEntity_IsInGround00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cProjectileEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cProjectileEntity* self = (const cProjectileEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsInGround'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsInGround();
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'IsInGround'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: PosFromPlayerPos of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_PosFromPlayerPos00
+static int tolua_AllToLua_cArrowEntity_PosFromPlayerPos00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cArrowEntity",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cPlayer",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cPlayer* a_Player = ((const cPlayer*) tolua_tousertype(tolua_S,2,0));
+ {
+ Vector3d tolua_ret = (Vector3d) cArrowEntity::PosFromPlayerPos(*a_Player);
+ {
+#ifdef __cplusplus
+ void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
+ tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#else
+ void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
+ tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#endif
+ }
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'PosFromPlayerPos'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SpeedFromPlayerLook of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_SpeedFromPlayerLook00
+static int tolua_AllToLua_cArrowEntity_SpeedFromPlayerLook00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cArrowEntity",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cPlayer",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cPlayer* a_Player = ((const cPlayer*) tolua_tousertype(tolua_S,2,0));
+ double a_Force = ((double) tolua_tonumber(tolua_S,3,0));
+ {
+ Vector3d tolua_ret = (Vector3d) cArrowEntity::SpeedFromPlayerLook(*a_Player,a_Force);
+ {
+#ifdef __cplusplus
+ void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
+ tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#else
+ void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
+ tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#endif
+ }
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SpeedFromPlayerLook'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetPickupState of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_GetPickupState00
+static int tolua_AllToLua_cArrowEntity_GetPickupState00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cArrowEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cArrowEntity* self = (const cArrowEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetPickupState'", NULL);
+#endif
+ {
+ cArrowEntity::ePickupState tolua_ret = (cArrowEntity::ePickupState) self->GetPickupState();
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetPickupState'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetPickupState of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_SetPickupState00
+static int tolua_AllToLua_cArrowEntity_SetPickupState00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cArrowEntity",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cArrowEntity* self = (cArrowEntity*) tolua_tousertype(tolua_S,1,0);
+ cArrowEntity::ePickupState a_PickupState = ((cArrowEntity::ePickupState) (int) tolua_tonumber(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetPickupState'", NULL);
+#endif
+ {
+ self->SetPickupState(a_PickupState);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetPickupState'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetDamageCoeff of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_GetDamageCoeff00
+static int tolua_AllToLua_cArrowEntity_GetDamageCoeff00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cArrowEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cArrowEntity* self = (const cArrowEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetDamageCoeff'", NULL);
+#endif
+ {
+ double tolua_ret = (double) self->GetDamageCoeff();
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetDamageCoeff'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetDamageCoeff of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_SetDamageCoeff00
+static int tolua_AllToLua_cArrowEntity_SetDamageCoeff00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cArrowEntity",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cArrowEntity* self = (cArrowEntity*) tolua_tousertype(tolua_S,1,0);
+ double a_DamageCoeff = ((double) tolua_tonumber(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetDamageCoeff'", NULL);
+#endif
+ {
+ self->SetDamageCoeff(a_DamageCoeff);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetDamageCoeff'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: CanPickup of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_CanPickup00
+static int tolua_AllToLua_cArrowEntity_CanPickup00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cArrowEntity",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cPlayer",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cArrowEntity* self = (const cArrowEntity*) tolua_tousertype(tolua_S,1,0);
+ const cPlayer* a_Player = ((const cPlayer*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'CanPickup'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->CanPickup(*a_Player);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'CanPickup'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: Get of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_Get00
static int tolua_AllToLua_cPluginManager_Get00(lua_State* tolua_S)
@@ -12728,6 +13320,50 @@ static int tolua_AllToLua_cWorld_SpawnMob00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: CreateProjectile of class cWorld */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_CreateProjectile00
+static int tolua_AllToLua_cWorld_CreateProjectile00(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_isusertype(tolua_S,6,"cEntity",0,&tolua_err) ||
+ !tolua_isusertype(tolua_S,7,"const Vector3d",1,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,8,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0);
+ double a_PosX = ((double) tolua_tonumber(tolua_S,2,0));
+ double a_PosY = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_PosZ = ((double) tolua_tonumber(tolua_S,4,0));
+ cProjectileEntity::eKind a_Kind = ((cProjectileEntity::eKind) (int) tolua_tonumber(tolua_S,5,0));
+ cEntity* a_Creator = ((cEntity*) tolua_tousertype(tolua_S,6,0));
+ const Vector3d* a_Speed = ((const Vector3d*) tolua_tousertype(tolua_S,7,NULL));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'CreateProjectile'", NULL);
+#endif
+ {
+ int tolua_ret = (int) self->CreateProjectile(a_PosX,a_PosY,a_PosZ,a_Kind,a_Creator,a_Speed);
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'CreateProjectile'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: Clear of class cInventory */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cInventory_Clear00
static int tolua_AllToLua_cInventory_Clear00(lua_State* tolua_S)
@@ -18065,221 +18701,6 @@ static int tolua_AllToLua_cWebPlugin_SafeString00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
-/* method: new of class cPickup */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_new00
-static int tolua_AllToLua_cPickup_new00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertable(tolua_S,1,"cPickup",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_isvaluenil(tolua_S,5,&tolua_err) || !tolua_isusertype(tolua_S,5,"const cItem",0,&tolua_err)) ||
- !tolua_isnumber(tolua_S,6,1,&tolua_err) ||
- !tolua_isnumber(tolua_S,7,1,&tolua_err) ||
- !tolua_isnumber(tolua_S,8,1,&tolua_err) ||
- !tolua_isnoobj(tolua_S,9,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- int a_MicroPosX = ((int) tolua_tonumber(tolua_S,2,0));
- int a_MicroPosY = ((int) tolua_tonumber(tolua_S,3,0));
- int a_MicroPosZ = ((int) tolua_tonumber(tolua_S,4,0));
- const cItem* a_Item = ((const cItem*) tolua_tousertype(tolua_S,5,0));
- float a_SpeedX = ((float) tolua_tonumber(tolua_S,6,0.f));
- float a_SpeedY = ((float) tolua_tonumber(tolua_S,7,0.f));
- float a_SpeedZ = ((float) tolua_tonumber(tolua_S,8,0.f));
- {
- cPickup* tolua_ret = (cPickup*) Mtolua_new((cPickup)(a_MicroPosX,a_MicroPosY,a_MicroPosZ,*a_Item,a_SpeedX,a_SpeedY,a_SpeedZ));
- tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPickup");
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: new_local of class cPickup */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_new00_local
-static int tolua_AllToLua_cPickup_new00_local(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertable(tolua_S,1,"cPickup",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_isvaluenil(tolua_S,5,&tolua_err) || !tolua_isusertype(tolua_S,5,"const cItem",0,&tolua_err)) ||
- !tolua_isnumber(tolua_S,6,1,&tolua_err) ||
- !tolua_isnumber(tolua_S,7,1,&tolua_err) ||
- !tolua_isnumber(tolua_S,8,1,&tolua_err) ||
- !tolua_isnoobj(tolua_S,9,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- int a_MicroPosX = ((int) tolua_tonumber(tolua_S,2,0));
- int a_MicroPosY = ((int) tolua_tonumber(tolua_S,3,0));
- int a_MicroPosZ = ((int) tolua_tonumber(tolua_S,4,0));
- const cItem* a_Item = ((const cItem*) tolua_tousertype(tolua_S,5,0));
- float a_SpeedX = ((float) tolua_tonumber(tolua_S,6,0.f));
- float a_SpeedY = ((float) tolua_tonumber(tolua_S,7,0.f));
- float a_SpeedZ = ((float) tolua_tonumber(tolua_S,8,0.f));
- {
- cPickup* tolua_ret = (cPickup*) Mtolua_new((cPickup)(a_MicroPosX,a_MicroPosY,a_MicroPosZ,*a_Item,a_SpeedX,a_SpeedY,a_SpeedZ));
- tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPickup");
- tolua_register_gc(tolua_S,lua_gettop(tolua_S));
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: GetItem of class cPickup */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_GetItem00
-static int tolua_AllToLua_cPickup_GetItem00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cPickup",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cPickup* self = (cPickup*) tolua_tousertype(tolua_S,1,0);
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetItem'", NULL);
-#endif
- {
- cItem& tolua_ret = (cItem&) self->GetItem();
- tolua_pushusertype(tolua_S,(void*)&tolua_ret,"cItem");
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'GetItem'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: CollectedBy of class cPickup */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_CollectedBy00
-static int tolua_AllToLua_cPickup_CollectedBy00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cPickup",0,&tolua_err) ||
- !tolua_isusertype(tolua_S,2,"cPlayer",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,3,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cPickup* self = (cPickup*) tolua_tousertype(tolua_S,1,0);
- cPlayer* a_Dest = ((cPlayer*) tolua_tousertype(tolua_S,2,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'CollectedBy'", NULL);
-#endif
- {
- bool tolua_ret = (bool) self->CollectedBy(a_Dest);
- tolua_pushboolean(tolua_S,(bool)tolua_ret);
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'CollectedBy'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: GetAge of class cPickup */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_GetAge00
-static int tolua_AllToLua_cPickup_GetAge00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"const cPickup",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- const cPickup* self = (const cPickup*) tolua_tousertype(tolua_S,1,0);
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetAge'", NULL);
-#endif
- {
- int tolua_ret = (int) self->GetAge();
- tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'GetAge'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: IsCollected of class cPickup */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_IsCollected00
-static int tolua_AllToLua_cPickup_IsCollected00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"const cPickup",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- const cPickup* self = (const cPickup*) tolua_tousertype(tolua_S,1,0);
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsCollected'", NULL);
-#endif
- {
- bool tolua_ret = (bool) self->IsCollected();
- tolua_pushboolean(tolua_S,(bool)tolua_ret);
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'IsCollected'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
/* get function: m_PrimaryServerVersion of class cRoot */
#ifndef TOLUA_DISABLE_tolua_get_cRoot_m_PrimaryServerVersion
static int tolua_get_cRoot_m_PrimaryServerVersion(lua_State* tolua_S)
@@ -20577,6 +20998,50 @@ tolua_lerror:
}
#endif //#ifndef TOLUA_DISABLE
+/* method: operator/ of class Vector3d */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_Vector3d__div00
+static int tolua_AllToLua_Vector3d__div00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const Vector3d",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const Vector3d* self = (const Vector3d*) tolua_tousertype(tolua_S,1,0);
+ const double f = ((const double) tolua_tonumber(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'operator/'", NULL);
+#endif
+ {
+ Vector3d tolua_ret = (Vector3d) self->operator/(f);
+ {
+#ifdef __cplusplus
+ void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
+ tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#else
+ void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
+ tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#endif
+ }
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function '.div'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* get function: x of class Vector3d */
#ifndef TOLUA_DISABLE_tolua_get_Vector3d_x
static int tolua_get_Vector3d_x(lua_State* tolua_S)
@@ -27606,6 +28071,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"E_ITEM_WAIT_DISC",E_ITEM_WAIT_DISC);
tolua_constant(tolua_S,"E_ITEM_LAST_DISC_PLUS_ONE",E_ITEM_LAST_DISC_PLUS_ONE);
tolua_constant(tolua_S,"E_ITEM_LAST_DISC",E_ITEM_LAST_DISC);
+ tolua_constant(tolua_S,"E_ITEM_LAST",E_ITEM_LAST);
tolua_constant(tolua_S,"E_META_CHEST_FACING_ZM",E_META_CHEST_FACING_ZM);
tolua_constant(tolua_S,"E_META_CHEST_FACING_ZP",E_META_CHEST_FACING_ZP);
tolua_constant(tolua_S,"E_META_CHEST_FACING_XM",E_META_CHEST_FACING_XM);
@@ -28009,10 +28475,11 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"etPlayer",cEntity::etPlayer);
tolua_constant(tolua_S,"etPickup",cEntity::etPickup);
tolua_constant(tolua_S,"etMonster",cEntity::etMonster);
- tolua_constant(tolua_S,"etMob",cEntity::etMob);
tolua_constant(tolua_S,"etFallingBlock",cEntity::etFallingBlock);
tolua_constant(tolua_S,"etMinecart",cEntity::etMinecart);
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);
@@ -28174,6 +28641,50 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"IsSwimming",tolua_AllToLua_cPlayer_IsSwimming00);
tolua_function(tolua_S,"IsSubmerged",tolua_AllToLua_cPlayer_IsSubmerged00);
tolua_endmodule(tolua_S);
+ #ifdef __cplusplus
+ tolua_cclass(tolua_S,"cPickup","cPickup","cEntity",tolua_collect_cPickup);
+ #else
+ tolua_cclass(tolua_S,"cPickup","cPickup","cEntity",NULL);
+ #endif
+ tolua_beginmodule(tolua_S,"cPickup");
+ tolua_function(tolua_S,"new",tolua_AllToLua_cPickup_new00);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cPickup_new00_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cPickup_new00_local);
+ tolua_function(tolua_S,"GetItem",tolua_AllToLua_cPickup_GetItem00);
+ tolua_function(tolua_S,"CollectedBy",tolua_AllToLua_cPickup_CollectedBy00);
+ tolua_function(tolua_S,"GetAge",tolua_AllToLua_cPickup_GetAge00);
+ tolua_function(tolua_S,"IsCollected",tolua_AllToLua_cPickup_IsCollected00);
+ tolua_endmodule(tolua_S);
+ tolua_cclass(tolua_S,"cProjectileEntity","cProjectileEntity","cEntity",NULL);
+ tolua_beginmodule(tolua_S,"cProjectileEntity");
+ tolua_constant(tolua_S,"pkArrow",cProjectileEntity::pkArrow);
+ tolua_constant(tolua_S,"pkSnowball",cProjectileEntity::pkSnowball);
+ tolua_constant(tolua_S,"pkEgg",cProjectileEntity::pkEgg);
+ tolua_constant(tolua_S,"pkGhastFireball",cProjectileEntity::pkGhastFireball);
+ tolua_constant(tolua_S,"pkFireCharge",cProjectileEntity::pkFireCharge);
+ tolua_constant(tolua_S,"pkEnderPearl",cProjectileEntity::pkEnderPearl);
+ tolua_constant(tolua_S,"pkExpBottle",cProjectileEntity::pkExpBottle);
+ tolua_constant(tolua_S,"pkSplashPotion",cProjectileEntity::pkSplashPotion);
+ tolua_constant(tolua_S,"pkWitherSkull",cProjectileEntity::pkWitherSkull);
+ tolua_constant(tolua_S,"pkFishingFloat",cProjectileEntity::pkFishingFloat);
+ tolua_function(tolua_S,"GetProjectileKind",tolua_AllToLua_cProjectileEntity_GetProjectileKind00);
+ tolua_function(tolua_S,"GetCreator",tolua_AllToLua_cProjectileEntity_GetCreator00);
+ tolua_function(tolua_S,"GetMCAClassName",tolua_AllToLua_cProjectileEntity_GetMCAClassName00);
+ tolua_function(tolua_S,"IsInGround",tolua_AllToLua_cProjectileEntity_IsInGround00);
+ tolua_endmodule(tolua_S);
+ tolua_cclass(tolua_S,"cArrowEntity","cArrowEntity","cProjectileEntity",NULL);
+ tolua_beginmodule(tolua_S,"cArrowEntity");
+ tolua_constant(tolua_S,"psNoPickup",cArrowEntity::psNoPickup);
+ tolua_constant(tolua_S,"psInSurvivalOrCreative",cArrowEntity::psInSurvivalOrCreative);
+ tolua_constant(tolua_S,"psInCreative",cArrowEntity::psInCreative);
+ tolua_function(tolua_S,"PosFromPlayerPos",tolua_AllToLua_cArrowEntity_PosFromPlayerPos00);
+ tolua_function(tolua_S,"SpeedFromPlayerLook",tolua_AllToLua_cArrowEntity_SpeedFromPlayerLook00);
+ tolua_function(tolua_S,"GetPickupState",tolua_AllToLua_cArrowEntity_GetPickupState00);
+ tolua_function(tolua_S,"SetPickupState",tolua_AllToLua_cArrowEntity_SetPickupState00);
+ tolua_function(tolua_S,"GetDamageCoeff",tolua_AllToLua_cArrowEntity_GetDamageCoeff00);
+ tolua_function(tolua_S,"SetDamageCoeff",tolua_AllToLua_cArrowEntity_SetDamageCoeff00);
+ tolua_function(tolua_S,"CanPickup",tolua_AllToLua_cArrowEntity_CanPickup00);
+ tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cPluginManager","cPluginManager","",NULL);
tolua_beginmodule(tolua_S,"cPluginManager");
tolua_constant(tolua_S,"HOOK_BLOCK_TO_PICKUPS",cPluginManager::HOOK_BLOCK_TO_PICKUPS);
@@ -28336,6 +28847,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetMaxCactusHeight",tolua_AllToLua_cWorld_GetMaxCactusHeight00);
tolua_function(tolua_S,"IsBlockDirectlyWatered",tolua_AllToLua_cWorld_IsBlockDirectlyWatered00);
tolua_function(tolua_S,"SpawnMob",tolua_AllToLua_cWorld_SpawnMob00);
+ tolua_function(tolua_S,"CreateProjectile",tolua_AllToLua_cWorld_CreateProjectile00);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cInventory","cInventory","cItemGrid::cListener",NULL);
tolua_beginmodule(tolua_S,"cInventory");
@@ -28639,20 +29151,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"HandleWebRequest",tolua_AllToLua_cWebPlugin_HandleWebRequest00);
tolua_function(tolua_S,"SafeString",tolua_AllToLua_cWebPlugin_SafeString00);
tolua_endmodule(tolua_S);
- #ifdef __cplusplus
- tolua_cclass(tolua_S,"cPickup","cPickup","cEntity",tolua_collect_cPickup);
- #else
- tolua_cclass(tolua_S,"cPickup","cPickup","cEntity",NULL);
- #endif
- tolua_beginmodule(tolua_S,"cPickup");
- tolua_function(tolua_S,"new",tolua_AllToLua_cPickup_new00);
- tolua_function(tolua_S,"new_local",tolua_AllToLua_cPickup_new00_local);
- tolua_function(tolua_S,".call",tolua_AllToLua_cPickup_new00_local);
- tolua_function(tolua_S,"GetItem",tolua_AllToLua_cPickup_GetItem00);
- tolua_function(tolua_S,"CollectedBy",tolua_AllToLua_cPickup_CollectedBy00);
- tolua_function(tolua_S,"GetAge",tolua_AllToLua_cPickup_GetAge00);
- tolua_function(tolua_S,"IsCollected",tolua_AllToLua_cPickup_IsCollected00);
- tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cRoot","cRoot","",NULL);
tolua_beginmodule(tolua_S,"cRoot");
tolua_variable(tolua_S,"m_PrimaryServerVersion",tolua_get_cRoot_m_PrimaryServerVersion,tolua_set_cRoot_m_PrimaryServerVersion);
@@ -28749,6 +29247,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,".sub",tolua_AllToLua_Vector3d__sub01);
tolua_function(tolua_S,".mul",tolua_AllToLua_Vector3d__mul00);
tolua_function(tolua_S,".mul",tolua_AllToLua_Vector3d__mul01);
+ tolua_function(tolua_S,".div",tolua_AllToLua_Vector3d__div00);
tolua_variable(tolua_S,"x",tolua_get_Vector3d_x,tolua_set_Vector3d_x);
tolua_variable(tolua_S,"y",tolua_get_Vector3d_y,tolua_set_Vector3d_y);
tolua_variable(tolua_S,"z",tolua_get_Vector3d_z,tolua_set_Vector3d_z);
diff --git a/source/Bindings.h b/source/Bindings.h
index 4c68ffbe9..e5b7e0f76 100644
--- a/source/Bindings.h
+++ b/source/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 08/27/13 08:55:57.
+** Generated automatically by tolua++-1.0.92 on 08/30/13 14:30:25.
*/
/* Exported function */
diff --git a/source/BlockID.h b/source/BlockID.h
index 0eb3df96d..de8335e85 100644
--- a/source/BlockID.h
+++ b/source/BlockID.h
@@ -367,7 +367,9 @@ enum ENUM_ITEM_ID
// Keep these two as the last values of the disc list, without a number - they will get their correct number assigned automagically by C++
// IsValidItem() depends on this!
E_ITEM_LAST_DISC_PLUS_ONE, ///< Useless, really, but needs to be present for the following value
- E_ITEM_LAST_DISC = E_ITEM_LAST_DISC_PLUS_ONE - 1 ///< Maximum disc itemtype number used
+ E_ITEM_LAST_DISC = E_ITEM_LAST_DISC_PLUS_ONE - 1, ///< Maximum disc itemtype number used
+
+ E_ITEM_LAST = E_ITEM_LAST_DISC, ///< Maximum valid ItemType
};
diff --git a/source/BlockTracer.h b/source/BlockTracer.h
index 6d67f1052..d0a34811d 100644
--- a/source/BlockTracer.h
+++ b/source/BlockTracer.h
@@ -31,12 +31,12 @@ public:
/** Called on each block encountered along the path, including the first block (path start)
When this callback returns true, the tracing is aborted.
*/
- virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) = 0;
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
When this callback returns true, the tracing is aborted.
*/
- virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) { return false; }
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) { return false; }
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
The coords specify the exact point at which the path exited the world.
diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp
index bed9fab92..555ecb952 100644
--- a/source/ClientHandle.cpp
+++ b/source/ClientHandle.cpp
@@ -576,8 +576,8 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch
// A plugin doesn't agree with the action. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return;
}
+ ItemHandler->OnItemShoot(m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
}
- LOGINFO("%s: Status SHOOT not implemented", __FUNCTION__);
return;
}
@@ -790,16 +790,16 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, c
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
- cBlockHandler * Handler = cBlockHandler::GetBlockHandler(BlockType);
+ cBlockHandler * BlockHandler = cBlockHandler::GetBlockHandler(BlockType);
- if (Handler->IsUseable() && !m_Player->IsCrouched())
+ if (BlockHandler->IsUseable() && !m_Player->IsCrouched())
{
if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
{
// A plugin doesn't agree with using the block, abort
return;
}
- Handler->OnUse(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
+ BlockHandler->OnUse(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
return;
}
diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp
index 19a65ef4e..b936d8d73 100644
--- a/source/Entities/Entity.cpp
+++ b/source/Entities/Entity.cpp
@@ -144,6 +144,10 @@ bool cEntity::Initialize(cWorld * a_World)
m_World->AddEntity(this);
cPluginManager::Get()->CallHookSpawnedEntity(*a_World, *this);
+
+ // Spawn the entity on the clients:
+ a_World->BroadcastSpawnEntity(*this);
+
return true;
}
@@ -477,7 +481,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
// TODO Add collision detection with entities.
- a_Dt /= 1000;
+ a_Dt /= 1000; // Convert from msec to sec
Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ());
Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ());
int BlockX = (int) floor(NextPos.x);
@@ -493,7 +497,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
// Make sure we got the correct chunk and a valid one. No one ever knows...
- cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX,BlockZ);
+ cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
if (NextChunk != NULL)
{
int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
@@ -512,11 +516,12 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
else
{
- //Push out entity.
+ // Push out entity.
m_bOnGround = true;
NextPos.y += 0.2;
- LOGD("Entity #%d (%s) is inside a block at {%d,%d,%d}",
- m_UniqueID, GetClass(), BlockX, BlockY, BlockZ);
+ LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
+ m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
+ );
}
if (!m_bOnGround)
@@ -524,34 +529,40 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
float fallspeed;
if (IsBlockWater(BlockIn))
{
- fallspeed = -3.0f * a_Dt; //Fall slower in water.
+ fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
}
else if (BlockIn == E_BLOCK_COBWEB)
{
- NextSpeed.y *= 0.05; //Reduce overall falling speed
- fallspeed = 0; //No falling.
+ NextSpeed.y *= 0.05; // Reduce overall falling speed
+ fallspeed = 0; // No falling.
}
else
{
- //Normal gravity
+ // Normal gravity
fallspeed = m_Gravity * a_Dt;
}
NextSpeed.y += fallspeed;
}
else
{
- //Friction
+ // Friction
if (NextSpeed.SqrLength() > 0.0004f)
{
- NextSpeed.x *= 0.7f/(1+a_Dt);
- if ( fabs(NextSpeed.x) < 0.05 ) NextSpeed.x = 0;
- NextSpeed.z *= 0.7f/(1+a_Dt);
- if ( fabs(NextSpeed.z) < 0.05 ) NextSpeed.z = 0;
+ NextSpeed.x *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.x) < 0.05)
+ {
+ NextSpeed.x = 0;
+ }
+ NextSpeed.z *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.z) < 0.05)
+ {
+ NextSpeed.z = 0;
+ }
}
}
- //Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
- //might have different speed modifiers according to terrain.
+ // Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
+ // might have different speed modifiers according to terrain.
if (BlockIn == E_BLOCK_COBWEB)
{
NextSpeed.x *= 0.25;
@@ -1028,9 +1039,9 @@ void cEntity::SetMass(double a_Mass)
}
else
{
- //Make sure that mass is not zero. 1g is the default because we
- //have to choose a number. It's perfectly legal to have a mass
- //less than 1g as long as is NOT equal or less than zero.
+ // Make sure that mass is not zero. 1g is the default because we
+ // have to choose a number. It's perfectly legal to have a mass
+ // less than 1g as long as is NOT equal or less than zero.
m_Mass = 0.001;
}
}
diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h
index 7a070a5dd..f407cd2c1 100644
--- a/source/Entities/Entity.h
+++ b/source/Entities/Entity.h
@@ -90,12 +90,13 @@ public:
etPlayer,
etPickup,
etMonster,
- etMob = etMonster, // DEPRECATED, use etMonster instead!
etFallingBlock,
etMinecart,
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,
@@ -162,7 +163,7 @@ public:
void SetPosY (double a_PosY);
void SetPosZ (double a_PosZ);
void SetPosition(double a_PosX, double a_PosY, double a_PosZ);
- void SetPosition(const Vector3d & a_Pos) { SetPosition(a_Pos.x,a_Pos.y,a_Pos.z);}
+ void SetPosition(const Vector3d & a_Pos) { SetPosition(a_Pos.x, a_Pos.y, a_Pos.z); }
void SetRot (const Vector3f & a_Rot);
void SetRotation(double a_Rotation);
void SetPitch (double a_Pitch);
diff --git a/source/Entities/FallingBlock.cpp b/source/Entities/FallingBlock.cpp
index 237327975..9fcd9ac80 100644
--- a/source/Entities/FallingBlock.cpp
+++ b/source/Entities/FallingBlock.cpp
@@ -22,20 +22,6 @@ cFallingBlock::cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_Block
-bool cFallingBlock::Initialize(cWorld * a_World)
-{
- if (super::Initialize(a_World))
- {
- a_World->BroadcastSpawnEntity(*this);
- return true;
- }
- return false;
-}
-
-
-
-
-
void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
{
a_ClientHandle.SendSpawnFallingBlock(*this);
diff --git a/source/Entities/FallingBlock.h b/source/Entities/FallingBlock.h
index 13931f061..5ba9909bb 100644
--- a/source/Entities/FallingBlock.h
+++ b/source/Entities/FallingBlock.h
@@ -29,7 +29,6 @@ public:
NIBBLETYPE GetBlockMeta(void) const { return m_BlockMeta; }
// cEntity overrides:
- virtual bool Initialize(cWorld * a_World) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp
index 3e6069237..808579582 100644
--- a/source/Entities/Minecart.cpp
+++ b/source/Entities/Minecart.cpp
@@ -22,20 +22,6 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
-bool cMinecart::Initialize(cWorld * a_World)
-{
- if (super::Initialize(a_World))
- {
- a_World->BroadcastSpawnEntity(*this);
- return true;
- }
- return false;
-}
-
-
-
-
-
void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
{
char Type = 0;
diff --git a/source/Entities/Minecart.h b/source/Entities/Minecart.h
index 91336673d..c1a0e84a0 100644
--- a/source/Entities/Minecart.h
+++ b/source/Entities/Minecart.h
@@ -35,7 +35,6 @@ public:
} ;
// cEntity overrides:
- virtual bool Initialize(cWorld * a_World) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
diff --git a/source/Entities/Pickup.cpp b/source/Entities/Pickup.cpp
index c8f36d503..9b388366a 100644
--- a/source/Entities/Pickup.cpp
+++ b/source/Entities/Pickup.cpp
@@ -40,20 +40,6 @@ cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem
-bool cPickup::Initialize(cWorld * a_World)
-{
- if (super::Initialize(a_World))
- {
- a_World->BroadcastSpawnEntity(*this);
- return true;
- }
- return false;
-}
-
-
-
-
-
void cPickup::SpawnOn(cClientHandle & a_Client)
{
a_Client.SendPickupSpawn(*this);
diff --git a/source/Entities/Pickup.h b/source/Entities/Pickup.h
index b0323dd92..af6eaf3bb 100644
--- a/source/Entities/Pickup.h
+++ b/source/Entities/Pickup.h
@@ -26,8 +26,6 @@ public:
cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem & a_Item, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f); // tolua_export
- virtual bool Initialize(cWorld * a_World) override;
-
cItem & GetItem(void) {return m_Item; } // tolua_export
const cItem & GetItem(void) const {return m_Item; }
diff --git a/source/Entities/Player.cpp b/source/Entities/Player.cpp
index 119afbafc..0cb047933 100644
--- a/source/Entities/Player.cpp
+++ b/source/Entities/Player.cpp
@@ -64,6 +64,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_IsSwimming(false)
, m_IsSubmerged(false)
, m_EatingFinishTick(-1)
+ , m_IsChargingBow(false)
+ , m_BowCharge(0)
{
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
@@ -213,6 +215,13 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
// Handle air drowning stuff
HandleAir();
+
+ // Handle charging the bow:
+ if (m_IsChargingBow)
+ {
+ m_BowCharge += 1;
+ LOGD("Player \"%s\" charging bow: %d", m_PlayerName.c_str(), m_BowCharge);
+ }
if (m_bDirtyPosition)
{
@@ -253,6 +262,41 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
+void cPlayer::StartChargingBow(void)
+{
+ LOGD("Player \"%s\" started charging their bow", m_PlayerName.c_str());
+ m_IsChargingBow = true;
+ m_BowCharge = 0;
+}
+
+
+
+
+
+int cPlayer::FinishChargingBow(void)
+{
+ LOGD("Player \"%s\" finished charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge);
+ int res = m_BowCharge;
+ m_IsChargingBow = false;
+ m_BowCharge = 0;
+ return res;
+}
+
+
+
+
+
+void cPlayer::CancelChargingBow(void)
+{
+ LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge);
+ m_IsChargingBow = false;
+ m_BowCharge = 0;
+}
+
+
+
+
+
void cPlayer::SetTouchGround(bool a_bTouchGround)
{
// If just
diff --git a/source/Entities/Player.h b/source/Entities/Player.h
index 5dcce8421..4adf946db 100644
--- a/source/Entities/Player.h
+++ b/source/Entities/Player.h
@@ -62,6 +62,18 @@ public:
/// Returns the currently equipped boots; empty item if none
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
+
+ /// Starts charging the equipped bow
+ void StartChargingBow(void);
+
+ /// Finishes charging the current bow. Returns the number of ticks for which the bow has been charged
+ int FinishChargingBow(void);
+
+ /// Cancels the current bow charging
+ void CancelChargingBow(void);
+
+ /// Returns true if the player is currently charging the bow
+ bool IsChargingBox(void) const { return m_IsChargingBow; }
void SetTouchGround( bool a_bTouchGround );
inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; }
@@ -351,6 +363,9 @@ protected:
/// The world tick in which eating will be finished. -1 if not eating
Int64 m_EatingFinishTick;
+
+ bool m_IsChargingBow;
+ int m_BowCharge;
virtual void Destroyed(void);
diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp
new file mode 100644
index 000000000..f405e9aa4
--- /dev/null
+++ b/source/Entities/ProjectileEntity.cpp
@@ -0,0 +1,296 @@
+
+// ProjectileEntity.cpp
+
+// Implements the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types
+
+#include "Globals.h"
+#include "ProjectileEntity.h"
+#include "../ClientHandle.h"
+#include "Player.h"
+#include "../LineBlockTracer.h"
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cProjectileTracerCallback:
+
+class cProjectileTracerCallback :
+ public cBlockTracer::cCallbacks
+{
+public:
+ cProjectileTracerCallback(cProjectileEntity * a_Projectile) :
+ m_Projectile(a_Projectile)
+ {
+ }
+
+protected:
+ cProjectileEntity * m_Projectile;
+
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
+ {
+ if (g_BlockIsSolid[a_BlockType])
+ {
+ // The projectile hit a solid block
+ m_Projectile->OnHitSolidBlock(a_BlockX, a_BlockY, a_BlockZ, a_EntryFace);
+ return true;
+ }
+
+ // Convey some special effects from special blocks:
+ switch (a_BlockType)
+ {
+ case E_BLOCK_LAVA:
+ case E_BLOCK_STATIONARY_LAVA:
+ {
+ m_Projectile->StartBurning(30);
+ break;
+ }
+ case E_BLOCK_WATER:
+ case E_BLOCK_STATIONARY_WATER:
+ {
+ m_Projectile->StopBurning();
+ break;
+ }
+ } // switch (a_BlockType)
+
+ // Continue tracing
+ return false;
+ }
+} ;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cProjectileEntity:
+
+cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
+ super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
+ m_ProjectileKind(a_Kind),
+ m_Creator(a_Creator),
+ m_IsInGround(false)
+{
+}
+
+
+
+
+
+cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
+ super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
+ m_ProjectileKind(a_Kind),
+ m_Creator(a_Creator),
+ m_IsInGround(false)
+{
+ SetSpeed(a_Speed);
+}
+
+
+
+
+
+cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed)
+{
+ Vector3d Speed;
+ if (a_Speed != NULL)
+ {
+ Speed = *a_Speed;
+ }
+
+ switch (a_Kind)
+ {
+ case pkArrow: return new cArrowEntity(a_Creator, a_X, a_Y, a_Z, Speed);
+ // TODO: the rest
+ }
+
+ LOGWARNING("%s: Unknown kind: %d", __FUNCTION__, a_Kind);
+ return NULL;
+}
+
+
+
+
+
+void cProjectileEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
+{
+ // TODO: Set proper position based on what face was hit
+ switch (a_BlockFace)
+ {
+ case BLOCK_FACE_TOP: SetPosition(0.5 + a_BlockX, 1.0 + a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_BOTTOM: SetPosition(0.5 + a_BlockX, a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_EAST: SetPosition( a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_WEST: SetPosition(1.0 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_NORTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 1.0 + a_BlockZ); break;
+ case BLOCK_FACE_SOUTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, a_BlockZ); break;
+ case BLOCK_FACE_NONE: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
+ }
+ SetSpeed(0, 0, 0);
+
+ // DEBUG:
+ LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, hit solid block at face %d",
+ m_UniqueID,
+ GetPosX(), GetPosY(), GetPosZ(),
+ a_BlockFace
+ );
+
+ m_IsInGround = true;
+}
+
+
+
+
+
+AString cProjectileEntity::GetMCAClassName(void) const
+{
+ switch (m_ProjectileKind)
+ {
+ case pkArrow: return "Arrow";
+ case pkSnowball: return "Snowball";
+ case pkEgg: return "Egg";
+ case pkGhastFireball: return "Fireball";
+ case pkFireCharge: return "SmallFireball";
+ case pkEnderPearl: return "ThrownEnderPearl";
+ case pkExpBottle: return "ThrownExpBottle";
+ case pkSplashPotion: return "ThrownPotion";
+ case pkWitherSkull: return "WitherSkull";
+ case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this?
+ }
+ ASSERT(!"Unhandled projectile entity kind!");
+ return "";
+}
+
+
+
+
+
+void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+ BroadcastMovementUpdate();
+}
+
+
+
+
+
+void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
+{
+ if (m_IsInGround)
+ {
+ // Already-grounded projectiles don't move at all
+ return;
+ }
+
+ Vector3d PerTickSpeed = GetSpeed() / 20;
+ Vector3d Pos = GetPosition();
+
+ // Trace the tick's worth of movement as a line:
+ Vector3d NextPos = Pos + PerTickSpeed;
+ cProjectileTracerCallback TracerCallback(this);
+ if (cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
+ {
+ // Nothing in the way, update the position
+ SetPosition(NextPos);
+ }
+
+ // Add gravity effect to the vertical speed component:
+ SetSpeedY(GetSpeedY() + m_Gravity / 20);
+
+ // DEBUG:
+ LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
+ m_UniqueID,
+ GetPosX(), GetPosY(), GetPosZ(),
+ GetSpeedX(), GetSpeedY(), GetSpeedZ()
+ );
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cArrowEntity:
+
+cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed) :
+ super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5),
+ m_PickupState(psNoPickup),
+ m_DamageCoeff(2)
+{
+ SetSpeed(a_Speed);
+ SetMass(0.1);
+ LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f}",
+ m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ()
+ );
+}
+
+
+
+
+
+cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) :
+ super(pkArrow, &a_Player, PosFromPlayerPos(a_Player), SpeedFromPlayerLook(a_Player, a_Force), 0.5, 0.5),
+ m_PickupState(psInSurvivalOrCreative),
+ m_DamageCoeff(2)
+{
+}
+
+
+
+
+
+Vector3d cArrowEntity::PosFromPlayerPos(const cPlayer & a_Player)
+{
+ Vector3d res = a_Player.GetEyePosition();
+
+ // Adjust the position to be just outside the player's bounding box:
+ res.x += 0.16 * cos(a_Player.GetPitch());
+ res.y += -0.1;
+ res.z += 0.16 * sin(a_Player.GetPitch());
+
+ return res;
+}
+
+
+
+
+
+Vector3d cArrowEntity::SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force)
+{
+ Vector3d res = a_Player.GetLookVector();
+ res.Normalize();
+
+ // TODO: Add a slight random change (+-0.0075 in each direction)
+
+ return res * a_Force * 1.5 * 20;
+}
+
+
+
+
+
+bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
+{
+ switch (m_PickupState)
+ {
+ case psNoPickup: return false;
+ case psInSurvivalOrCreative: return (a_Player.IsGameModeSurvival() || a_Player.IsGameModeCreative());
+ case psInCreative: return a_Player.IsGameModeCreative();
+ }
+ ASSERT(!"Unhandled pickup state");
+ return false;
+}
+
+
+
+
+
+void cArrowEntity::SpawnOn(cClientHandle & a_Client)
+{
+ a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0);
+}
+
+
+
+
diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h
index 2e050068b..1569ad035 100644
--- a/source/Entities/ProjectileEntity.h
+++ b/source/Entities/ProjectileEntity.h
@@ -1,7 +1,7 @@
// ProjectileEntity.h
-// Declares the cProjectileEntity class representing the common base class for projectiles
+// Declares the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types
@@ -29,8 +29,8 @@ public:
pkArrow = 60,
pkSnowball = 61,
pkEgg = 62,
- pkGhastFireball = 63, // TODO: Unverified TypeID, check this in ProtoProxy
- pkFireCharge = 64, // TODO: Unverified TypeID, check this in ProtoProxy
+ pkGhastFireball = 63,
+ pkFireCharge = 64,
pkEnderPearl = 65,
pkExpBottle = 75,
pkSplashPotion = 73,
@@ -38,17 +38,48 @@ public:
pkFishingFloat = 90,
} ;
+ // tolua_end
+
+ CLASS_PROTODEF(cProjectileEntity);
+
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
- /// Called by the physics blocktracer when the entity hits a solid block, the coords and the face hit is given
- virtual void OnHitSolidBlock(double a_BlockX, double a_BlockY, double a_BlockZ, char a_BlockFace) {};
+ static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed = NULL);
+
+ /// Called by the physics blocktracer when the entity hits a solid block, the block's coords and the face hit is given
+ virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
+
+ // tolua_begin
+
+ /// Returns the kind of the projectile (fast class identification)
+ eKind GetProjectileKind(void) const { return m_ProjectileKind; }
+
+ /// Returns the entity who created this projectile; may be NULL
+ cEntity * GetCreator(void) { return m_Creator; }
+
+ /// Returns the string that is used as the entity type (class name) in MCA files
+ AString GetMCAClassName(void) const;
+
+ /// Returns true if the projectile has hit the ground and is stuck there
+ bool IsInGround(void) const { return m_IsInGround; }
protected:
- eKind m_Kind;
+ eKind m_ProjectileKind;
/// The entity who has created this projectile; may be NULL (e. g. for dispensers)
cEntity * m_Creator;
+
+ /// True if the projectile has hit the ground and is stuck there
+ bool m_IsInGround;
+
+ // tolua_end
+
+ // cEntity overrides:
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
+
+ // tolua_begin
} ;
@@ -58,9 +89,64 @@ protected:
class cArrowEntity :
public cProjectileEntity
{
+ typedef cProjectileEntity super;
+
public:
- cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
- cArrowEntity(cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
+ /// Determines when the arrow can be picked up (depending on player gamemode). Corresponds to the MCA file "pickup" field
+ enum ePickupState
+ {
+ psNoPickup = 0,
+ psInSurvivalOrCreative = 1,
+ psInCreative = 2,
+ } ;
+
+ // tolua_end
+
+ CLASS_PROTODEF(cArrowEntity);
+
+ /// Creates a new arrow with psNoPickup state and default damage modifier coeff
+ cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed);
+
+ /// Creates a new arrow as shot by a player, initializes it from the player object
+ cArrowEntity(cPlayer & a_Player, double a_Force);
+
+ // tolua_begin
+
+ /// Returns the initial arrow position, as defined by the player eye position + adjustment.
+ static Vector3d PosFromPlayerPos(const cPlayer & a_Player);
+
+ /// Returns the initial arrow speed, as defined by the player look vector and the force coefficient
+ static Vector3d SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force);
+
+ /// Returns whether the arrow can be picked up by players
+ ePickupState GetPickupState(void) const { return m_PickupState; }
+
+ /// Sets a new pickup state
+ void SetPickupState(ePickupState a_PickupState) { m_PickupState = a_PickupState; }
+
+ /// Returns the damage modifier coeff.
+ double GetDamageCoeff(void) const { return m_DamageCoeff; }
+
+ /// Sets the damage modifier coeff
+ void SetDamageCoeff(double a_DamageCoeff) { m_DamageCoeff = a_DamageCoeff; }
+
+ /// Returns true if the specified player can pick the arrow up
+ bool CanPickup(const cPlayer & a_Player) const;
+
+ // tolua_end
+
+protected:
+
+ /// Determines when the arrow can be picked up by players
+ ePickupState m_PickupState;
+
+ /// The coefficient applied to the damage that the arrow will deal, based on the bow enchantment. 2.0 for normal arrow
+ double m_DamageCoeff;
+
+ // cEntity overrides:
+ virtual void SpawnOn(cClientHandle & a_Client) override;
+
+ // tolua_begin
} ;
// tolua_end
diff --git a/source/Entities/TNTEntity.cpp b/source/Entities/TNTEntity.cpp
index 43a0dea09..ad3d9ae0c 100644
--- a/source/Entities/TNTEntity.cpp
+++ b/source/Entities/TNTEntity.cpp
@@ -29,20 +29,6 @@ cTNTEntity::cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec) :
-bool cTNTEntity::Initialize(cWorld * a_World)
-{
- if (super::Initialize(a_World))
- {
- a_World->BroadcastSpawnEntity(*this);
- return true;
- }
- return false;
-}
-
-
-
-
-
void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle)
{
a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT
diff --git a/source/Entities/TNTEntity.h b/source/Entities/TNTEntity.h
index ae6fc75e2..eb5040e8a 100644
--- a/source/Entities/TNTEntity.h
+++ b/source/Entities/TNTEntity.h
@@ -19,7 +19,6 @@ public:
cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec);
// cEntity overrides:
- virtual bool Initialize(cWorld * a_World) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
diff --git a/source/Items/ItemBow.h b/source/Items/ItemBow.h
new file mode 100644
index 000000000..845192ef7
--- /dev/null
+++ b/source/Items/ItemBow.h
@@ -0,0 +1,80 @@
+
+// ItemBow.h
+
+// Declares the cItemBowHandler class representing the itemhandler for bows
+
+
+
+
+
+#pragma once
+
+#include "../Entities/ProjectileEntity.h"
+
+
+
+
+
+class cItemBowHandler :
+ public cItemHandler
+{
+ typedef cItemHandler super;
+
+public:
+ cItemBowHandler(void) :
+ super(E_ITEM_BOW)
+ {
+ }
+
+
+ virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
+ {
+ ASSERT(a_Player != NULL);
+
+ // Check if the player has an arrow in the inventory, or is in Creative:
+ if (!(a_Player->IsGameModeCreative() || a_Player->GetInventory().HasItems(cItem(E_ITEM_ARROW))))
+ {
+ return false;
+ }
+ a_Player->StartChargingBow();
+ return true;
+ }
+
+
+ virtual void OnItemShoot(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
+ {
+ // Actual shot - produce the arrow with speed based on the ticks that the bow was charged
+ ASSERT(a_Player != NULL);
+
+ int BowCharge = a_Player->FinishChargingBow();
+ double Force = (double)BowCharge / 20;
+ Force = (Force * Force + 2 * Force) / 3; // This formula is used by the 1.6.2 client
+ if (Force < 0.1)
+ {
+ // Too little force, ignore the shot
+ return;
+ }
+ if (Force > 1)
+ {
+ Force = 1;
+ }
+
+ // Create the arrow entity:
+ cArrowEntity * Arrow = new cArrowEntity(*a_Player, Force * 2);
+ if (Arrow == NULL)
+ {
+ return;
+ }
+ if (!Arrow->Initialize(a_Player->GetWorld()))
+ {
+ delete Arrow;
+ return;
+ }
+ a_Player->GetWorld()->BroadcastSpawnEntity(*Arrow);
+ }
+} ;
+
+
+
+
+
diff --git a/source/Items/ItemHandler.cpp b/source/Items/ItemHandler.cpp
index 66d36e1a6..c0de4a6ec 100644
--- a/source/Items/ItemHandler.cpp
+++ b/source/Items/ItemHandler.cpp
@@ -8,6 +8,7 @@
// Handlers:
#include "ItemBed.h"
+#include "ItemBow.h"
#include "ItemBrewingStand.h"
#include "ItemBucket.h"
#include "ItemCauldron.h"
@@ -47,18 +48,24 @@ cItemHandler * cItemHandler::m_ItemHandler[2268];
-cItemHandler *cItemHandler::GetItemHandler(int a_ItemType)
+cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
{
- if(a_ItemType < 0) a_ItemType = 0;
+ if (a_ItemType < 0)
+ {
+ ASSERT(!"Bad item type");
+ a_ItemType = 0;
+ }
- if(!m_HandlerInitialized)
- { //We have to initialize
+ if (!m_HandlerInitialized)
+ {
+ // We need to initialize
memset(m_ItemHandler, 0, sizeof(m_ItemHandler));
m_HandlerInitialized = true;
}
- if(m_ItemHandler[a_ItemType])
- return m_ItemHandler[a_ItemType];
- m_ItemHandler[a_ItemType] = CreateItemHandler(a_ItemType);
+ if (m_ItemHandler[a_ItemType] == NULL)
+ {
+ m_ItemHandler[a_ItemType] = CreateItemHandler(a_ItemType);
+ }
return m_ItemHandler[a_ItemType];
}
@@ -77,6 +84,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_BLOCK_SAPLING: return new cItemSaplingHandler(a_ItemType);
case E_BLOCK_WOOL: return new cItemClothHandler(a_ItemType);
case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
+ case E_ITEM_BOW: return new cItemBowHandler;
case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType);
diff --git a/source/Items/ItemHandler.h b/source/Items/ItemHandler.h
index 44d43e8f7..e39bb054b 100644
--- a/source/Items/ItemHandler.h
+++ b/source/Items/ItemHandler.h
@@ -21,8 +21,11 @@ class cItemHandler
public:
cItemHandler(int a_ItemType);
- /// Called when the player tries to use the item. Return false to make the item unusable. DEFAULT: False
- virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir); //eg for fishing or hoes
+ /// Called when the player tries to use the item (right mouse button). Return false to make the item unusable. DEFAULT: False
+ virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
+
+ /// Called when the client sends the SHOOT status in the lclk packet
+ virtual void OnItemShoot(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) {}
/// Called while the player diggs a block using this item
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
@@ -88,7 +91,7 @@ protected:
int m_ItemType;
static cItemHandler *CreateItemHandler(int m_ItemType);
- static cItemHandler *m_ItemHandler[2268];
+ static cItemHandler * m_ItemHandler[E_ITEM_LAST + 1];
static bool m_HandlerInitialized; //used to detect if the itemhandlers are initialized
};
diff --git a/source/LineBlockTracer.cpp b/source/LineBlockTracer.cpp
index 03464314a..7cc14089d 100644
--- a/source/LineBlockTracer.cpp
+++ b/source/LineBlockTracer.cpp
@@ -55,6 +55,7 @@ bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ,
m_DirX = (m_StartX < m_EndX) ? 1 : -1;
m_DirY = (m_StartY < m_EndY) ? 1 : -1;
m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1;
+ m_CurrentFace = BLOCK_FACE_NONE;
// Check the start coords, adjust into the world:
if (m_StartY < 0)
@@ -178,9 +179,9 @@ bool cLineBlockTracer::MoveToNextBlock(void)
// Based on the wall hit, adjust the current coords
switch (Direction)
{
- case dirX: m_CurrentX += m_DirX; break;
- case dirY: m_CurrentY += m_DirY; break;
- case dirZ: m_CurrentZ += m_DirZ; break;
+ case dirX: m_CurrentX += m_DirX; m_CurrentFace = (m_DirX > 0) ? BLOCK_FACE_EAST : BLOCK_FACE_WEST; break;
+ case dirY: m_CurrentY += m_DirY; m_CurrentFace = (m_DirY > 0) ? BLOCK_FACE_BOTTOM : BLOCK_FACE_TOP; break;
+ case dirZ: m_CurrentZ += m_DirZ; m_CurrentFace = (m_DirZ > 0) ? BLOCK_FACE_SOUTH : BLOCK_FACE_NORTH; break;
case dirNONE: return false;
}
return true;
@@ -211,7 +212,7 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
- if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta))
+ if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta, m_CurrentFace))
{
// The callback terminated the trace
return false;
@@ -219,7 +220,7 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
}
else
{
- if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ))
+ if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace))
{
// The callback terminated the trace
return false;
diff --git a/source/LineBlockTracer.h b/source/LineBlockTracer.h
index 4616cb191..ccbb70ea6 100644
--- a/source/LineBlockTracer.h
+++ b/source/LineBlockTracer.h
@@ -60,6 +60,9 @@ protected:
// The current block
int m_CurrentX, m_CurrentY, m_CurrentZ;
+
+ // The face through which the current block has been entered
+ char m_CurrentFace;
/// Adjusts the start point above the world to just at the world's top
diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp
index 27c6684f2..87efecd35 100644
--- a/source/ManualBindings.cpp
+++ b/source/ManualBindings.cpp
@@ -1649,7 +1649,7 @@ public:
{
}
- virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock"))
{
@@ -1661,6 +1661,7 @@ public:
m_LuaState.Push(a_BlockZ);
m_LuaState.Push(a_BlockType);
m_LuaState.Push(a_BlockMeta);
+ m_LuaState.Push(a_EntryFace);
if (!m_LuaState.CallFunction(1))
{
return false;
@@ -1674,7 +1675,7 @@ public:
return res;
}
- virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData"))
{
@@ -1684,6 +1685,7 @@ public:
m_LuaState.Push(a_BlockX);
m_LuaState.Push(a_BlockY);
m_LuaState.Push(a_BlockZ);
+ m_LuaState.Push(a_EntryFace);
if (!m_LuaState.CallFunction(1))
{
return false;
diff --git a/source/Vector3d.h b/source/Vector3d.h
index 6f28a857b..ecc72e421 100644
--- a/source/Vector3d.h
+++ b/source/Vector3d.h
@@ -30,12 +30,13 @@ public: // tolua_export
void operator -= ( Vector3d* a_V ) { x -= a_V->x; y -= a_V->y; z -= a_V->z; }
void operator *= ( double a_f ) { x *= a_f; y *= a_f; z *= a_f; }
- Vector3d operator + ( const Vector3d& v2 ) const { return Vector3d( x + v2.x, y + v2.y, z + v2.z ); } // tolua_export
- Vector3d operator + ( const Vector3d* v2 ) const { return Vector3d( x + v2->x, y + v2->y, z + v2->z ); } // tolua_export
- Vector3d operator - ( const Vector3d& v2 ) const { return Vector3d( x - v2.x, y - v2.y, z - v2.z ); } // tolua_export
- Vector3d operator - ( const Vector3d* v2 ) const { return Vector3d( x - v2->x, y - v2->y, z - v2->z ); } // tolua_export
- Vector3d operator * ( const double f ) const { return Vector3d( x * f, y * f, z * f ); } // tolua_export
- Vector3d operator * ( const Vector3d& v2 ) const { return Vector3d( x * v2.x, y * v2.y, z * v2.z ); } // tolua_export
+ Vector3d operator + (const Vector3d & v2) const { return Vector3d(x + v2.x, y + v2.y, z + v2.z ); } // tolua_export
+ Vector3d operator + (const Vector3d * v2) const { return Vector3d(x + v2->x, y + v2->y, z + v2->z ); } // tolua_export
+ Vector3d operator - (const Vector3d & v2) const { return Vector3d(x - v2.x, y - v2.y, z - v2.z ); } // tolua_export
+ Vector3d operator - (const Vector3d * v2) const { return Vector3d(x - v2->x, y - v2->y, z - v2->z ); } // tolua_export
+ Vector3d operator * (const double f) const { return Vector3d(x * f, y * f, z * f ); } // tolua_export
+ Vector3d operator * (const Vector3d & v2) const { return Vector3d(x * v2.x, y * v2.y, z * v2.z ); } // tolua_export
+ Vector3d operator / (const double f) const { return Vector3d(x / f, y / f, z / f ); } // tolua_export
double x, y, z; // tolua_export
diff --git a/source/World.cpp b/source/World.cpp
index 1985f01ec..ab783d7a7 100644
--- a/source/World.cpp
+++ b/source/World.cpp
@@ -5,8 +5,6 @@
#include "World.h"
#include "ChunkDef.h"
#include "ClientHandle.h"
-#include "Entities/Pickup.h"
-#include "Entities/Player.h"
#include "Server.h"
#include "Item.h"
#include "Root.h"
@@ -14,6 +12,11 @@
#include "ChunkMap.h"
#include "OSSupport/Timer.h"
+// Entities (except mobs):
+#include "Entities/Pickup.h"
+#include "Entities/Player.h"
+#include "Entities/TNTEntity.h"
+
// Simulators:
#include "Simulator/SimulatorManager.h"
#include "Simulator/FloodyFluidSimulator.h"
@@ -55,7 +58,6 @@
#include "PluginManager.h"
#include "Blocks/BlockHandler.h"
#include "Vector3d.h"
-#include "Entities/TNTEntity.h"
#include "Tracer.h"
#include "tolua++.h"
@@ -2647,6 +2649,26 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
+int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const Vector3d * a_Speed)
+{
+ cProjectileEntity * Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Speed);
+ if (Projectile == NULL)
+ {
+ return -1;
+ }
+ if (!Projectile->Initialize(this))
+ {
+ delete Projectile;
+ return -1;
+ }
+ BroadcastSpawnEntity(*Projectile);
+ return Projectile->GetUniqueID();
+}
+
+
+
+
+
void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Results)
{
cCSLock Lock(m_CSPlayers);
diff --git a/source/World.h b/source/World.h
index bcda169bd..9e2bf4e8f 100644
--- a/source/World.h
+++ b/source/World.h
@@ -21,6 +21,7 @@
#include "LightingThread.h"
#include "Item.h"
#include "Mobs/Monster.h"
+#include "Entities/ProjectileEntity.h"
@@ -573,6 +574,9 @@ public:
/// Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise
int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType); // tolua_export
+ /// Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise
+ int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const Vector3d * a_Speed = NULL); // tolua_export
+
/// Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread!
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
diff --git a/source/WorldStorage/NBTChunkSerializer.cpp b/source/WorldStorage/NBTChunkSerializer.cpp
index 706e913ef..baae0dc01 100644
--- a/source/WorldStorage/NBTChunkSerializer.cpp
+++ b/source/WorldStorage/NBTChunkSerializer.cpp
@@ -22,6 +22,8 @@
#include "../Entities/Minecart.h"
#include "../Mobs/Monster.h"
#include "../Entities/Pickup.h"
+#include "../Entities/ProjectileEntity.h"
+
@@ -330,6 +332,62 @@ void cNBTChunkSerializer::AddPickupEntity(cPickup * a_Pickup)
+void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
+{
+ m_Writer.BeginCompound("");
+ AddBasicEntity(a_Projectile, a_Projectile->GetMCAClassName());
+ Vector3d Pos = a_Projectile->GetPosition();
+ m_Writer.AddShort("xTile", (Int16)floor(Pos.x));
+ m_Writer.AddShort("yTile", (Int16)floor(Pos.y));
+ m_Writer.AddShort("zTile", (Int16)floor(Pos.z));
+ m_Writer.AddShort("inTile", 0); // TODO: Query the block type (is it needed?)
+ m_Writer.AddShort("shake", 0); // TODO: Any shake?
+ m_Writer.AddByte ("inGround", a_Projectile->IsInGround() ? 1 : 0);
+
+ switch (a_Projectile->GetProjectileKind())
+ {
+ case cProjectileEntity::pkArrow:
+ {
+ m_Writer.AddByte("inData", 0); // TODO: Query the block meta (is it needed?)
+ m_Writer.AddByte("pickup", ((cArrowEntity *)a_Projectile)->GetPickupState());
+ m_Writer.AddDouble("damage", ((cArrowEntity *)a_Projectile)->GetDamageCoeff());
+ break;
+ }
+ case cProjectileEntity::pkGhastFireball:
+ {
+ m_Writer.AddInt("ExplosionPower", 1);
+ // fall-through:
+ }
+ case cProjectileEntity::pkFireCharge:
+ case cProjectileEntity::pkWitherSkull:
+ {
+ m_Writer.BeginList("Motion", TAG_Double);
+ m_Writer.AddDouble("", a_Projectile->GetSpeedX());
+ m_Writer.AddDouble("", a_Projectile->GetSpeedY());
+ m_Writer.AddDouble("", a_Projectile->GetSpeedZ());
+ m_Writer.EndList();
+ break;
+ }
+ default:
+ {
+ ASSERT(!"Unsaved projectile entity!");
+ }
+ } // switch (ProjectileKind)
+ cEntity * Creator = a_Projectile->GetCreator();
+ if (Creator != NULL)
+ {
+ if (Creator->GetEntityType() == cEntity::etPlayer)
+ {
+ m_Writer.AddString("ownerName", ((cPlayer *)Creator)->GetName());
+ }
+ }
+ m_Writer.EndCompound();
+}
+
+
+
+
+
void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart)
{
m_Writer.BeginList("Items", TAG_Compound);
@@ -403,10 +461,11 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity)
switch (a_Entity->GetEntityType())
{
- case cEntity::etFallingBlock: AddFallingBlockEntity((cFallingBlock *)a_Entity); break;
- case cEntity::etMinecart: AddMinecartEntity ((cMinecart *) a_Entity); break;
- case cEntity::etMonster: AddMonsterEntity ((cMonster *) a_Entity); break;
- case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
+ case cEntity::etFallingBlock: AddFallingBlockEntity((cFallingBlock *) a_Entity); break;
+ case cEntity::etMinecart: AddMinecartEntity ((cMinecart *) a_Entity); break;
+ case cEntity::etMonster: AddMonsterEntity ((cMonster *) a_Entity); break;
+ case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
+ case cEntity::etProjectile: AddProjectileEntity ((cProjectileEntity *)a_Entity); break;
case cEntity::etPlayer: return; // Players aren't saved into the world
default:
{
diff --git a/source/WorldStorage/NBTChunkSerializer.h b/source/WorldStorage/NBTChunkSerializer.h
index cd1388f89..481c578f3 100644
--- a/source/WorldStorage/NBTChunkSerializer.h
+++ b/source/WorldStorage/NBTChunkSerializer.h
@@ -36,6 +36,7 @@ class cMinecartWithHopper;
class cMonster;
class cPickup;
class cItemGrid;
+class cProjectileEntity;
@@ -97,6 +98,7 @@ protected:
void AddMinecartEntity (cMinecart * a_Minecart);
void AddMonsterEntity (cMonster * a_Monster);
void AddPickupEntity (cPickup * a_Pickup);
+ void AddProjectileEntity (cProjectileEntity * a_Projectile);
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
diff --git a/source/WorldStorage/WSSAnvil.cpp b/source/WorldStorage/WSSAnvil.cpp
index 72d583e2b..3ab64148e 100644
--- a/source/WorldStorage/WSSAnvil.cpp
+++ b/source/WorldStorage/WSSAnvil.cpp
@@ -20,13 +20,13 @@
#include "../Item.h"
#include "../ItemGrid.h"
#include "../StringCompression.h"
-#include "../Entities/Entity.h"
#include "../OSSupport/MakeDir.h"
#include "FastNBT.h"
+#include "../Mobs/Monster.h"
#include "../Entities/FallingBlock.h"
#include "../Entities/Minecart.h"
-#include "../Mobs/Monster.h"
#include "../Entities/Pickup.h"
+#include "../Entities/ProjectileEntity.h"
@@ -956,6 +956,10 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{
LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
+ if (strncmp(a_IDTag, "Arrow", a_IDTagLength) == 0)
+ {
+ LoadArrowFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
// TODO: other entities
}
@@ -1043,7 +1047,7 @@ void cWSSAnvil::LoadMinecartTFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- //TODO: Everything to do with TNT carts
+ // TODO: Everything to do with TNT carts
a_Entities.push_back(Minecart.release());
}
@@ -1060,7 +1064,7 @@ void cWSSAnvil::LoadMinecartHFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- //TODO: Everything to do with hopper carts
+ // TODO: Everything to do with hopper carts
a_Entities.push_back(Minecart.release());
}
@@ -1093,6 +1097,45 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
+void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cArrowEntity> Arrow(new cArrowEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
+ if (!LoadEntityBaseFromNBT(*Arrow.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ // Load pickup state:
+ int PickupIdx = a_NBT.FindChildByName(a_TagIdx, "pickup");
+ if (PickupIdx > 0)
+ {
+ Arrow->SetPickupState((cArrowEntity::ePickupState)a_NBT.GetByte(PickupIdx));
+ }
+ else
+ {
+ // Try the older "player" tag:
+ int PlayerIdx = a_NBT.FindChildByName(a_TagIdx, "player");
+ if (PlayerIdx > 0)
+ {
+ Arrow->SetPickupState((a_NBT.GetByte(PlayerIdx) == 0) ? cArrowEntity::psNoPickup : cArrowEntity::psInSurvivalOrCreative);
+ }
+ }
+
+ // Load damage:
+ int DamageIdx = a_NBT.FindChildByName(a_TagIdx, "damage");
+ if (DamageIdx > 0)
+ {
+ Arrow->SetDamageCoeff(a_NBT.GetDouble(DamageIdx));
+ }
+
+ // Store the new arrow in the entities list:
+ a_Entities.push_back(Arrow.release());
+}
+
+
+
+
+
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
{
double Pos[3];
diff --git a/source/WorldStorage/WSSAnvil.h b/source/WorldStorage/WSSAnvil.h
index 47fda3f7b..b2556ab50 100644
--- a/source/WorldStorage/WSSAnvil.h
+++ b/source/WorldStorage/WSSAnvil.h
@@ -145,6 +145,7 @@ protected:
void LoadMinecartTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadMinecartHFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadPickupFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadArrowFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
/// Loads entity common data from the NBT compound; returns true if successful
bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx);