summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/AllToLua.pkg1
-rw-r--r--source/Bindings.cpp1353
-rw-r--r--source/Bindings.h2
-rw-r--r--source/BlockID.cpp139
-rw-r--r--source/BlockID.h9
-rw-r--r--source/Blocks/BlockBed.cpp2
-rw-r--r--source/Blocks/BlockBed.h6
-rw-r--r--source/Blocks/BlockCactus.h6
-rw-r--r--source/Blocks/BlockCrops.h6
-rw-r--r--source/Blocks/BlockDeadBush.h12
-rw-r--r--source/Blocks/BlockDoor.cpp7
-rw-r--r--source/Blocks/BlockDoor.h86
-rw-r--r--source/Blocks/BlockFenceGate.h34
-rw-r--r--source/Blocks/BlockFlower.h12
-rw-r--r--source/Blocks/BlockHandler.cpp23
-rw-r--r--source/Blocks/BlockHandler.h8
-rw-r--r--source/Blocks/BlockLever.h6
-rw-r--r--source/Blocks/BlockMushroom.h12
-rw-r--r--source/Blocks/BlockMycelium.h5
-rw-r--r--source/Blocks/BlockPumpkin.h60
-rw-r--r--source/Blocks/BlockRedstone.h11
-rw-r--r--source/Blocks/BlockRedstoneRepeater.h12
-rw-r--r--source/Blocks/BlockSapling.h12
-rw-r--r--source/Blocks/BlockSign.h6
-rw-r--r--source/Blocks/BlockSugarcane.h6
-rw-r--r--source/Blocks/BlockTorch.h103
-rw-r--r--source/BoundingBox.cpp331
-rw-r--r--source/BoundingBox.h90
-rw-r--r--source/ChunkMap.cpp2
-rw-r--r--source/ChunkMap.h2
-rw-r--r--source/ClientHandle.cpp185
-rw-r--r--source/ClientHandle.h14
-rw-r--r--source/Defines.h29
-rw-r--r--source/Doors.h87
-rw-r--r--source/Entities/Boat.cpp87
-rw-r--r--source/Entities/Boat.h38
-rw-r--r--source/Entities/Entity.cpp101
-rw-r--r--source/Entities/Entity.h20
-rw-r--r--source/Entities/Player.cpp10
-rw-r--r--source/Entities/ProjectileEntity.cpp357
-rw-r--r--source/Entities/ProjectileEntity.h89
-rw-r--r--source/Entities/TNTEntity.cpp2
-rw-r--r--source/Items/ItemBoat.h54
-rw-r--r--source/Items/ItemHandler.cpp8
-rw-r--r--source/ManualBindings.cpp138
-rw-r--r--source/Mobs/Monster.cpp43
-rw-r--r--source/Mobs/Monster.h7
-rw-r--r--source/Mobs/Skeleton.cpp19
-rw-r--r--source/Mobs/Skeleton.h1
-rw-r--r--source/Mobs/Zombie.cpp20
-rw-r--r--source/Mobs/Zombie.h3
-rw-r--r--source/OSSupport/Event.cpp47
-rw-r--r--source/OSSupport/Event.h10
-rw-r--r--source/Piston.cpp8
-rw-r--r--source/Protocol/Protocol125.cpp2
-rw-r--r--source/Protocol/Protocol132.cpp13
-rw-r--r--source/Protocol/Protocol16x.cpp4
-rw-r--r--source/Vector3d.cpp72
-rw-r--r--source/Vector3d.h88
-rw-r--r--source/World.cpp6
-rw-r--r--source/World.h13
-rw-r--r--source/WorldStorage/NBTChunkSerializer.cpp16
-rw-r--r--source/WorldStorage/NBTChunkSerializer.h2
-rw-r--r--source/WorldStorage/WSSAnvil.cpp151
-rw-r--r--source/WorldStorage/WSSAnvil.h27
65 files changed, 3304 insertions, 831 deletions
diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg
index 8d87be307..b423c43a5 100644
--- a/source/AllToLua.pkg
+++ b/source/AllToLua.pkg
@@ -53,6 +53,7 @@ $cfile "Vector3d.h"
$cfile "Vector3i.h"
$cfile "Matrix4f.h"
$cfile "Cuboid.h"
+$cfile "BoundingBox.h"
$cfile "Tracer.h"
$cfile "Group.h"
$cfile "BlockArea.h"
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index fbc25ed1c..c0e4f9911 100644
--- a/source/Bindings.cpp
+++ b/source/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 09/01/13 14:42:04.
+** Generated automatically by tolua++-1.0.92 on 09/15/13 20:27:51.
*/
#ifndef __cplusplus
@@ -53,6 +53,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
#include "Vector3i.h"
#include "Matrix4f.h"
#include "Cuboid.h"
+#include "BoundingBox.h"
#include "Tracer.h"
#include "Group.h"
#include "BlockArea.h"
@@ -163,6 +164,13 @@ static int tolua_collect_cTracer (lua_State* tolua_S)
return 0;
}
+static int tolua_collect_cBoundingBox (lua_State* tolua_S)
+{
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ Mtolua_delete(self);
+ return 0;
+}
+
static int tolua_collect_Vector3f (lua_State* tolua_S)
{
Vector3f* self = (Vector3f*) tolua_tousertype(tolua_S,1,0);
@@ -204,66 +212,69 @@ static int tolua_collect_Vector3d (lua_State* tolua_S)
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"cThrownEnderPearlEntity");
- tolua_usertype(tolua_S,"TakeDamageInfo");
- tolua_usertype(tolua_S,"cPluginManager");
- tolua_usertype(tolua_S,"cMonster");
- tolua_usertype(tolua_S,"cCraftingGrid");
- tolua_usertype(tolua_S,"cCraftingRecipe");
- tolua_usertype(tolua_S,"cPlugin");
- tolua_usertype(tolua_S,"cWindow");
- tolua_usertype(tolua_S,"cStringMap");
- tolua_usertype(tolua_S,"cItemGrid");
- tolua_usertype(tolua_S,"cBlockArea");
+ tolua_usertype(tolua_S,"cFurnaceEntity");
+ tolua_usertype(tolua_S,"cEntity");
+ tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"cEnchantments");
- tolua_usertype(tolua_S,"cLuaWindow");
- tolua_usertype(tolua_S,"cServer");
+ tolua_usertype(tolua_S,"cMonster");
+ tolua_usertype(tolua_S,"cPluginLua");
tolua_usertype(tolua_S,"cRoot");
- tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"std::vector<cIniFile::key>");
- tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cPickup");
- tolua_usertype(tolua_S,"std::vector<std::string>");
- tolua_usertype(tolua_S,"cTracer");
- tolua_usertype(tolua_S,"cClientHandle");
+ tolua_usertype(tolua_S,"cItems");
+ tolua_usertype(tolua_S,"cFireChargeEntity");
+ tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"cChunkDesc");
tolua_usertype(tolua_S,"cFurnaceRecipe");
- tolua_usertype(tolua_S,"Vector3i");
- tolua_usertype(tolua_S,"cChatColor");
- tolua_usertype(tolua_S,"cThrownSnowballEntity");
- tolua_usertype(tolua_S,"cWebAdmin");
- tolua_usertype(tolua_S,"cCraftingRecipes");
- tolua_usertype(tolua_S,"cItems");
- tolua_usertype(tolua_S,"cWebPlugin");
- tolua_usertype(tolua_S,"cItem");
+ tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"Vector3f");
- tolua_usertype(tolua_S,"cArrowEntity");
- tolua_usertype(tolua_S,"cDropSpenserEntity");
- tolua_usertype(tolua_S,"sWebAdminPage");
- tolua_usertype(tolua_S,"HTTPFormData");
+ tolua_usertype(tolua_S,"cCraftingRecipes");
tolua_usertype(tolua_S,"cChestEntity");
tolua_usertype(tolua_S,"cDispenserEntity");
- tolua_usertype(tolua_S,"HTTPRequest");
- tolua_usertype(tolua_S,"cBlockEntity");
- tolua_usertype(tolua_S,"cItemGrid::cListener");
- tolua_usertype(tolua_S,"HTTPTemplateRequest");
- tolua_usertype(tolua_S,"cFurnaceEntity");
- tolua_usertype(tolua_S,"cDropperEntity");
- tolua_usertype(tolua_S,"cPluginLua");
- tolua_usertype(tolua_S,"cBlockEntityWithItems");
+ tolua_usertype(tolua_S,"cGhastFireballEntity");
tolua_usertype(tolua_S,"cLineBlockTracer");
+ tolua_usertype(tolua_S,"cListeners");
+ tolua_usertype(tolua_S,"cThrownSnowballEntity");
+ tolua_usertype(tolua_S,"Vector3d");
+ tolua_usertype(tolua_S,"TakeDamageInfo");
+ tolua_usertype(tolua_S,"cCraftingRecipe");
+ tolua_usertype(tolua_S,"cPlugin");
+ tolua_usertype(tolua_S,"cItemGrid");
+ tolua_usertype(tolua_S,"cBlockArea");
+ tolua_usertype(tolua_S,"cLuaWindow");
+ tolua_usertype(tolua_S,"cInventory");
+ tolua_usertype(tolua_S,"cBoundingBox");
+ tolua_usertype(tolua_S,"cBlockEntityWithItems");
+ tolua_usertype(tolua_S,"HTTPFormData");
+ tolua_usertype(tolua_S,"cTracer");
+ tolua_usertype(tolua_S,"cArrowEntity");
+ tolua_usertype(tolua_S,"cDropSpenserEntity");
+ tolua_usertype(tolua_S,"cWindow");
+ tolua_usertype(tolua_S,"Vector3i");
+ tolua_usertype(tolua_S,"cCraftingGrid");
+ tolua_usertype(tolua_S,"cGroup");
+ tolua_usertype(tolua_S,"cStringMap");
+ tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"cCriticalSection");
+ tolua_usertype(tolua_S,"HTTPTemplateRequest");
+ tolua_usertype(tolua_S,"cServer");
+ tolua_usertype(tolua_S,"std::vector<std::string>");
+ tolua_usertype(tolua_S,"cClientHandle");
+ tolua_usertype(tolua_S,"cChatColor");
+ tolua_usertype(tolua_S,"sWebAdminPage");
+ tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"cIniFile");
- tolua_usertype(tolua_S,"cEntity");
- tolua_usertype(tolua_S,"cListeners");
+ tolua_usertype(tolua_S,"cWebAdmin");
+ tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"cPawn");
- tolua_usertype(tolua_S,"cThrownEggEntity");
+ tolua_usertype(tolua_S,"cPlayer");
tolua_usertype(tolua_S,"cGroupManager");
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
- tolua_usertype(tolua_S,"cInventory");
+ tolua_usertype(tolua_S,"HTTPRequest");
tolua_usertype(tolua_S,"cProjectileEntity");
- tolua_usertype(tolua_S,"cWorld");
- tolua_usertype(tolua_S,"cPlayer");
- tolua_usertype(tolua_S,"Vector3d");
+ tolua_usertype(tolua_S,"cItemGrid::cListener");
+ tolua_usertype(tolua_S,"cDropperEntity");
+ tolua_usertype(tolua_S,"cThrownEggEntity");
}
/* method: new of class cIniFile */
@@ -4717,6 +4728,38 @@ static int tolua_AllToLua_cEntity_IsMinecart00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: IsBoat of class cEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsBoat00
+static int tolua_AllToLua_cEntity_IsBoat00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cEntity* self = (const cEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsBoat'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsBoat();
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'IsBoat'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: IsTNT of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsTNT00
static int tolua_AllToLua_cEntity_IsTNT00(lua_State* tolua_S)
@@ -6445,6 +6488,41 @@ static int tolua_AllToLua_cEntity_AddSpeedZ00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: SteerVehicle of class cEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SteerVehicle00
+static int tolua_AllToLua_cEntity_SteerVehicle00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
+ float a_Forward = ((float) tolua_tonumber(tolua_S,2,0));
+ float a_Sideways = ((float) tolua_tonumber(tolua_S,3,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SteerVehicle'", NULL);
+#endif
+ {
+ self->SteerVehicle(a_Forward,a_Sideways);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SteerVehicle'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: GetUniqueID of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_GetUniqueID00
static int tolua_AllToLua_cEntity_GetUniqueID00(lua_State* tolua_S)
@@ -6645,6 +6723,133 @@ tolua_lerror:
}
#endif //#ifndef TOLUA_DISABLE
+/* method: GetGravity of class cEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_GetGravity00
+static int tolua_AllToLua_cEntity_GetGravity00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cEntity* self = (const cEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetGravity'", NULL);
+#endif
+ {
+ float tolua_ret = (float) self->GetGravity();
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetGravity'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetGravity of class cEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SetGravity00
+static int tolua_AllToLua_cEntity_SetGravity00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
+ float a_Gravity = ((float) tolua_tonumber(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetGravity'", NULL);
+#endif
+ {
+ self->SetGravity(a_Gravity);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetGravity'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetRotationFromSpeed of class cEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SetRotationFromSpeed00
+static int tolua_AllToLua_cEntity_SetRotationFromSpeed00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetRotationFromSpeed'", NULL);
+#endif
+ {
+ self->SetRotationFromSpeed();
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetRotationFromSpeed'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetPitchFromSpeed of class cEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SetPitchFromSpeed00
+static int tolua_AllToLua_cEntity_SetPitchFromSpeed00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetPitchFromSpeed'", NULL);
+#endif
+ {
+ self->SetPitchFromSpeed();
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetPitchFromSpeed'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: GetRawDamageAgainst of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_GetRawDamageAgainst00
static int tolua_AllToLua_cEntity_GetRawDamageAgainst00(lua_State* tolua_S)
@@ -9957,6 +10162,71 @@ static int tolua_AllToLua_cArrowEntity_CanPickup00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: IsCritical of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_IsCritical00
+static int tolua_AllToLua_cArrowEntity_IsCritical00(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 'IsCritical'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsCritical();
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'IsCritical'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetIsCritical of class cArrowEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cArrowEntity_SetIsCritical00
+static int tolua_AllToLua_cArrowEntity_SetIsCritical00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cArrowEntity",0,&tolua_err) ||
+ !tolua_isboolean(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);
+ bool a_IsCritical = ((bool) tolua_toboolean(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetIsCritical'", NULL);
+#endif
+ {
+ self->SetIsCritical(a_IsCritical);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetIsCritical'.",&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)
@@ -11789,100 +12059,6 @@ static int tolua_AllToLua_cWorld_GetBlockBlockLight00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
-/* method: GetBlockTypeMeta of class cWorld */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetBlockTypeMeta00
-static int tolua_AllToLua_cWorld_GetBlockTypeMeta00(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_isnumber(tolua_S,6,0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,7,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0);
- int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0));
- int a_BlockY = ((int) tolua_tonumber(tolua_S,3,0));
- int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0));
- unsigned char a_BlockType = (( unsigned char) tolua_tonumber(tolua_S,5,0));
- unsigned char a_BlockMeta = (( unsigned char) tolua_tonumber(tolua_S,6,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetBlockTypeMeta'", NULL);
-#endif
- {
- bool tolua_ret = (bool) self->GetBlockTypeMeta(a_BlockX,a_BlockY,a_BlockZ,a_BlockType,a_BlockMeta);
- tolua_pushboolean(tolua_S,(bool)tolua_ret);
- tolua_pushnumber(tolua_S,(lua_Number)a_BlockType);
- tolua_pushnumber(tolua_S,(lua_Number)a_BlockMeta);
- }
- }
- return 3;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'GetBlockTypeMeta'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: GetBlockInfo of class cWorld */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetBlockInfo00
-static int tolua_AllToLua_cWorld_GetBlockInfo00(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_isnumber(tolua_S,6,0,&tolua_err) ||
- !tolua_isnumber(tolua_S,7,0,&tolua_err) ||
- !tolua_isnumber(tolua_S,8,0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,9,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0);
- int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0));
- int a_BlockY = ((int) tolua_tonumber(tolua_S,3,0));
- int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0));
- unsigned char a_BlockType = (( unsigned char) tolua_tonumber(tolua_S,5,0));
- unsigned char a_Meta = (( unsigned char) tolua_tonumber(tolua_S,6,0));
- unsigned char a_SkyLight = (( unsigned char) tolua_tonumber(tolua_S,7,0));
- unsigned char a_BlockLight = (( unsigned char) tolua_tonumber(tolua_S,8,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetBlockInfo'", NULL);
-#endif
- {
- bool tolua_ret = (bool) self->GetBlockInfo(a_BlockX,a_BlockY,a_BlockZ,a_BlockType,a_Meta,a_SkyLight,a_BlockLight);
- tolua_pushboolean(tolua_S,(bool)tolua_ret);
- tolua_pushnumber(tolua_S,(lua_Number)a_BlockType);
- tolua_pushnumber(tolua_S,(lua_Number)a_Meta);
- tolua_pushnumber(tolua_S,(lua_Number)a_SkyLight);
- tolua_pushnumber(tolua_S,(lua_Number)a_BlockLight);
- }
- }
- return 5;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'GetBlockInfo'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
/* method: FastSetBlock of class cWorld */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_FastSetBlock01
static int tolua_AllToLua_cWorld_FastSetBlock01(lua_State* tolua_S)
@@ -12378,9 +12554,9 @@ static int tolua_AllToLua_cWorld_WakeUpSimulatorsInArea00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
-/* method: DoExplosiontAt of class cWorld */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_DoExplosiontAt00
-static int tolua_AllToLua_cWorld_DoExplosiontAt00(lua_State* tolua_S)
+/* method: DoExplosionAt of class cWorld */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_DoExplosionAt00
+static int tolua_AllToLua_cWorld_DoExplosionAt00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
@@ -12408,16 +12584,16 @@ static int tolua_AllToLua_cWorld_DoExplosiontAt00(lua_State* tolua_S)
eExplosionSource a_Source = ((eExplosionSource) (int) tolua_tonumber(tolua_S,7,0));
void* a_SourceData = ((void*) tolua_touserdata(tolua_S,8,0));
#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'DoExplosiontAt'", NULL);
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'DoExplosionAt'", NULL);
#endif
{
- self->DoExplosiontAt(a_ExplosionSize,a_BlockX,a_BlockY,a_BlockZ,a_CanCauseFire,a_Source,a_SourceData);
+ self->DoExplosionAt(a_ExplosionSize,a_BlockX,a_BlockY,a_BlockZ,a_CanCauseFire,a_Source,a_SourceData);
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'DoExplosiontAt'.",&tolua_err);
+ tolua_error(tolua_S,"#ferror in function 'DoExplosionAt'.",&tolua_err);
return 0;
#endif
}
@@ -20811,6 +20987,114 @@ static int tolua_AllToLua_Vector3d_Cross00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: LineCoeffToXYPlane of class Vector3d */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_Vector3d_LineCoeffToXYPlane00
+static int tolua_AllToLua_Vector3d_LineCoeffToXYPlane00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const Vector3d",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const Vector3d* self = (const Vector3d*) tolua_tousertype(tolua_S,1,0);
+ const Vector3d* a_OtherEnd = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ double a_Z = ((double) tolua_tonumber(tolua_S,3,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'LineCoeffToXYPlane'", NULL);
+#endif
+ {
+ double tolua_ret = (double) self->LineCoeffToXYPlane(*a_OtherEnd,a_Z);
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'LineCoeffToXYPlane'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: LineCoeffToXZPlane of class Vector3d */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_Vector3d_LineCoeffToXZPlane00
+static int tolua_AllToLua_Vector3d_LineCoeffToXZPlane00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const Vector3d",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const Vector3d* self = (const Vector3d*) tolua_tousertype(tolua_S,1,0);
+ const Vector3d* a_OtherEnd = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ double a_Y = ((double) tolua_tonumber(tolua_S,3,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'LineCoeffToXZPlane'", NULL);
+#endif
+ {
+ double tolua_ret = (double) self->LineCoeffToXZPlane(*a_OtherEnd,a_Y);
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'LineCoeffToXZPlane'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: LineCoeffToYZPlane of class Vector3d */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_Vector3d_LineCoeffToYZPlane00
+static int tolua_AllToLua_Vector3d_LineCoeffToYZPlane00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const Vector3d",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const Vector3d* self = (const Vector3d*) tolua_tousertype(tolua_S,1,0);
+ const Vector3d* a_OtherEnd = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ double a_X = ((double) tolua_tonumber(tolua_S,3,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'LineCoeffToYZPlane'", NULL);
+#endif
+ {
+ double tolua_ret = (double) self->LineCoeffToYZPlane(*a_OtherEnd,a_X);
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'LineCoeffToYZPlane'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: Equals of class Vector3d */
#ifndef TOLUA_DISABLE_tolua_AllToLua_Vector3d_Equals00
static int tolua_AllToLua_Vector3d_Equals00(lua_State* tolua_S)
@@ -21228,6 +21512,24 @@ static int tolua_set_Vector3d_z(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* get function: EPS of class Vector3d */
+#ifndef TOLUA_DISABLE_tolua_get_Vector3d_EPS
+static int tolua_get_Vector3d_EPS(lua_State* tolua_S)
+{
+ tolua_pushnumber(tolua_S,(lua_Number)Vector3d::EPS);
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* get function: NO_INTERSECTION of class Vector3d */
+#ifndef TOLUA_DISABLE_tolua_get_Vector3d_NO_INTERSECTION
+static int tolua_get_Vector3d_NO_INTERSECTION(lua_State* tolua_S)
+{
+ tolua_pushnumber(tolua_S,(lua_Number)Vector3d::NO_INTERSECTION);
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: new of class Vector3i */
#ifndef TOLUA_DISABLE_tolua_AllToLua_Vector3i_new00
static int tolua_AllToLua_Vector3i_new00(lua_State* tolua_S)
@@ -22405,6 +22707,700 @@ static int tolua_AllToLua_cCuboid_IsSorted00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: new of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new00
+static int tolua_AllToLua_cBoundingBox_new00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",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_isnumber(tolua_S,6,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,7,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,8,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ double a_MinX = ((double) tolua_tonumber(tolua_S,2,0));
+ double a_MaxX = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_MinY = ((double) tolua_tonumber(tolua_S,4,0));
+ double a_MaxY = ((double) tolua_tonumber(tolua_S,5,0));
+ double a_MinZ = ((double) tolua_tonumber(tolua_S,6,0));
+ double a_MaxZ = ((double) tolua_tonumber(tolua_S,7,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(a_MinX,a_MaxX,a_MinY,a_MaxY,a_MinZ,a_MaxZ));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ }
+ }
+ 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 cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new00_local
+static int tolua_AllToLua_cBoundingBox_new00_local(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",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_isnumber(tolua_S,6,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,7,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,8,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ double a_MinX = ((double) tolua_tonumber(tolua_S,2,0));
+ double a_MaxX = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_MinY = ((double) tolua_tonumber(tolua_S,4,0));
+ double a_MaxY = ((double) tolua_tonumber(tolua_S,5,0));
+ double a_MinZ = ((double) tolua_tonumber(tolua_S,6,0));
+ double a_MaxZ = ((double) tolua_tonumber(tolua_S,7,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(a_MinX,a_MaxX,a_MinY,a_MaxY,a_MinZ,a_MaxZ));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ 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: new of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new01
+static int tolua_AllToLua_cBoundingBox_new01(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,3,&tolua_err) || !tolua_isusertype(tolua_S,3,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const Vector3d* a_Min = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ const Vector3d* a_Max = ((const Vector3d*) tolua_tousertype(tolua_S,3,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(*a_Min,*a_Max));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_new00(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new01_local
+static int tolua_AllToLua_cBoundingBox_new01_local(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,3,&tolua_err) || !tolua_isusertype(tolua_S,3,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const Vector3d* a_Min = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ const Vector3d* a_Max = ((const Vector3d*) tolua_tousertype(tolua_S,3,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(*a_Min,*a_Max));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_new00_local(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new02
+static int tolua_AllToLua_cBoundingBox_new02(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,4,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,5,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const Vector3d* a_Pos = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ double a_Radius = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_Height = ((double) tolua_tonumber(tolua_S,4,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(*a_Pos,a_Radius,a_Height));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_new01(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new02_local
+static int tolua_AllToLua_cBoundingBox_new02_local(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,4,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,5,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const Vector3d* a_Pos = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ double a_Radius = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_Height = ((double) tolua_tonumber(tolua_S,4,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(*a_Pos,a_Radius,a_Height));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_new01_local(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new03
+static int tolua_AllToLua_cBoundingBox_new03(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cBoundingBox",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const cBoundingBox* a_Orig = ((const cBoundingBox*) tolua_tousertype(tolua_S,2,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(*a_Orig));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_new02(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_new03_local
+static int tolua_AllToLua_cBoundingBox_new03_local(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cBoundingBox",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const cBoundingBox* a_Orig = ((const cBoundingBox*) tolua_tousertype(tolua_S,2,0));
+ {
+ cBoundingBox* tolua_ret = (cBoundingBox*) Mtolua_new((cBoundingBox)(*a_Orig));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBoundingBox");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_new02_local(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: Move of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_Move00
+static int tolua_AllToLua_cBoundingBox_Move00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",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_isnoobj(tolua_S,5,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ double a_OffX = ((double) tolua_tonumber(tolua_S,2,0));
+ double a_OffY = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_OffZ = ((double) tolua_tonumber(tolua_S,4,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Move'", NULL);
+#endif
+ {
+ self->Move(a_OffX,a_OffY,a_OffZ);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'Move'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: Move of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_Move01
+static int tolua_AllToLua_cBoundingBox_Move01(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ const Vector3d* a_Off = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Move'", NULL);
+#endif
+ {
+ self->Move(*a_Off);
+ }
+ }
+ return 0;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_Move00(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: Expand of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_Expand00
+static int tolua_AllToLua_cBoundingBox_Expand00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",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_isnoobj(tolua_S,5,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ double a_ExpandX = ((double) tolua_tonumber(tolua_S,2,0));
+ double a_ExpandY = ((double) tolua_tonumber(tolua_S,3,0));
+ double a_ExpandZ = ((double) tolua_tonumber(tolua_S,4,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Expand'", NULL);
+#endif
+ {
+ self->Expand(a_ExpandX,a_ExpandY,a_ExpandZ);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'Expand'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: DoesIntersect of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_DoesIntersect00
+static int tolua_AllToLua_cBoundingBox_DoesIntersect00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cBoundingBox",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ const cBoundingBox* a_Other = ((const cBoundingBox*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'DoesIntersect'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->DoesIntersect(*a_Other);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'DoesIntersect'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: Union of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_Union00
+static int tolua_AllToLua_cBoundingBox_Union00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cBoundingBox",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ const cBoundingBox* a_Other = ((const cBoundingBox*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Union'", NULL);
+#endif
+ {
+ cBoundingBox tolua_ret = (cBoundingBox) self->Union(*a_Other);
+ {
+#ifdef __cplusplus
+ void* tolua_obj = Mtolua_new((cBoundingBox)(tolua_ret));
+ tolua_pushusertype(tolua_S,tolua_obj,"cBoundingBox");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#else
+ void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(cBoundingBox));
+ tolua_pushusertype(tolua_S,tolua_obj,"cBoundingBox");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+#endif
+ }
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'Union'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsInside of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_IsInside00
+static int tolua_AllToLua_cBoundingBox_IsInside00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ const Vector3d* a_Point = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsInside'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsInside(*a_Point);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'IsInside'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsInside of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_IsInside01
+static int tolua_AllToLua_cBoundingBox_IsInside01(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",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_isnoobj(tolua_S,5,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ cBoundingBox* self = (cBoundingBox*) 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));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsInside'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsInside(a_X,a_Y,a_Z);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_IsInside00(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsInside of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_IsInside02
+static int tolua_AllToLua_cBoundingBox_IsInside02(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"cBoundingBox",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ cBoundingBox* a_Other = ((cBoundingBox*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsInside'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsInside(*a_Other);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_IsInside01(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsInside of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_IsInside03
+static int tolua_AllToLua_cBoundingBox_IsInside03(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,3,&tolua_err) || !tolua_isusertype(tolua_S,3,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ const Vector3d* a_Min = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ const Vector3d* a_Max = ((const Vector3d*) tolua_tousertype(tolua_S,3,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsInside'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsInside(*a_Min,*a_Max);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_IsInside02(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsInside of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_IsInside04
+static int tolua_AllToLua_cBoundingBox_IsInside04(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,3,&tolua_err) || !tolua_isusertype(tolua_S,3,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,4,&tolua_err) || !tolua_isusertype(tolua_S,4,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,5,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const Vector3d* a_Min = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ const Vector3d* a_Max = ((const Vector3d*) tolua_tousertype(tolua_S,3,0));
+ const Vector3d* a_Point = ((const Vector3d*) tolua_tousertype(tolua_S,4,0));
+ {
+ bool tolua_ret = (bool) cBoundingBox::IsInside(*a_Min,*a_Max,*a_Point);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_IsInside03(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsInside of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_IsInside05
+static int tolua_AllToLua_cBoundingBox_IsInside05(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,3,&tolua_err) || !tolua_isusertype(tolua_S,3,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,4,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,5,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,6,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,7,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const Vector3d* a_Min = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ const Vector3d* a_Max = ((const Vector3d*) tolua_tousertype(tolua_S,3,0));
+ double a_X = ((double) tolua_tonumber(tolua_S,4,0));
+ double a_Y = ((double) tolua_tonumber(tolua_S,5,0));
+ double a_Z = ((double) tolua_tonumber(tolua_S,6,0));
+ {
+ bool tolua_ret = (bool) cBoundingBox::IsInside(*a_Min,*a_Max,a_X,a_Y,a_Z);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_IsInside04(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: CalcLineIntersection of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_CalcLineIntersection00
+static int tolua_AllToLua_cBoundingBox_CalcLineIntersection00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,3,&tolua_err) || !tolua_isusertype(tolua_S,3,"const Vector3d",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
+ {
+ cBoundingBox* self = (cBoundingBox*) tolua_tousertype(tolua_S,1,0);
+ const Vector3d* a_Line1 = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ const Vector3d* a_Line2 = ((const Vector3d*) tolua_tousertype(tolua_S,3,0));
+ double a_LineCoeff = ((double) tolua_tonumber(tolua_S,4,0));
+ char a_Face = ((char) tolua_tonumber(tolua_S,5,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'CalcLineIntersection'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->CalcLineIntersection(*a_Line1,*a_Line2,a_LineCoeff,a_Face);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ tolua_pushnumber(tolua_S,(lua_Number)a_LineCoeff);
+ tolua_pushnumber(tolua_S,(lua_Number)a_Face);
+ }
+ }
+ return 3;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'CalcLineIntersection'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: CalcLineIntersection of class cBoundingBox */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cBoundingBox_CalcLineIntersection01
+static int tolua_AllToLua_cBoundingBox_CalcLineIntersection01(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cBoundingBox",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,3,&tolua_err) || !tolua_isusertype(tolua_S,3,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,4,&tolua_err) || !tolua_isusertype(tolua_S,4,"const Vector3d",0,&tolua_err)) ||
+ (tolua_isvaluenil(tolua_S,5,&tolua_err) || !tolua_isusertype(tolua_S,5,"const Vector3d",0,&tolua_err)) ||
+ !tolua_isnumber(tolua_S,6,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,7,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,8,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const Vector3d* a_Min = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
+ const Vector3d* a_Max = ((const Vector3d*) tolua_tousertype(tolua_S,3,0));
+ const Vector3d* a_Line1 = ((const Vector3d*) tolua_tousertype(tolua_S,4,0));
+ const Vector3d* a_Line2 = ((const Vector3d*) tolua_tousertype(tolua_S,5,0));
+ double a_LineCoeff = ((double) tolua_tonumber(tolua_S,6,0));
+ char a_Face = ((char) tolua_tonumber(tolua_S,7,0));
+ {
+ bool tolua_ret = (bool) cBoundingBox::CalcLineIntersection(*a_Min,*a_Max,*a_Line1,*a_Line2,a_LineCoeff,a_Face);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ tolua_pushnumber(tolua_S,(lua_Number)a_LineCoeff);
+ tolua_pushnumber(tolua_S,(lua_Number)a_Face);
+ }
+ }
+ return 3;
+tolua_lerror:
+ return tolua_AllToLua_cBoundingBox_CalcLineIntersection00(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: new of class cTracer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cTracer_new00
static int tolua_AllToLua_cTracer_new00(lua_State* tolua_S)
@@ -28367,6 +29363,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"dimOverworld",dimOverworld);
tolua_constant(tolua_S,"dimEnd",dimEnd);
tolua_constant(tolua_S,"dtAttack",dtAttack);
+ tolua_constant(tolua_S,"dtRangedAttack",dtRangedAttack);
tolua_constant(tolua_S,"dtLightning",dtLightning);
tolua_constant(tolua_S,"dtFalling",dtFalling);
tolua_constant(tolua_S,"dtDrowning",dtDrowning);
@@ -28379,11 +29376,15 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"dtFireContact",dtFireContact);
tolua_constant(tolua_S,"dtInVoid",dtInVoid);
tolua_constant(tolua_S,"dtPotionOfHarming",dtPotionOfHarming);
+ tolua_constant(tolua_S,"dtEnderPearl",dtEnderPearl);
tolua_constant(tolua_S,"dtAdmin",dtAdmin);
tolua_constant(tolua_S,"dtPawnAttack",dtPawnAttack);
tolua_constant(tolua_S,"dtEntityAttack",dtEntityAttack);
tolua_constant(tolua_S,"dtMob",dtMob);
tolua_constant(tolua_S,"dtMobAttack",dtMobAttack);
+ tolua_constant(tolua_S,"dtArrowAttack",dtArrowAttack);
+ tolua_constant(tolua_S,"dtArrow",dtArrow);
+ tolua_constant(tolua_S,"dtProjectile",dtProjectile);
tolua_constant(tolua_S,"dtFall",dtFall);
tolua_constant(tolua_S,"dtDrown",dtDrown);
tolua_constant(tolua_S,"dtSuffocation",dtSuffocation);
@@ -28431,6 +29432,12 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_array(tolua_S,"g_BlockRequiresSpecialTool",tolua_get_AllToLua_g_BlockRequiresSpecialTool,tolua_set_AllToLua_g_BlockRequiresSpecialTool);
tolua_array(tolua_S,"g_BlockIsSolid",tolua_get_AllToLua_g_BlockIsSolid,tolua_set_AllToLua_g_BlockIsSolid);
tolua_constant(tolua_S,"BLOCK_FACE_NONE",BLOCK_FACE_NONE);
+ tolua_constant(tolua_S,"BLOCK_FACE_XM",BLOCK_FACE_XM);
+ tolua_constant(tolua_S,"BLOCK_FACE_XP",BLOCK_FACE_XP);
+ tolua_constant(tolua_S,"BLOCK_FACE_YM",BLOCK_FACE_YM);
+ tolua_constant(tolua_S,"BLOCK_FACE_YP",BLOCK_FACE_YP);
+ tolua_constant(tolua_S,"BLOCK_FACE_ZM",BLOCK_FACE_ZM);
+ tolua_constant(tolua_S,"BLOCK_FACE_ZP",BLOCK_FACE_ZP);
tolua_constant(tolua_S,"BLOCK_FACE_BOTTOM",BLOCK_FACE_BOTTOM);
tolua_constant(tolua_S,"BLOCK_FACE_TOP",BLOCK_FACE_TOP);
tolua_constant(tolua_S,"BLOCK_FACE_NORTH",BLOCK_FACE_NORTH);
@@ -28583,6 +29590,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"etMonster",cEntity::etMonster);
tolua_constant(tolua_S,"etFallingBlock",cEntity::etFallingBlock);
tolua_constant(tolua_S,"etMinecart",cEntity::etMinecart);
+ tolua_constant(tolua_S,"etBoat",cEntity::etBoat);
tolua_constant(tolua_S,"etTNT",cEntity::etTNT);
tolua_constant(tolua_S,"etProjectile",cEntity::etProjectile);
tolua_constant(tolua_S,"etMob",cEntity::etMob);
@@ -28595,6 +29603,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"IsPickup",tolua_AllToLua_cEntity_IsPickup00);
tolua_function(tolua_S,"IsMob",tolua_AllToLua_cEntity_IsMob00);
tolua_function(tolua_S,"IsMinecart",tolua_AllToLua_cEntity_IsMinecart00);
+ tolua_function(tolua_S,"IsBoat",tolua_AllToLua_cEntity_IsBoat00);
tolua_function(tolua_S,"IsTNT",tolua_AllToLua_cEntity_IsTNT00);
tolua_function(tolua_S,"IsA",tolua_AllToLua_cEntity_IsA00);
tolua_function(tolua_S,"GetClass",tolua_AllToLua_cEntity_GetClass00);
@@ -28648,12 +29657,17 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"AddSpeedX",tolua_AllToLua_cEntity_AddSpeedX00);
tolua_function(tolua_S,"AddSpeedY",tolua_AllToLua_cEntity_AddSpeedY00);
tolua_function(tolua_S,"AddSpeedZ",tolua_AllToLua_cEntity_AddSpeedZ00);
+ tolua_function(tolua_S,"SteerVehicle",tolua_AllToLua_cEntity_SteerVehicle00);
tolua_function(tolua_S,"GetUniqueID",tolua_AllToLua_cEntity_GetUniqueID00);
tolua_function(tolua_S,"IsDestroyed",tolua_AllToLua_cEntity_IsDestroyed00);
tolua_function(tolua_S,"Destroy",tolua_AllToLua_cEntity_Destroy00);
tolua_function(tolua_S,"TakeDamage",tolua_AllToLua_cEntity_TakeDamage00);
tolua_function(tolua_S,"TakeDamage",tolua_AllToLua_cEntity_TakeDamage01);
tolua_function(tolua_S,"TakeDamage",tolua_AllToLua_cEntity_TakeDamage02);
+ tolua_function(tolua_S,"GetGravity",tolua_AllToLua_cEntity_GetGravity00);
+ tolua_function(tolua_S,"SetGravity",tolua_AllToLua_cEntity_SetGravity00);
+ tolua_function(tolua_S,"SetRotationFromSpeed",tolua_AllToLua_cEntity_SetRotationFromSpeed00);
+ tolua_function(tolua_S,"SetPitchFromSpeed",tolua_AllToLua_cEntity_SetPitchFromSpeed00);
tolua_function(tolua_S,"GetRawDamageAgainst",tolua_AllToLua_cEntity_GetRawDamageAgainst00);
tolua_function(tolua_S,"GetArmorCoverAgainst",tolua_AllToLua_cEntity_GetArmorCoverAgainst00);
tolua_function(tolua_S,"GetKnockbackAmountAgainst",tolua_AllToLua_cEntity_GetKnockbackAmountAgainst00);
@@ -28790,6 +29804,8 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
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_function(tolua_S,"IsCritical",tolua_AllToLua_cArrowEntity_IsCritical00);
+ tolua_function(tolua_S,"SetIsCritical",tolua_AllToLua_cArrowEntity_SetIsCritical00);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cThrownEggEntity","cThrownEggEntity","cProjectileEntity",NULL);
tolua_beginmodule(tolua_S,"cThrownEggEntity");
@@ -28800,6 +29816,12 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_cclass(tolua_S,"cThrownSnowballEntity","cThrownSnowballEntity","cProjectileEntity",NULL);
tolua_beginmodule(tolua_S,"cThrownSnowballEntity");
tolua_endmodule(tolua_S);
+ tolua_cclass(tolua_S,"cGhastFireballEntity","cGhastFireballEntity","cProjectileEntity",NULL);
+ tolua_beginmodule(tolua_S,"cGhastFireballEntity");
+ tolua_endmodule(tolua_S);
+ tolua_cclass(tolua_S,"cFireChargeEntity","cFireChargeEntity","cProjectileEntity",NULL);
+ tolua_beginmodule(tolua_S,"cFireChargeEntity");
+ 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);
@@ -28919,8 +29941,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"SetBlockMeta",tolua_AllToLua_cWorld_SetBlockMeta00);
tolua_function(tolua_S,"GetBlockSkyLight",tolua_AllToLua_cWorld_GetBlockSkyLight00);
tolua_function(tolua_S,"GetBlockBlockLight",tolua_AllToLua_cWorld_GetBlockBlockLight00);
- tolua_function(tolua_S,"GetBlockTypeMeta",tolua_AllToLua_cWorld_GetBlockTypeMeta00);
- tolua_function(tolua_S,"GetBlockInfo",tolua_AllToLua_cWorld_GetBlockInfo00);
tolua_function(tolua_S,"FastSetBlock",tolua_AllToLua_cWorld_FastSetBlock01);
tolua_function(tolua_S,"GetBlock",tolua_AllToLua_cWorld_GetBlock01);
tolua_function(tolua_S,"GetBlockMeta",tolua_AllToLua_cWorld_GetBlockMeta01);
@@ -28935,7 +29955,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetSpawnZ",tolua_AllToLua_cWorld_GetSpawnZ00);
tolua_function(tolua_S,"WakeUpSimulators",tolua_AllToLua_cWorld_WakeUpSimulators00);
tolua_function(tolua_S,"WakeUpSimulatorsInArea",tolua_AllToLua_cWorld_WakeUpSimulatorsInArea00);
- tolua_function(tolua_S,"DoExplosiontAt",tolua_AllToLua_cWorld_DoExplosiontAt00);
+ tolua_function(tolua_S,"DoExplosionAt",tolua_AllToLua_cWorld_DoExplosionAt00);
tolua_function(tolua_S,"GetSignLines",tolua_AllToLua_cWorld_GetSignLines00);
tolua_function(tolua_S,"GrowTree",tolua_AllToLua_cWorld_GrowTree00);
tolua_function(tolua_S,"GrowTreeFromSapling",tolua_AllToLua_cWorld_GrowTreeFromSapling00);
@@ -29357,6 +30377,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"SqrLength",tolua_AllToLua_Vector3d_SqrLength00);
tolua_function(tolua_S,"Dot",tolua_AllToLua_Vector3d_Dot00);
tolua_function(tolua_S,"Cross",tolua_AllToLua_Vector3d_Cross00);
+ tolua_function(tolua_S,"LineCoeffToXYPlane",tolua_AllToLua_Vector3d_LineCoeffToXYPlane00);
+ tolua_function(tolua_S,"LineCoeffToXZPlane",tolua_AllToLua_Vector3d_LineCoeffToXZPlane00);
+ tolua_function(tolua_S,"LineCoeffToYZPlane",tolua_AllToLua_Vector3d_LineCoeffToYZPlane00);
tolua_function(tolua_S,"Equals",tolua_AllToLua_Vector3d_Equals00);
tolua_function(tolua_S,".add",tolua_AllToLua_Vector3d__add00);
tolua_function(tolua_S,".add",tolua_AllToLua_Vector3d__add01);
@@ -29368,6 +30391,8 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
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);
+ tolua_variable(tolua_S,"EPS",tolua_get_Vector3d_EPS,NULL);
+ tolua_variable(tolua_S,"NO_INTERSECTION",tolua_get_Vector3d_NO_INTERSECTION,NULL);
tolua_endmodule(tolua_S);
#ifdef __cplusplus
tolua_cclass(tolua_S,"Vector3i","Vector3i","",tolua_collect_Vector3i);
@@ -29430,6 +30455,38 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"IsSorted",tolua_AllToLua_cCuboid_IsSorted00);
tolua_endmodule(tolua_S);
#ifdef __cplusplus
+ tolua_cclass(tolua_S,"cBoundingBox","cBoundingBox","",tolua_collect_cBoundingBox);
+ #else
+ tolua_cclass(tolua_S,"cBoundingBox","cBoundingBox","",NULL);
+ #endif
+ tolua_beginmodule(tolua_S,"cBoundingBox");
+ tolua_function(tolua_S,"new",tolua_AllToLua_cBoundingBox_new00);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cBoundingBox_new00_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cBoundingBox_new00_local);
+ tolua_function(tolua_S,"new",tolua_AllToLua_cBoundingBox_new01);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cBoundingBox_new01_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cBoundingBox_new01_local);
+ tolua_function(tolua_S,"new",tolua_AllToLua_cBoundingBox_new02);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cBoundingBox_new02_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cBoundingBox_new02_local);
+ tolua_function(tolua_S,"new",tolua_AllToLua_cBoundingBox_new03);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cBoundingBox_new03_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cBoundingBox_new03_local);
+ tolua_function(tolua_S,"Move",tolua_AllToLua_cBoundingBox_Move00);
+ tolua_function(tolua_S,"Move",tolua_AllToLua_cBoundingBox_Move01);
+ tolua_function(tolua_S,"Expand",tolua_AllToLua_cBoundingBox_Expand00);
+ tolua_function(tolua_S,"DoesIntersect",tolua_AllToLua_cBoundingBox_DoesIntersect00);
+ tolua_function(tolua_S,"Union",tolua_AllToLua_cBoundingBox_Union00);
+ tolua_function(tolua_S,"IsInside",tolua_AllToLua_cBoundingBox_IsInside00);
+ tolua_function(tolua_S,"IsInside",tolua_AllToLua_cBoundingBox_IsInside01);
+ tolua_function(tolua_S,"IsInside",tolua_AllToLua_cBoundingBox_IsInside02);
+ tolua_function(tolua_S,"IsInside",tolua_AllToLua_cBoundingBox_IsInside03);
+ tolua_function(tolua_S,"IsInside",tolua_AllToLua_cBoundingBox_IsInside04);
+ tolua_function(tolua_S,"IsInside",tolua_AllToLua_cBoundingBox_IsInside05);
+ tolua_function(tolua_S,"CalcLineIntersection",tolua_AllToLua_cBoundingBox_CalcLineIntersection00);
+ tolua_function(tolua_S,"CalcLineIntersection",tolua_AllToLua_cBoundingBox_CalcLineIntersection01);
+ tolua_endmodule(tolua_S);
+ #ifdef __cplusplus
tolua_cclass(tolua_S,"cTracer","cTracer","",tolua_collect_cTracer);
#else
tolua_cclass(tolua_S,"cTracer","cTracer","",NULL);
diff --git a/source/Bindings.h b/source/Bindings.h
index c706c2281..8dc9f5d4d 100644
--- a/source/Bindings.h
+++ b/source/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 09/01/13 14:42:05.
+** Generated automatically by tolua++-1.0.92 on 09/15/13 20:27:51.
*/
/* Exported function */
diff --git a/source/BlockID.cpp b/source/BlockID.cpp
index 40664647a..c3bd3c750 100644
--- a/source/BlockID.cpp
+++ b/source/BlockID.cpp
@@ -21,6 +21,7 @@ bool g_BlockPistonBreakable[256];
bool g_BlockIsSnowable[256];
bool g_BlockRequiresSpecialTool[256];
bool g_BlockIsSolid[256];
+bool g_BlockIsTorchPlaceable[256];
@@ -419,6 +420,7 @@ AString DamageTypeToString(eDamageType a_DamageType)
switch (a_DamageType)
{
case dtAttack: return "dtAttack";
+ case dtRangedAttack: return "dtRangedAttack";
case dtLightning: return "dtLightning";
case dtFalling: return "dtFalling";
case dtDrowning: return "dtDrowning";
@@ -463,6 +465,7 @@ eDamageType StringToDamageType(const AString & a_DamageTypeString)
{
// Cannonical names:
{ dtAttack, "dtAttack"},
+ { dtRangedAttack, "dtRangedAttack"},
{ dtLightning, "dtLightning"},
{ dtFalling, "dtFalling"},
{ dtDrowning, "dtDrowning"},
@@ -478,23 +481,26 @@ eDamageType StringToDamageType(const AString & a_DamageTypeString)
{ dtAdmin, "dtAdmin"},
// Common synonyms:
- { dtPawnAttack, "dtAttack"},
- { dtEntityAttack, "dtAttack"},
- { dtMob, "dtAttack"},
- { dtMobAttack, "dtAttack"},
- { dtFall, "dtFalling"},
- { dtDrown, "dtDrowning"},
- { dtSuffocation, "dtSuffocating"},
- { dtStarvation, "dtStarving"},
- { dtHunger, "dtStarving"},
- { dtCactus, "dtCactusContact"},
- { dtCactuses, "dtCactusContact"},
- { dtCacti, "dtCactusContact"},
- { dtLava, "dtLavaContact"},
- { dtPoison, "dtPoisoning"},
- { dtBurning, "dtOnFire"},
- { dtInFire, "dtFireContact"},
- { dtPlugin, "dtAdmin"},
+ { dtAttack, "dtPawnAttack"},
+ { dtAttack, "dtEntityAttack"},
+ { dtAttack, "dtMob"},
+ { dtAttack, "dtMobAttack"},
+ { dtRangedAttack, "dtArrowAttack"},
+ { dtRangedAttack, "dtArrow"},
+ { dtRangedAttack, "dtProjectile"},
+ { dtFalling, "dtFall"},
+ { dtDrowning, "dtDrown"},
+ { dtSuffocating, "dtSuffocation"},
+ { dtStarving, "dtStarvation"},
+ { dtStarving, "dtHunger"},
+ { dtCactusContact, "dtCactus"},
+ { dtCactusContact, "dtCactuses"},
+ { dtCactusContact, "dtCacti"},
+ { dtLavaContact, "dtLava"},
+ { dtPoisoning, "dtPoison"},
+ { dtOnFire, "dtBurning"},
+ { dtFireContact, "dtInFire"},
+ { dtAdmin, "dtPlugin"},
} ;
for (int i = 0; i < ARRAYCOUNT(DamageTypeMap); i++)
{
@@ -523,6 +529,7 @@ public:
memset(g_BlockTransparent, 0x00, sizeof(g_BlockTransparent));
memset(g_BlockOneHitDig, 0x00, sizeof(g_BlockOneHitDig));
memset(g_BlockPistonBreakable, 0x00, sizeof(g_BlockPistonBreakable));
+ memset(g_BlockIsTorchPlaceable, 0x00, sizeof(g_BlockIsTorchPlaceable));
// Setting bools to true must be done manually, see http://forum.mc-server.org/showthread.php?tid=629&pid=5415#pid5415
for (int i = 0; i < ARRAYCOUNT(g_BlockIsSnowable); i++)
@@ -696,6 +703,7 @@ public:
g_BlockIsSnowable[E_BLOCK_GLASS] = false;
g_BlockIsSnowable[E_BLOCK_ICE] = false;
g_BlockIsSnowable[E_BLOCK_LAVA] = false;
+ g_BlockIsSnowable[E_BLOCK_LILY_PAD] = false;
g_BlockIsSnowable[E_BLOCK_LOCKED_CHEST] = false;
g_BlockIsSnowable[E_BLOCK_REDSTONE_REPEATER_OFF] = false;
g_BlockIsSnowable[E_BLOCK_REDSTONE_REPEATER_ON] = false;
@@ -717,8 +725,9 @@ public:
g_BlockIsSnowable[E_BLOCK_WALLSIGN] = false;
g_BlockIsSnowable[E_BLOCK_WATER] = false;
g_BlockIsSnowable[E_BLOCK_YELLOW_FLOWER] = false;
+
- // Blocks that don´t drop without a special tool
+ // Blocks that don't drop without a special tool
g_BlockRequiresSpecialTool[E_BLOCK_BRICK] = true;
g_BlockRequiresSpecialTool[E_BLOCK_CAULDRON] = true;
g_BlockRequiresSpecialTool[E_BLOCK_COAL_ORE] = true;
@@ -754,31 +763,20 @@ public:
g_BlockRequiresSpecialTool[E_BLOCK_VINES] = true;
// Nonsolid Blocks:
+ g_BlockIsSolid[E_BLOCK_ACTIVATOR_RAIL] = false;
g_BlockIsSolid[E_BLOCK_AIR] = false;
- g_BlockIsSolid[E_BLOCK_BED] = false;
- g_BlockIsSolid[E_BLOCK_BIRCH_WOOD_STAIRS] = false;
- g_BlockIsSolid[E_BLOCK_BRICK_STAIRS] = false;
g_BlockIsSolid[E_BLOCK_BROWN_MUSHROOM] = false;
- g_BlockIsSolid[E_BLOCK_CACTUS] = false;
- g_BlockIsSolid[E_BLOCK_CAKE] = false;
- g_BlockIsSolid[E_BLOCK_CHEST] = false;
- g_BlockIsSolid[E_BLOCK_COBBLESTONE_STAIRS] = false;
+ g_BlockIsSolid[E_BLOCK_CARROTS] = false;
+ g_BlockIsSolid[E_BLOCK_COBWEB] = false;
g_BlockIsSolid[E_BLOCK_CROPS] = false;
- g_BlockIsSolid[E_BLOCK_ENCHANTMENT_TABLE] = false;
+ g_BlockIsSolid[E_BLOCK_DETECTOR_RAIL] = false;
g_BlockIsSolid[E_BLOCK_END_PORTAL] = false;
- g_BlockIsSolid[E_BLOCK_END_PORTAL_FRAME] = false;
- g_BlockIsSolid[E_BLOCK_FARMLAND] = false;
- g_BlockIsSolid[E_BLOCK_FENCE] = false;
g_BlockIsSolid[E_BLOCK_FIRE] = false;
- g_BlockIsSolid[E_BLOCK_GLASS] = false;
- g_BlockIsSolid[E_BLOCK_IRON_DOOR] = false;
- g_BlockIsSolid[E_BLOCK_JUNGLE_WOOD_STAIRS] = false;
- g_BlockIsSolid[E_BLOCK_LADDER] = false;
+ g_BlockIsSolid[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE] = false;
g_BlockIsSolid[E_BLOCK_LAVA] = false;
- g_BlockIsSolid[E_BLOCK_LEAVES] = false;
g_BlockIsSolid[E_BLOCK_LEVER] = false;
- g_BlockIsSolid[E_BLOCK_LOCKED_CHEST] = false;
- g_BlockIsSolid[E_BLOCK_NETHER_BRICK_STAIRS] = false;
+ g_BlockIsSolid[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE] = false;
+ g_BlockIsSolid[E_BLOCK_MELON_STEM] = false;
g_BlockIsSolid[E_BLOCK_NETHER_PORTAL] = false;
g_BlockIsSolid[E_BLOCK_PISTON] = false;
g_BlockIsSolid[E_BLOCK_PISTON_EXTENSION] = false;
@@ -791,29 +789,84 @@ public:
g_BlockIsSolid[E_BLOCK_RED_MUSHROOM] = false;
g_BlockIsSolid[E_BLOCK_RED_ROSE] = false;
g_BlockIsSolid[E_BLOCK_REEDS] = false;
- g_BlockIsSolid[E_BLOCK_SANDSTONE_STAIRS] = false;
g_BlockIsSolid[E_BLOCK_SAPLING] = false;
g_BlockIsSolid[E_BLOCK_SIGN_POST] = false;
g_BlockIsSolid[E_BLOCK_SNOW] = false;
- g_BlockIsSolid[E_BLOCK_SPRUCE_WOOD_STAIRS] = false;
g_BlockIsSolid[E_BLOCK_STATIONARY_LAVA] = false;
g_BlockIsSolid[E_BLOCK_STATIONARY_WATER] = false;
- g_BlockIsSolid[E_BLOCK_STONE_BRICK_STAIRS] = false;
g_BlockIsSolid[E_BLOCK_STONE_BUTTON] = false;
g_BlockIsSolid[E_BLOCK_STONE_PRESSURE_PLATE] = false;
- g_BlockIsSolid[E_BLOCK_STONE_SLAB] = false;
g_BlockIsSolid[E_BLOCK_TALL_GRASS] = false;
- g_BlockIsSolid[E_BLOCK_TNT] = false;
g_BlockIsSolid[E_BLOCK_TORCH] = false;
- g_BlockIsSolid[E_BLOCK_TRAPDOOR] = false;
+ g_BlockIsSolid[E_BLOCK_TRIPWIRE] = false;
g_BlockIsSolid[E_BLOCK_VINES] = false;
g_BlockIsSolid[E_BLOCK_WALLSIGN] = false;
g_BlockIsSolid[E_BLOCK_WATER] = false;
g_BlockIsSolid[E_BLOCK_WOODEN_BUTTON] = false;
- g_BlockIsSolid[E_BLOCK_WOODEN_DOOR] = false;
g_BlockIsSolid[E_BLOCK_WOODEN_PRESSURE_PLATE] = false;
g_BlockIsSolid[E_BLOCK_WOODEN_SLAB] = false;
g_BlockIsSolid[E_BLOCK_YELLOW_FLOWER] = false;
+
+ // Torch placeable
+ g_BlockIsTorchPlaceable[E_BLOCK_BEDROCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_COAL] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_REDSTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BOOKCASE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BRICK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_CLAY] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_COAL_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_COBBLESTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_COMMAND_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_CRAFTING_TABLE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DIAMOND_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DIAMOND_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DIRT] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DISPENSER] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DOUBLE_STONE_SLAB] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DOUBLE_WOODEN_SLAB] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DROPPER] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_EMERALD_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_EMERALD_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_END_STONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_FURNACE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GLOWSTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GOLD_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GOLD_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GRASS] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GRAVEL] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HARDENED_CLAY] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HAY_BALE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HUGE_BROWN_MUSHROOM] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HUGE_RED_MUSHROOM] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_IRON_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_IRON_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_JACK_O_LANTERN] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_JUKEBOX] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_LAPIS_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_LAPIS_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_LOG] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_MELON] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_MOSSY_COBBLESTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_MYCELIUM] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NETHERRACK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NETHER_BRICK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NETHER_QUARTZ_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NOTE_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_OBSIDIAN] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_PLANKS] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_PUMPKIN] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_QUARTZ_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_LAMP_OFF] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_LAMP_ON] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_ORE_GLOWING] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SANDSTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SAND] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SILVERFISH_EGG] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SPONGE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_STAINED_CLAY] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_WOOL] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_STONE] = true;
}
} BlockPropertiesInitializer;
diff --git a/source/BlockID.h b/source/BlockID.h
index 40da3c651..7971b4f84 100644
--- a/source/BlockID.h
+++ b/source/BlockID.h
@@ -165,7 +165,7 @@ enum ENUM_BLOCK_ID
E_BLOCK_NETHER_QUARTZ_ORE = 153,
E_BLOCK_HOPPER = 154,
E_BLOCK_QUARTZ_BLOCK = 155,
- E_BLOCK_QUARTZ_STAIR = 156,
+ E_BLOCK_QUARTZ_STAIRS = 156,
E_BLOCK_ACTIVATOR_RAIL = 157,
E_BLOCK_DROPPER = 158,
@@ -659,6 +659,7 @@ enum eDamageType
{
// Canonical names for the types (as documented in the plugin wiki):
dtAttack, // Being attacked by a mob
+ dtRangedAttack, // Being attacked by a projectile, possibly from a mob
dtLightning, // Hit by a lightning strike
dtFalling, // Falling down; dealt when hitting the ground
dtDrowning, // Drowning in water / lava
@@ -671,6 +672,7 @@ enum eDamageType
dtFireContact, // Standing inside a fire block
dtInVoid, // Falling into the Void (Y < 0)
dtPotionOfHarming,
+ dtEnderPearl, // Thrown an ender pearl, teleported by it
dtAdmin, // Damage applied by an admin command
// Some common synonyms:
@@ -678,6 +680,9 @@ enum eDamageType
dtEntityAttack = dtAttack,
dtMob = dtAttack,
dtMobAttack = dtAttack,
+ dtArrowAttack = dtRangedAttack,
+ dtArrow = dtRangedAttack,
+ dtProjectile = dtRangedAttack,
dtFall = dtFalling,
dtDrown = dtDrowning,
dtSuffocation = dtSuffocating,
@@ -770,7 +775,7 @@ extern bool g_BlockPistonBreakable[256];
extern bool g_BlockIsSnowable[256];
extern bool g_BlockRequiresSpecialTool[256];
extern bool g_BlockIsSolid[256];
-
+extern bool g_BlockIsTorchPlaceable[256];
diff --git a/source/Blocks/BlockBed.cpp b/source/Blocks/BlockBed.cpp
index f5e9db88d..66eb9130c 100644
--- a/source/Blocks/BlockBed.cpp
+++ b/source/Blocks/BlockBed.cpp
@@ -56,7 +56,7 @@ void cBlockBedHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, i
if (a_World->GetDimension() != dimOverworld)
{
Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ);
- a_World->DoExplosiontAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords);
+ a_World->DoExplosionAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords);
}
else
{
diff --git a/source/Blocks/BlockBed.h b/source/Blocks/BlockBed.h
index 0bf1cfc0f..8a289b22c 100644
--- a/source/Blocks/BlockBed.h
+++ b/source/Blocks/BlockBed.h
@@ -37,12 +37,6 @@ public:
}
- virtual bool DoesAllowBlockOnTop() override
- {
- return false;
- }
-
-
// Bed specific helper functions
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
diff --git a/source/Blocks/BlockCactus.h b/source/Blocks/BlockCactus.h
index 1d123bc0a..4147ad473 100644
--- a/source/Blocks/BlockCactus.h
+++ b/source/Blocks/BlockCactus.h
@@ -63,12 +63,6 @@ public:
return true;
}
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
void OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
diff --git a/source/Blocks/BlockCrops.h b/source/Blocks/BlockCrops.h
index 4bc76fd50..9e19b14ec 100644
--- a/source/Blocks/BlockCrops.h
+++ b/source/Blocks/BlockCrops.h
@@ -20,12 +20,6 @@ public:
}
- virtual bool DoesAllowBlockOnTop() override
- {
- return false;
- }
-
-
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_Meta) override
{
MTRand rand;
diff --git a/source/Blocks/BlockDeadBush.h b/source/Blocks/BlockDeadBush.h
index 379e8e5df..14617d006 100644
--- a/source/Blocks/BlockDeadBush.h
+++ b/source/Blocks/BlockDeadBush.h
@@ -28,18 +28,6 @@ public:
{
return (a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_SAND);
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
-
- virtual bool CanBePlacedOnSide() override
- {
- return false;
- }
} ;
diff --git a/source/Blocks/BlockDoor.cpp b/source/Blocks/BlockDoor.cpp
index 02cbd28e2..e71ccd368 100644
--- a/source/Blocks/BlockDoor.cpp
+++ b/source/Blocks/BlockDoor.cpp
@@ -3,7 +3,6 @@
#include "BlockDoor.h"
#include "../Item.h"
#include "../World.h"
-#include "../Doors.h"
#include "../Entities/Player.h"
@@ -26,7 +25,7 @@ void cBlockDoorHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY
if (OldMeta & 8)
{
// Was upper part of door
- if (cDoors::IsDoor(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
+ if (IsDoor(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
{
a_World->FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
}
@@ -34,7 +33,7 @@ void cBlockDoorHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY
else
{
// Was lower part
- if (cDoors::IsDoor(a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)))
+ if (IsDoor(a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)))
{
a_World->FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_AIR, 0);
}
@@ -49,7 +48,7 @@ void cBlockDoorHandler::OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX
{
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR)
{
- cDoors::ChangeDoor(a_World, a_BlockX, a_BlockY, a_BlockZ);
+ ChangeDoor(a_World, a_BlockX, a_BlockY, a_BlockZ);
}
}
diff --git a/source/Blocks/BlockDoor.h b/source/Blocks/BlockDoor.h
index 4978fee38..03a79d47d 100644
--- a/source/Blocks/BlockDoor.h
+++ b/source/Blocks/BlockDoor.h
@@ -3,7 +3,6 @@
#include "BlockHandler.h"
#include "../World.h"
-#include "../Doors.h"
#include "../Entities/Player.h"
@@ -43,7 +42,7 @@ public:
}
a_BlockType = m_BlockType;
- a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation());
+ a_BlockMeta = PlayerYawToMetaData(a_Player->GetRotation());
return true;
}
@@ -68,12 +67,6 @@ public:
}
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
-
-
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
@@ -98,6 +91,83 @@ public:
}
return false;
}
+
+
+ /// Converts the player's yaw to placed door's blockmeta
+ inline static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
+ {
+ ASSERT((a_Yaw >= -180) && (a_Yaw < 180));
+
+ a_Yaw += 90 + 45;
+ if (a_Yaw > 360)
+ {
+ a_Yaw -= 360;
+ }
+ if ((a_Yaw >= 0) && (a_Yaw < 90))
+ {
+ return 0x0;
+ }
+ else if ((a_Yaw >= 180) && (a_Yaw < 270))
+ {
+ return 0x2;
+ }
+ else if ((a_Yaw >= 90) && (a_Yaw < 180))
+ {
+ return 0x1;
+ }
+ else
+ {
+ return 0x3;
+ }
+ }
+
+
+ /// Returns true if the specified blocktype is any kind of door
+ inline static bool IsDoor(BLOCKTYPE a_Block)
+ {
+ return (a_Block == E_BLOCK_WOODEN_DOOR) || (a_Block == E_BLOCK_IRON_DOOR);
+ }
+
+
+ /// Returns the metadata for the opposite door state (open vs closed)
+ static NIBBLETYPE ChangeStateMetaData(NIBBLETYPE a_MetaData)
+ {
+ return a_MetaData ^ 4;
+ }
+
+
+ /// Changes the door at the specified coords from open to close or vice versa
+ static void ChangeDoor(cWorld * a_World, int a_X, int a_Y, int a_Z)
+ {
+ NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ a_World->SetBlockMeta(a_X, a_Y, a_Z, ChangeStateMetaData(OldMetaData));
+
+ if (OldMetaData & 8)
+ {
+ // Current block is top of the door
+ BLOCKTYPE BottomBlock = a_World->GetBlock(a_X, a_Y - 1, a_Z);
+ NIBBLETYPE BottomMeta = a_World->GetBlockMeta(a_X, a_Y - 1, a_Z);
+
+ if (IsDoor(BottomBlock) && !(BottomMeta & 8))
+ {
+ a_World->SetBlockMeta(a_X, a_Y - 1, a_Z, ChangeStateMetaData(BottomMeta));
+ }
+ }
+ else
+ {
+ // Current block is bottom of the door
+ BLOCKTYPE TopBlock = a_World->GetBlock(a_X, a_Y + 1, a_Z);
+ NIBBLETYPE TopMeta = a_World->GetBlockMeta(a_X, a_Y + 1, a_Z);
+
+ if (IsDoor(TopBlock) && (TopMeta & 8))
+ {
+ a_World->SetBlockMeta(a_X, a_Y + 1, a_Z, ChangeStateMetaData(TopMeta));
+ }
+ }
+ }
+
+
} ;
diff --git a/source/Blocks/BlockFenceGate.h b/source/Blocks/BlockFenceGate.h
index d6f8aa85f..6423a7cb0 100644
--- a/source/Blocks/BlockFenceGate.h
+++ b/source/Blocks/BlockFenceGate.h
@@ -2,7 +2,6 @@
#pragma once
#include "BlockHandler.h"
-#include "../Doors.h"
@@ -26,7 +25,7 @@ public:
) override
{
a_BlockType = m_BlockType;
- a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation() + 270);
+ a_BlockMeta = PlayerYawToMetaData(a_Player->GetRotation());
return true;
}
@@ -34,7 +33,7 @@ public:
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- NIBBLETYPE NewMetaData = cDoors::RotationToMetaData(a_Player->GetRotation() + 270);
+ NIBBLETYPE NewMetaData = PlayerYawToMetaData(a_Player->GetRotation());
OldMetaData ^= 4; // Toggle the gate
if ((OldMetaData & 1) == (NewMetaData & 1))
{
@@ -53,6 +52,35 @@ public:
{
return true;
}
+
+
+ /// Converts the player's yaw to placed gate's blockmeta
+ inline static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
+ {
+ ASSERT((a_Yaw >= -180) && (a_Yaw < 180));
+
+ a_Yaw += 360 + 45;
+ if (a_Yaw > 360)
+ {
+ a_Yaw -= 360;
+ }
+ if ((a_Yaw >= 0) && (a_Yaw < 90))
+ {
+ return 0x0;
+ }
+ else if ((a_Yaw >= 180) && (a_Yaw < 270))
+ {
+ return 0x2;
+ }
+ else if ((a_Yaw >= 90) && (a_Yaw < 180))
+ {
+ return 0x1;
+ }
+ else
+ {
+ return 0x3;
+ }
+ }
} ;
diff --git a/source/Blocks/BlockFlower.h b/source/Blocks/BlockFlower.h
index 952901ba5..421e2d5d8 100644
--- a/source/Blocks/BlockFlower.h
+++ b/source/Blocks/BlockFlower.h
@@ -30,18 +30,6 @@ public:
}
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return true;
- }
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
-
-
virtual const char * GetStepSound(void) override
{
return "step.grass";
diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp
index 2627ac6b4..3e97d1e9d 100644
--- a/source/Blocks/BlockHandler.cpp
+++ b/source/Blocks/BlockHandler.cpp
@@ -41,6 +41,7 @@
#include "BlockNote.h"
#include "BlockOre.h"
#include "BlockPiston.h"
+#include "BlockPumpkin.h"
#include "BlockRail.h"
#include "BlockRedstone.h"
#include "BlockRedstoneRepeater.h"
@@ -153,8 +154,10 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType);
case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler ();
case E_BLOCK_PLANKS: return new cBlockWoodHandler (a_BlockType);
+ case E_BLOCK_PUMPKIN: return new cBlockPumpkinHandler (a_BlockType);
+ case E_BLOCK_JACK_O_LANTERN: return new cBlockPumpkinHandler (a_BlockType);
case E_BLOCK_PUMPKIN_STEM: return new cBlockStemsHandler (a_BlockType);
- case E_BLOCK_QUARTZ_STAIR: return new cBlockStairsHandler (a_BlockType);
+ case E_BLOCK_QUARTZ_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_POTATOES: return new cBlockCropsHandler (a_BlockType);
case E_BLOCK_POWERED_RAIL: return new cBlockRailHandler (a_BlockType);
@@ -412,24 +415,6 @@ bool cBlockHandler::DoesIgnoreBuildCollision(void)
-bool cBlockHandler::DoesAllowBlockOnTop(void)
-{
- return true;
-}
-
-
-
-
-
-bool cBlockHandler::CanBePlacedOnSide(void)
-{
- return true;
-}
-
-
-
-
-
bool cBlockHandler::DoesDropOnUnsuitable(void)
{
return true;
diff --git a/source/Blocks/BlockHandler.h b/source/Blocks/BlockHandler.h
index 228ce174b..0487505ee 100644
--- a/source/Blocks/BlockHandler.h
+++ b/source/Blocks/BlockHandler.h
@@ -83,10 +83,7 @@ public:
NOTE: This call doesn't actually place the block
*/
// virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
-
- /// Called when the player tries to place a block on top of this block (Only if he aims directly on this block); return false to disallow
- virtual bool DoesAllowBlockOnTop(void);
-
+
/// Called to check whether this block supports a rclk action. If it returns true, OnUse() is called
virtual bool IsUseable(void);
@@ -99,9 +96,6 @@ public:
For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision
*/
virtual bool DoesIgnoreBuildCollision(void);
-
- /// Indicates this block can be placed on the side of other blocks. Default: true
- virtual bool CanBePlacedOnSide(void);
/// Does this block drop if it gets destroyed by an unsuitable situation? Default: true
virtual bool DoesDropOnUnsuitable(void);
diff --git a/source/Blocks/BlockLever.h b/source/Blocks/BlockLever.h
index 362cf563e..ddf48297c 100644
--- a/source/Blocks/BlockLever.h
+++ b/source/Blocks/BlockLever.h
@@ -42,12 +42,6 @@ public:
a_BlockMeta = cRedstoneSimulator::LeverDirectionToMetaData(a_BlockFace);
return true;
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockMushroom.h b/source/Blocks/BlockMushroom.h
index b3b23e2ba..2846a6317 100644
--- a/source/Blocks/BlockMushroom.h
+++ b/source/Blocks/BlockMushroom.h
@@ -46,18 +46,6 @@ public:
}
return true;
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockMycelium.h b/source/Blocks/BlockMycelium.h
index 0ed7162ac..7f897c72a 100644
--- a/source/Blocks/BlockMycelium.h
+++ b/source/Blocks/BlockMycelium.h
@@ -20,6 +20,11 @@ public:
{
a_Pickups.push_back(cItem(E_BLOCK_DIRT, 1, 0));
}
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.gravel";
+ }
} ;
diff --git a/source/Blocks/BlockPumpkin.h b/source/Blocks/BlockPumpkin.h
new file mode 100644
index 000000000..76abc6818
--- /dev/null
+++ b/source/Blocks/BlockPumpkin.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+class cBlockPumpkinHandler :
+ public cBlockHandler
+{
+public:
+ cBlockPumpkinHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = m_BlockType;
+ a_BlockMeta = PlayerYawToMetaData(a_Player->GetRotation());
+ return true;
+ }
+
+ inline static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
+ {
+ ASSERT((a_Yaw >= -180) && (a_Yaw < 180));
+
+ a_Yaw += 180 + 45;
+ if (a_Yaw > 360)
+ {
+ a_Yaw -= 360;
+ }
+ if ((a_Yaw >= 0) && (a_Yaw < 90))
+ {
+ return 0x0;
+ }
+ else if ((a_Yaw >= 180) && (a_Yaw < 270))
+ {
+ return 0x2;
+ }
+ else if ((a_Yaw >= 90) && (a_Yaw < 180))
+ {
+ return 0x1;
+ }
+ else
+ {
+ return 0x3;
+ }
+ }
+
+} ;
+
+
+
+
diff --git a/source/Blocks/BlockRedstone.h b/source/Blocks/BlockRedstone.h
index ae0466937..f28f3f2d6 100644
--- a/source/Blocks/BlockRedstone.h
+++ b/source/Blocks/BlockRedstone.h
@@ -16,11 +16,6 @@ public:
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
@@ -33,12 +28,6 @@ public:
// Reset meta to 0
a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, 1));
}
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
} ;
diff --git a/source/Blocks/BlockRedstoneRepeater.h b/source/Blocks/BlockRedstoneRepeater.h
index f3e250963..24250ab86 100644
--- a/source/Blocks/BlockRedstoneRepeater.h
+++ b/source/Blocks/BlockRedstoneRepeater.h
@@ -32,23 +32,11 @@ public:
}
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
-
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
}
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
-
virtual const char * GetStepSound(void) override
{
return "step.wood";
diff --git a/source/Blocks/BlockSapling.h b/source/Blocks/BlockSapling.h
index 17ef4984f..fff2fa88b 100644
--- a/source/Blocks/BlockSapling.h
+++ b/source/Blocks/BlockSapling.h
@@ -29,12 +29,6 @@ public:
{
return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ));
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
void OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
@@ -50,12 +44,6 @@ public:
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x08);
}
}
-
-
- virtual bool CanBePlacedOnSide() override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockSign.h b/source/Blocks/BlockSign.h
index e6426180f..7fbe61893 100644
--- a/source/Blocks/BlockSign.h
+++ b/source/Blocks/BlockSign.h
@@ -23,12 +23,6 @@ public:
{
a_Pickups.push_back(cItem(E_ITEM_SIGN, 1, 0));
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockSugarcane.h b/source/Blocks/BlockSugarcane.h
index 9d66d6be6..28a60df80 100644
--- a/source/Blocks/BlockSugarcane.h
+++ b/source/Blocks/BlockSugarcane.h
@@ -77,12 +77,6 @@ public:
{
a_World->GrowSugarcane(a_BlockX, a_BlockY, a_BlockZ, 1);
}
-
-
- virtual bool CanBePlacedOnSide() override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockTorch.h b/source/Blocks/BlockTorch.h
index 3a50cab77..b9e0dbf27 100644
--- a/source/Blocks/BlockTorch.h
+++ b/source/Blocks/BlockTorch.h
@@ -24,16 +24,31 @@ public:
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
- // Find proper placement. Use the player-supplied one as the default, but fix if not okay:
- if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
+ // Find proper placement of torch
+
+ if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM))
{
- a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ);
-
- if (a_BlockFace == BLOCK_FACE_BOTTOM)
+ a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ); // Top or bottom faces clicked, find a suitable face
+ if (a_BlockFace == BLOCK_FACE_NONE)
{
+ // Client wouldn't have sent anything anyway, but whatever
return false;
}
}
+ else
+ {
+ // Not top or bottom faces, try to preserve whatever face was clicked
+ if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
+ {
+ // Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
+ a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ);
+ if (a_BlockFace == BLOCK_FACE_NONE)
+ {
+ return false;
+ }
+ }
+ }
+
a_BlockType = m_BlockType;
a_BlockMeta = DirectionToMetaData(a_BlockFace);
return true;
@@ -100,51 +115,58 @@ public:
}
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return true;
- }
-
-
- static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_Direction)
+ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_BlockFace)
{
- if ( g_BlockIsSolid[a_BlockType] ) {
- return (a_Direction == 0x1); // allow only direction "standing on floor"
+ if ( !g_BlockIsTorchPlaceable[a_BlockType] )
+ {
+ return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright
}
- else {
- return g_BlockIsSolid[a_BlockType];
+ else
+ {
+ return true;
}
}
static bool TorchCanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
- // TODO: If placing a torch from below, check all 4 XZ neighbors, place it on that neighbor instead
- // How to propagate that change up?
- // Simon: The easiest way is to calculate the position two times, shouldn�t cost much cpu power :)
-
- if (a_BlockFace == BLOCK_FACE_BOTTOM)
- {
- return false;
- }
-
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
-
return CanBePlacedOn(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ), a_BlockFace);
}
- /// Finds a suitable Face for the Torch. Returns BLOCK_FACE_BOTTOM on failure
+ /// Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure
static char FindSuitableFace(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- for (int i = 1; i <= 5; i++)
+ // TODO: If placing a torch from below, check all 4 XZ neighbors, place it on that neighbor instead
+ // How to propagate that change up?
+ // Simon: The easiest way is to calculate the position two times, shouldn't cost much cpu power :)
+
+ for (int i = 0; i <= 5; i++)
{
- if (TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, i))
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, i, true);
+ BLOCKTYPE BlockInQuestion = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+
+ if (
+ ((BlockInQuestion == E_BLOCK_GLASS) ||
+ (BlockInQuestion == E_BLOCK_FENCE) ||
+ (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
+ (BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)) &&
+ (i = 1)
+ )
+ {
+ return i;
+ }
+ else if ( g_BlockIsTorchPlaceable[BlockInQuestion] )
{
return i;
}
+ else
+ {
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, i, false);
+ }
}
- return BLOCK_FACE_BOTTOM;
+ return BLOCK_FACE_NONE;
}
@@ -163,11 +185,28 @@ public:
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- // TODO: Use AdjustCoordsByMeta(), then cChunk::UnboundedRelGetBlock() and finally some comparison
char Face = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
- return TorchCanBePlacedAt(a_Chunk.GetWorld(), BlockX, a_RelY, BlockZ, Face);
+
+ AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true);
+ BLOCKTYPE BlockInQuestion;
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockInQuestion);
+
+ if ((BlockInQuestion == E_BLOCK_GLASS) || (BlockInQuestion == E_BLOCK_FENCE) || (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE))
+ {
+ // Torches can be placed on tops of glass and fences, despite them being 'untorcheable'
+ // No need to check for upright orientation, it was done when the torch was placed
+ return true;
+ }
+ else if ( !g_BlockIsTorchPlaceable[BlockInQuestion] )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
diff --git a/source/BoundingBox.cpp b/source/BoundingBox.cpp
new file mode 100644
index 000000000..d8a1bc679
--- /dev/null
+++ b/source/BoundingBox.cpp
@@ -0,0 +1,331 @@
+
+// BoundingBox.cpp
+
+// Implements the cBoundingBox class representing an axis-aligned bounding box with floatingpoint coords
+
+#include "Globals.h"
+#include "BoundingBox.h"
+#include "Defines.h"
+
+
+
+
+
+#if 0
+
+/// A simple self-test that is executed on program start, used to verify bbox functionality
+class SelfTest
+{
+public:
+ SelfTest(void)
+ {
+ Vector3d Min(1, 1, 1);
+ Vector3d Max(2, 2, 2);
+ Vector3d LineDefs[] =
+ {
+ Vector3d(1.5, 4, 1.5), Vector3d(1.5, 3, 1.5), // Should intersect at 2, face 1 (YP)
+ Vector3d(1.5, 0, 1.5), Vector3d(1.5, 4, 1.5), // Should intersect at 0.25, face 0 (YM)
+ Vector3d(0, 0, 0), Vector3d(2, 2, 2), // Should intersect at 0.5, face 0, 3 or 5 (anyM)
+ Vector3d(0.999, 0, 1.5), Vector3d(0.999, 4, 1.5), // Should not intersect
+ Vector3d(1.999, 0, 1.5), Vector3d(1.999, 4, 1.5), // Should intersect at 0.25, face 0 (YM)
+ Vector3d(2.001, 0, 1.5), Vector3d(2.001, 4, 1.5), // Should not intersect
+ } ;
+ for (int i = 0; i < ARRAYCOUNT(LineDefs) / 2; i++)
+ {
+ double LineCoeff;
+ char Face;
+ Vector3d Line1 = LineDefs[2 * i];
+ Vector3d Line2 = LineDefs[2 * i + 1];
+ bool res = cBoundingBox::CalcLineIntersection(Min, Max, Line1, Line2, LineCoeff, Face);
+ printf("LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d\n",
+ Line1.x, Line1.y, Line1.z,
+ Line2.x, Line2.y, Line2.z,
+ res ? 1 : 0, LineCoeff, Face
+ );
+ } // for i - LineDefs[]
+ printf("BoundingBox selftest complete.");
+ }
+} Test;
+
+#endif
+
+
+
+
+
+cBoundingBox::cBoundingBox(double a_MinX, double a_MaxX, double a_MinY, double a_MaxY, double a_MinZ, double a_MaxZ) :
+ m_Min(a_MinX, a_MinY, a_MinZ),
+ m_Max(a_MaxX, a_MaxY, a_MaxZ)
+{
+}
+
+
+
+
+
+cBoundingBox::cBoundingBox(const Vector3d & a_Min, const Vector3d & a_Max) :
+ m_Min(a_Min),
+ m_Max(a_Max)
+{
+}
+
+
+
+
+
+cBoundingBox::cBoundingBox(const Vector3d & a_Pos, double a_Radius, double a_Height) :
+ m_Min(a_Pos.x - a_Radius, a_Pos.y, a_Pos.z - a_Radius),
+ m_Max(a_Pos.x + a_Radius, a_Pos.y + a_Height, a_Pos.z + a_Radius)
+{
+}
+
+
+
+
+
+cBoundingBox::cBoundingBox(const cBoundingBox & a_Orig) :
+ m_Min(a_Orig.m_Min),
+ m_Max(a_Orig.m_Max)
+{
+}
+
+
+
+
+
+void cBoundingBox::Move(double a_OffX, double a_OffY, double a_OffZ)
+{
+ m_Min.x += a_OffX;
+ m_Min.y += a_OffY;
+ m_Min.z += a_OffZ;
+ m_Max.x += a_OffX;
+ m_Max.y += a_OffY;
+ m_Max.z += a_OffZ;
+}
+
+
+
+
+
+void cBoundingBox::Move(const Vector3d & a_Off)
+{
+ m_Min.x += a_Off.x;
+ m_Min.y += a_Off.y;
+ m_Min.z += a_Off.z;
+ m_Max.x += a_Off.x;
+ m_Max.y += a_Off.y;
+ m_Max.z += a_Off.z;
+}
+
+
+
+
+
+void cBoundingBox::Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ)
+{
+ m_Min.x -= a_ExpandX;
+ m_Min.y -= a_ExpandY;
+ m_Min.z -= a_ExpandZ;
+ m_Max.x += a_ExpandX;
+ m_Max.y += a_ExpandY;
+ m_Max.z += a_ExpandZ;
+}
+
+
+
+
+
+bool cBoundingBox::DoesIntersect(const cBoundingBox & a_Other)
+{
+ return (
+ ((a_Other.m_Min.x <= m_Max.x) && (a_Other.m_Max.x >= m_Min.x)) && // X coords intersect
+ ((a_Other.m_Min.y <= m_Max.y) && (a_Other.m_Max.y >= m_Min.y)) && // Y coords intersect
+ ((a_Other.m_Min.z <= m_Max.z) && (a_Other.m_Max.z >= m_Min.z)) // Z coords intersect
+ );
+}
+
+
+
+
+
+cBoundingBox cBoundingBox::Union(const cBoundingBox & a_Other)
+{
+ return cBoundingBox(
+ std::min(m_Min.x, a_Other.m_Min.x),
+ std::min(m_Min.y, a_Other.m_Min.y),
+ std::min(m_Min.z, a_Other.m_Min.z),
+ std::max(m_Max.x, a_Other.m_Max.x),
+ std::max(m_Max.y, a_Other.m_Max.y),
+ std::max(m_Max.z, a_Other.m_Max.z)
+ );
+}
+
+
+
+
+
+bool cBoundingBox::IsInside(const Vector3d & a_Point)
+{
+ return IsInside(m_Min, m_Max, a_Point);
+}
+
+
+
+
+
+bool cBoundingBox::IsInside(double a_X, double a_Y,double a_Z)
+{
+ return IsInside(m_Min, m_Max, a_X, a_Y, a_Z);
+}
+
+
+
+
+
+bool cBoundingBox::IsInside(cBoundingBox & a_Other)
+{
+ // If both a_Other's coords are inside this, then the entire a_Other is inside
+ return (IsInside(a_Other.m_Min) && IsInside(a_Other.m_Max));
+}
+
+
+
+
+
+bool cBoundingBox::IsInside(const Vector3d & a_Min, const Vector3d & a_Max)
+{
+ // If both coords are inside this, then the entire a_Other is inside
+ return (IsInside(a_Min) && IsInside(a_Max));
+}
+
+
+
+
+
+bool cBoundingBox::IsInside(const Vector3d & a_Min, const Vector3d & a_Max, const Vector3d & a_Point)
+{
+ return (
+ ((a_Point.x >= a_Min.x) && (a_Point.x <= a_Max.x)) &&
+ ((a_Point.y >= a_Min.y) && (a_Point.y <= a_Max.y)) &&
+ ((a_Point.z >= a_Min.z) && (a_Point.z <= a_Max.z))
+ );
+}
+
+
+
+
+
+bool cBoundingBox::IsInside(const Vector3d & a_Min, const Vector3d & a_Max, double a_X, double a_Y, double a_Z)
+{
+ return (
+ ((a_X >= a_Min.x) && (a_X <= a_Max.x)) &&
+ ((a_Y >= a_Min.y) && (a_Y <= a_Max.y)) &&
+ ((a_Z >= a_Min.z) && (a_Z <= a_Max.z))
+ );
+}
+
+
+
+
+
+bool cBoundingBox::CalcLineIntersection(const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, char & a_Face)
+{
+ return CalcLineIntersection(m_Min, m_Max, a_Line1, a_Line2, a_LineCoeff, a_Face);
+}
+
+
+
+
+
+bool cBoundingBox::CalcLineIntersection(const Vector3d & a_Min, const Vector3d & a_Max, const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, char & a_Face)
+{
+ if (IsInside(a_Min, a_Max, a_Line1))
+ {
+ // The starting point is inside the bounding box.
+ a_LineCoeff = 0;
+ a_Face = BLOCK_FACE_YM; // Make it look as the top face was hit, although none really are.
+ return true;
+ }
+
+ char Face = 0;
+ double Coeff = Vector3d::NO_INTERSECTION;
+
+ // Check each individual bbox face for intersection with the line, remember the one with the lowest coeff
+ double c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Min.z);
+ if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
+ {
+ Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
+ Coeff = c;
+ }
+ c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Max.z);
+ if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
+ {
+ Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
+ Coeff = c;
+ }
+ c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Min.y);
+ if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
+ {
+ Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
+ Coeff = c;
+ }
+ c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Max.y);
+ if ((c >= 0) && (c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
+ {
+ Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
+ Coeff = c;
+ }
+ c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Min.x);
+ if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
+ {
+ Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
+ Coeff = c;
+ }
+ c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Max.x);
+ if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
+ {
+ Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
+ Coeff = c;
+ }
+
+ if (Coeff >= Vector3d::NO_INTERSECTION)
+ {
+ // There has been no intersection
+ return false;
+ }
+
+ a_LineCoeff = Coeff;
+ a_Face = Face;
+ return true;
+}
+
+
+
+
+
+bool cBoundingBox::Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection)
+{
+ a_Intersection.m_Min.x = std::max(m_Min.x, a_Other.m_Min.x);
+ a_Intersection.m_Max.x = std::min(m_Max.x, a_Other.m_Max.x);
+ if (a_Intersection.m_Min.x >= a_Intersection.m_Max.x)
+ {
+ return false;
+ }
+ a_Intersection.m_Min.y = std::max(m_Min.y, a_Other.m_Min.y);
+ a_Intersection.m_Max.y = std::min(m_Max.y, a_Other.m_Max.y);
+ if (a_Intersection.m_Min.y >= a_Intersection.m_Max.y)
+ {
+ return false;
+ }
+ a_Intersection.m_Min.z = std::max(m_Min.z, a_Other.m_Min.z);
+ a_Intersection.m_Max.z = std::min(m_Max.z, a_Other.m_Max.z);
+ if (a_Intersection.m_Min.z >= a_Intersection.m_Max.z)
+ {
+ return false;
+ }
+ return true;
+}
+
+
+
+
diff --git a/source/BoundingBox.h b/source/BoundingBox.h
new file mode 100644
index 000000000..ff9963989
--- /dev/null
+++ b/source/BoundingBox.h
@@ -0,0 +1,90 @@
+
+// BoundingBox.h
+
+// Declares the cBoundingBox class representing an axis-aligned bounding box with floatingpoint coords
+
+
+
+
+#pragma once
+
+#include "Vector3d.h"
+
+
+
+
+
+// tolua_begin
+
+/** Represents two sets of coords, minimum and maximum for each direction.
+All the coords within those limits (inclusive the edges) are considered "inside" the box.
+For intersection purposes, though, if the intersection is "sharp" in any coord (i. e. zero volume),
+the boxes are considered non-intersecting.
+*/
+class cBoundingBox
+{
+public:
+ cBoundingBox(double a_MinX, double a_MaxX, double a_MinY, double a_MaxY, double a_MinZ, double a_MaxZ);
+ cBoundingBox(const Vector3d & a_Min, const Vector3d & a_Max);
+ cBoundingBox(const Vector3d & a_Pos, double a_Radius, double a_Height);
+ cBoundingBox(const cBoundingBox & a_Orig);
+
+ /// Moves the entire boundingbox by the specified offset
+ void Move(double a_OffX, double a_OffY, double a_OffZ);
+
+ /// Moves the entire boundingbox by the specified offset
+ void Move(const Vector3d & a_Off);
+
+ /// Expands the bounding box by the specified amount in each direction (so the box becomes larger by 2 * Expand in each direction)
+ void Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ);
+
+ /// Returns true if the two bounding boxes intersect
+ bool DoesIntersect(const cBoundingBox & a_Other);
+
+ /// Returns the union of the two bounding boxes
+ cBoundingBox Union(const cBoundingBox & a_Other);
+
+ /// Returns true if the point is inside the bounding box
+ bool IsInside(const Vector3d & a_Point);
+
+ /// Returns true if the point is inside the bounding box
+ bool IsInside(double a_X, double a_Y,double a_Z);
+
+ /// Returns true if a_Other is inside this bounding box
+ bool IsInside(cBoundingBox & a_Other);
+
+ /// Returns true if a boundingbox specified by a_Min and a_Max is inside this bounding box
+ bool IsInside(const Vector3d & a_Min, const Vector3d & a_Max);
+
+ /// Returns true if the specified point is inside the bounding box specified by its min/max corners
+ static bool IsInside(const Vector3d & a_Min, const Vector3d & a_Max, const Vector3d & a_Point);
+
+ /// Returns true if the specified point is inside the bounding box specified by its min/max corners
+ static bool IsInside(const Vector3d & a_Min, const Vector3d & a_Max, double a_X, double a_Y, double a_Z);
+
+ /** Returns true if this bounding box is intersected by the line specified by its two points
+ Also calculates the distance along the line in which the intersection occurs (0 .. 1)
+ Only forward collisions (a_LineCoeff >= 0) are returned.
+ */
+ bool CalcLineIntersection(const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, char & a_Face);
+
+ /** Returns true if the specified bounding box is intersected by the line specified by its two points
+ Also calculates the distance along the line in which the intersection occurs (0 .. 1) and the face hit (BLOCK_FACE_ constants)
+ Only forward collisions (a_LineCoeff >= 0) are returned.
+ */
+ static bool CalcLineIntersection(const Vector3d & a_Min, const Vector3d & a_Max, const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, char & a_Face);
+
+ // tolua_end
+
+ /// Calculates the intersection of the two bounding boxes; returns true if nonempty
+ bool Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection);
+
+protected:
+ Vector3d m_Min;
+ Vector3d m_Max;
+
+} ; // tolua_export
+
+
+
+
diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp
index a15f3aed1..3c098fdfe 100644
--- a/source/ChunkMap.cpp
+++ b/source/ChunkMap.cpp
@@ -1562,7 +1562,7 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback
-void cChunkMap::DoExplosiontAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlocksAffected)
+void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlocksAffected)
{
// Don't explode if outside of Y range (prevents the following test running into unallocated memory):
if ((a_BlockY < 0) || (a_BlockY > cChunkDef::Height - 1))
diff --git a/source/ChunkMap.h b/source/ChunkMap.h
index b0af0d779..fcb164f7b 100644
--- a/source/ChunkMap.h
+++ b/source/ChunkMap.h
@@ -184,7 +184,7 @@ public:
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible
/// Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates
- void DoExplosiontAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlockAffected);
+ void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlockAffected);
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false.
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible
diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp
index 357c07105..1806ce8e6 100644
--- a/source/ClientHandle.cpp
+++ b/source/ClientHandle.cpp
@@ -11,7 +11,6 @@
#include "BlockEntities/SignEntity.h"
#include "UI/Window.h"
#include "Item.h"
-#include "Doors.h"
#include "Piston.h"
#include "Mobs/Monster.h"
#include "ChatColor.h"
@@ -98,6 +97,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance)
, m_HasStartedDigging(false)
, m_CurrentExplosionTick(0)
, m_RunningSumExplosions(0)
+ , m_HasSentPlayerChunk(false)
{
m_Protocol = new cProtocolRecognizer(this);
@@ -489,8 +489,14 @@ void cClientHandle::HandleCreativeInventory(short a_SlotNum, const cItem & a_Hel
void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround)
{
+ if ((m_Player == NULL) || (m_State != csPlaying))
+ {
+ // The client hasn't been spawned yet and sends nonsense, we know better
+ return;
+ }
+
/*
- // TODO: Invalid stance check
+ // TODO: Invalid stance check
if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
{
LOGD("Invalid stance");
@@ -499,7 +505,7 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
}
*/
- // LOGD("recv player pos: {%0.2f %0.2f %0.2f}, ground: %d", a_PosX, a_PosY, a_PosZ, a_IsOnGround ? 1 : 0);
+ // If the player has moved too far, "repair" them:
Vector3d Pos(a_PosX, a_PosY, a_PosZ);
if ((m_Player->GetPosition() - Pos).SqrLength() > 100 * 100)
{
@@ -513,7 +519,7 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
{
// we only add this exhaustion if the player is not swimming - otherwise we end up with both jump + swim exhaustion
- if(! m_Player->IsSwimming() )
+ if (!m_Player->IsSwimming())
{
m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2);
}
@@ -908,15 +914,6 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
}
else
{
- // Check for Blocks not allowing placement on top
- if ((a_BlockFace == BLOCK_FACE_TOP) && !Handler->DoesAllowBlockOnTop())
- {
- // Resend the old block
- // Sometimes the client still places the block O.o
- World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
- return;
- }
-
if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision())
{
// Tried to place a block *into* another?
@@ -938,13 +935,6 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
cBlockHandler * NewBlock = BlockHandler(BlockType);
- if ((a_BlockFace != BLOCK_FACE_TOP) && !NewBlock->CanBePlacedOnSide())
- {
- // Cannot be placed on the side of an other block
- World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
- return;
- }
-
if (cRoot::Get()->GetPluginManager()->CallHookPlayerPlacingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
{
// A plugin doesn't agree with placing the block, revert the block on the client:
@@ -997,11 +987,15 @@ void cClientHandle::HandleChat(const AString & a_Message)
void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsOnGround)
{
+ if ((m_Player == NULL) || (m_State != csPlaying))
+ {
+ return;
+ }
+
m_Player->SetRotation (a_Rotation);
m_Player->SetHeadYaw (a_Rotation);
m_Player->SetPitch (a_Pitch);
m_Player->SetTouchGround(a_IsOnGround);
- m_Player->WrapRotation();
}
@@ -1010,6 +1004,12 @@ void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsO
void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround)
{
+ if ((m_Player == NULL) || (m_State != csPlaying))
+ {
+ // The client hasn't been spawned yet and sends nonsense, we know better
+ return;
+ }
+
/*
// TODO: Invalid stance check
if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
@@ -1019,46 +1019,13 @@ void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_
return;
}
*/
- switch (m_State)
- {
- case csPlaying:
- {
- m_Player->MoveTo(Vector3d(a_PosX, a_PosY, a_PosZ));
- m_Player->SetStance (a_Stance);
- m_Player->SetTouchGround(a_IsOnGround);
- m_Player->SetHeadYaw (a_Rotation);
- m_Player->SetRotation (a_Rotation);
- m_Player->SetPitch (a_Pitch);
- m_Player->WrapRotation();
- break;
- }
-
- case csDownloadingWorld:
- {
- Vector3d ReceivedPosition = Vector3d(a_PosX, a_PosY, a_PosZ);
- // LOGD("Received MoveLook confirmation: {%0.2f %0.2f %0.2f}", a_PosX, a_PosY, a_PosZ);
-
- // Test the distance between points with a small/large enough value instead of comparing directly. Floating point inaccuracies might screw stuff up
- double Dist = (ReceivedPosition - m_ConfirmPosition).SqrLength();
- if (Dist < 1.0)
- {
- if (ReceivedPosition.Equals(m_ConfirmPosition))
- {
- LOGINFO("Exact position confirmed by client!");
- }
- m_State = csPlaying;
- }
- else
- {
- LOGWARNING("Player \"%s\" sent a weird position confirmation %.2f blocks away, retrying", m_Username.c_str(), sqrt(Dist));
- LOGD(" Expected pos: {%0.2f, %0.2f, %0.2f}", m_ConfirmPosition.x, m_ConfirmPosition.y, m_ConfirmPosition.z);
- LOGD(" Received pos: {%0.2f, %0.2f, %0.2f}", a_PosX, a_PosY, a_PosZ);
- m_ConfirmPosition = m_Player->GetPosition();
- SendPlayerMoveLook();
- }
- break;
- }
- }
+
+ m_Player->MoveTo(Vector3d(a_PosX, a_PosY, a_PosZ));
+ m_Player->SetStance (a_Stance);
+ m_Player->SetTouchGround(a_IsOnGround);
+ m_Player->SetHeadYaw (a_Rotation);
+ m_Player->SetRotation (a_Rotation);
+ m_Player->SetPitch (a_Pitch);
}
@@ -1090,6 +1057,15 @@ void cClientHandle::HandleSlotSelected(short a_SlotNum)
+void cClientHandle::HandleSteerVehicle(float a_Forward, float a_Sideways)
+{
+ m_Player->SteerVehicle(a_Forward, a_Sideways);
+}
+
+
+
+
+
void cClientHandle::HandleWindowClose(char a_WindowID)
{
m_Player->CloseWindowIfID(a_WindowID);
@@ -1199,7 +1175,7 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick)
void cClientHandle::HandleRespawn(void)
{
- if( m_Player == NULL )
+ if (m_Player == NULL)
{
Destroy();
return;
@@ -1413,6 +1389,7 @@ void cClientHandle::MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket)
m_State = csAuthenticated;
m_LastStreamedChunkX = 0x7fffffff;
m_LastStreamedChunkZ = 0x7fffffff;
+ m_HasSentPlayerChunk = false;
}
@@ -1486,17 +1463,23 @@ void cClientHandle::Tick(float a_Dt)
Destroy();
}
- if ((m_State == csDownloadingWorld) && m_ShouldCheckDownloaded)
- {
- CheckIfWorldDownloaded();
- m_ShouldCheckDownloaded = false;
- }
-
if (m_Player == NULL)
{
return;
}
+ // If the chunk the player's in was just sent, spawn the player:
+ if (m_HasSentPlayerChunk && (m_State != csPlaying))
+ {
+ if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player))
+ {
+ // Broadcast that this player has joined the game! Yay~
+ m_Player->GetWorld()->BroadcastChat(m_Username + " joined the game!", this);
+ }
+ m_Protocol->SendPlayerMoveLook();
+ m_State = csPlaying;
+ }
+
// Send a ping packet:
cTimer t1;
if ((m_LastPingTime + cClientHandle::PING_TIME_MS <= t1.GetNowTime()))
@@ -1592,14 +1575,6 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
{
ASSERT(m_Player != NULL);
- if ((m_State == csAuthenticated) || (m_State == csDownloadingWorld))
- {
- if ((a_ChunkX == m_Player->GetChunkX()) && (a_ChunkZ == m_Player->GetChunkZ()))
- {
- m_Protocol->SendPlayerMoveLook();
- }
- }
-
// Check chunks being sent, erase them from m_ChunksToSend:
bool Found = false;
{
@@ -1609,11 +1584,6 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
{
m_ChunksToSend.erase(itr);
-
- // Make the tick thread check if all the needed chunks have been downloaded
- // -- needed to offload this from here due to a deadlock possibility
- m_ShouldCheckDownloaded = true;
-
Found = true;
break;
}
@@ -1628,6 +1598,15 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
}
m_Protocol->SendChunkData(a_ChunkX, a_ChunkZ, a_Serializer);
+
+ // If it is the chunk the player's in, make them spawn (in the tick thread):
+ if ((m_State == csAuthenticated) || (m_State == csDownloadingWorld))
+ {
+ if ((a_ChunkX == m_Player->GetChunkX()) && (a_ChunkZ == m_Player->GetChunkZ()))
+ {
+ m_HasSentPlayerChunk = true;
+ }
+ }
}
@@ -2069,50 +2048,6 @@ void cClientHandle::SendWindowProperty(const cWindow & a_Window, int a_Property,
-void cClientHandle::CheckIfWorldDownloaded(void)
-{
- if (m_State != csDownloadingWorld)
- {
- return;
- }
-
- bool ShouldSendConfirm = false;
- {
- cCSLock Lock(m_CSChunkLists);
- ShouldSendConfirm = m_ChunksToSend.empty();
- }
-
- if (ShouldSendConfirm)
- {
- SendConfirmPosition();
- }
-}
-
-
-
-
-
-void cClientHandle::SendConfirmPosition(void)
-{
- LOG("Spawning player \"%s\" at {%.2f, %.2f, %.2f}",
- m_Username.c_str(), m_Player->GetPosX(), m_Player->GetPosY(), m_Player->GetPosZ()
- );
-
- m_State = csConfirmingPos;
-
- if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player))
- {
- // Broadcast that this player has joined the game! Yay~
- m_Player->GetWorld()->BroadcastChat(m_Username + " joined the game!", this);
- }
-
- SendPlayerMoveLook();
-}
-
-
-
-
-
const AString & cClientHandle::GetUsername(void) const
{
return m_Username;
diff --git a/source/ClientHandle.h b/source/ClientHandle.h
index 761cf25fe..07efc5d9c 100644
--- a/source/ClientHandle.h
+++ b/source/ClientHandle.h
@@ -56,7 +56,7 @@ public:
static const int DEFAULT_VIEW_DISTANCE = 9;
#endif
static const int MAX_VIEW_DISTANCE = 10;
- static const int MIN_VIEW_DISTANCE = 4;
+ static const int MIN_VIEW_DISTANCE = 3;
/// How many ticks should be checked for a running average of explosions, for limiting purposes
static const int NUM_CHECK_EXPLOSIONS_TICKS = 20;
@@ -125,7 +125,7 @@ public:
void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock);
void SendSpawnMob (const cMonster & a_Mob);
void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch);
- void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType);
+ void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType = 0);
void SendTabCompletionResults(const AStringVector & a_Results);
void SendTeleportEntity (const cEntity & a_Entity);
void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ);
@@ -177,6 +177,7 @@ public:
void HandleRespawn (void);
void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem);
void HandleSlotSelected (short a_SlotNum);
+ void HandleSteerVehicle (float Forward, float Sideways);
void HandleTabCompletion (const AString & a_Text);
void HandleUpdateSign (
int a_BlockX, int a_BlockY, int a_BlockZ,
@@ -298,17 +299,14 @@ private:
static int s_ClientCount;
int m_UniqueID;
+ /// Set to true when the chunk where the player is is sent to the client. Used for spawning the player
+ bool m_HasSentPlayerChunk;
+
/// Returns true if the rate block interactions is within a reasonable limit (bot protection)
bool CheckBlockInteractionsRate(void);
- /// Checks whether all loaded chunks have been sent to the client; if so, sends the position to confirm
- void CheckIfWorldDownloaded(void);
-
- /// Sends the PlayerMoveLook packet that the client needs to reply to for the game to start
- void SendConfirmPosition(void);
-
/// Adds a single chunk to be streamed to the client; used by StreamChunks()
void StreamChunk(int a_ChunkX, int a_ChunkZ);
diff --git a/source/Defines.h b/source/Defines.h
index 6bc1a18f6..6dd81137e 100644
--- a/source/Defines.h
+++ b/source/Defines.h
@@ -43,16 +43,24 @@ extern bool g_BlockIsSolid[256];
-/// Block face constants, used in PlayerDigging and PlayerBlockPlacement packets
-enum
+/// Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc
+enum eBlockFace
{
- BLOCK_FACE_NONE = -1, // Interacting with no block face - swinging the item in the air
- BLOCK_FACE_BOTTOM = 0, // Interacting with the bottom face of the block (YM)
- BLOCK_FACE_TOP = 1, // Interacting with the top face of the block (YP)
- BLOCK_FACE_NORTH = 2, // Interacting with the northern face of the block (ZP)
- BLOCK_FACE_SOUTH = 3, // Interacting with the southern face of the block (ZM)
- BLOCK_FACE_WEST = 4, // Interacting with the western face of the block (XP)
- BLOCK_FACE_EAST = 5, // Interacting with the eastern face of the block (XM)
+ BLOCK_FACE_NONE = -1, // Interacting with no block face - swinging the item in the air
+ BLOCK_FACE_XM = 5, // Interacting with the X- face of the block
+ BLOCK_FACE_XP = 4, // Interacting with the X+ face of the block
+ BLOCK_FACE_YM = 0, // Interacting with the Y- face of the block
+ BLOCK_FACE_YP = 1, // Interacting with the Y+ face of the block
+ BLOCK_FACE_ZM = 3, // Interacting with the Z- face of the block
+ BLOCK_FACE_ZP = 2, // Interacting with the Z+ face of the block
+
+ // Synonyms using the (deprecated) world directions:
+ BLOCK_FACE_BOTTOM = BLOCK_FACE_YM, // Interacting with the bottom face of the block
+ BLOCK_FACE_TOP = BLOCK_FACE_YP, // Interacting with the top face of the block
+ BLOCK_FACE_NORTH = BLOCK_FACE_ZP, // Interacting with the northern face of the block
+ BLOCK_FACE_SOUTH = BLOCK_FACE_ZM, // Interacting with the southern face of the block
+ BLOCK_FACE_WEST = BLOCK_FACE_XP, // Interacting with the western face of the block
+ BLOCK_FACE_EAST = BLOCK_FACE_XM, // Interacting with the eastern face of the block
} ;
@@ -345,8 +353,7 @@ inline void AddFaceDirection(int & a_BlockX, unsigned char & a_BlockY, int & a_B
-#include <math.h>
-#define PI 3.14159265358979323846264338327950288419716939937510582097494459072381640628620899862803482534211706798f
+#define PI 3.14159265358979323846264338327950288419716939937510582097494459072381640628620899862803482534211706798f
inline void EulerToVector(double a_Pan, double a_Pitch, double & a_X, double & a_Y, double & a_Z)
{
diff --git a/source/Doors.h b/source/Doors.h
deleted file mode 100644
index 69784a3d7..000000000
--- a/source/Doors.h
+++ /dev/null
@@ -1,87 +0,0 @@
-
-#pragma once
-
-
-
-
-
-// tolua_begin
-class cDoors
-{
-public:
- static char RotationToMetaData(double a_Rotation)
- {
- a_Rotation += 90 + 45; // So its not aligned with axis
- if (a_Rotation > 360)
- {
- a_Rotation -= 360;
- }
- if (a_Rotation >= 0.f && a_Rotation < 90)
- {
- return 0x0;
- }
- else if ((a_Rotation >= 180) && (a_Rotation < 270))
- {
- return 0x2;
- }
- else if ((a_Rotation >= 90) && (a_Rotation < 180))
- {
- return 0x1;
- }
- else
- {
- return 0x3;
- }
- }
-
-
- static NIBBLETYPE ChangeStateMetaData(NIBBLETYPE a_MetaData)
- {
-
- a_MetaData ^= 4; //XOR bit 2 aka 3. bit (Door open state)
-
- return a_MetaData;
- }
-
-
- static void ChangeDoor(cWorld * a_World, int a_X, int a_Y, int a_Z)
- {
- NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_X, a_Y, a_Z);
-
- a_World->SetBlockMeta(a_X, a_Y, a_Z, ChangeStateMetaData(OldMetaData));
-
- if (OldMetaData & 8)
- {
- // Current block is top of the door
- BLOCKTYPE BottomBlock = a_World->GetBlock(a_X, a_Y - 1, a_Z);
- NIBBLETYPE BottomMeta = a_World->GetBlockMeta(a_X, a_Y - 1, a_Z);
-
- if (IsDoor(BottomBlock) && !(BottomMeta & 8))
- {
- a_World->SetBlockMeta(a_X, a_Y - 1, a_Z, ChangeStateMetaData(BottomMeta));
- }
- }
- else
- {
- // Current block is bottom of the door
- BLOCKTYPE TopBlock = a_World->GetBlock(a_X, a_Y + 1, a_Z);
- NIBBLETYPE TopMeta = a_World->GetBlockMeta(a_X, a_Y + 1, a_Z);
-
- if (IsDoor(TopBlock) && (TopMeta & 8))
- {
- a_World->SetBlockMeta(a_X, a_Y + 1, a_Z, ChangeStateMetaData(TopMeta));
- }
- }
- }
-
-
- inline static bool IsDoor(BLOCKTYPE a_Block)
- {
- return (a_Block == E_BLOCK_WOODEN_DOOR) || (a_Block == E_BLOCK_IRON_DOOR);
- }
-} ;
-// tolua_end
-
-
-
-
diff --git a/source/Entities/Boat.cpp b/source/Entities/Boat.cpp
new file mode 100644
index 000000000..56e766dd4
--- /dev/null
+++ b/source/Entities/Boat.cpp
@@ -0,0 +1,87 @@
+
+// Boat.cpp
+
+// Implements the cBoat class representing a boat in the world
+
+#include "Globals.h"
+#include "Boat.h"
+#include "../World.h"
+#include "../ClientHandle.h"
+#include "Player.h"
+
+
+
+
+
+cBoat::cBoat(double a_X, double a_Y, double a_Z) :
+ super(etBoat, a_X, a_Y, a_Z, 0.98, 0.7)
+{
+ SetMass(20.f);
+ SetMaxHealth(6);
+ SetHealth(6);
+}
+
+
+
+
+void cBoat::SpawnOn(cClientHandle & a_ClientHandle)
+{
+ a_ClientHandle.SendSpawnVehicle(*this, 1);
+}
+
+
+
+
+
+void cBoat::DoTakeDamage(TakeDamageInfo & TDI)
+{
+ super::DoTakeDamage(TDI);
+
+ if (GetHealth() == 0)
+ {
+ Destroy(true);
+ }
+}
+
+
+
+
+
+void cBoat::OnRightClicked(cPlayer & a_Player)
+{
+ if (m_Attachee != NULL)
+ {
+ if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
+ {
+ // This player is already sitting in, they want out.
+ a_Player.Detach();
+ return;
+ }
+
+ if (m_Attachee->IsPlayer())
+ {
+ // Another player is already sitting in here, cannot attach
+ return;
+ }
+
+ // Detach whatever is sitting in this boat now:
+ m_Attachee->Detach();
+ }
+
+ // Attach the player to this boat
+ a_Player.AttachTo(this);
+}
+
+
+
+
+
+void cBoat::HandlePhysics(float a_Dt, cChunk & a_Chunk)
+{
+ super::HandlePhysics(a_Dt, a_Chunk);
+ BroadcastMovementUpdate();
+}
+
+
+
+
diff --git a/source/Entities/Boat.h b/source/Entities/Boat.h
new file mode 100644
index 000000000..734ebda83
--- /dev/null
+++ b/source/Entities/Boat.h
@@ -0,0 +1,38 @@
+
+// Boat.h
+
+// Declares the cBoat class representing a boat in the world
+
+
+
+
+
+#pragma once
+
+#include "Entity.h"
+#include "../Item.h"
+
+
+
+
+
+class cBoat :
+ public cEntity
+{
+ typedef cEntity super;
+
+public:
+ CLASS_PROTODEF(cBoat);
+
+ // cEntity overrides:
+ virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
+ virtual void OnRightClicked(cPlayer & a_Player) override;
+ virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
+ virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
+
+ cBoat(double a_X, double a_Y, double a_Z);
+} ;
+
+
+
+
diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp
index e79b441f3..d9272b39d 100644
--- a/source/Entities/Entity.cpp
+++ b/source/Entities/Entity.cpp
@@ -55,6 +55,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
, m_TicksSinceLastBurnDamage(0)
, m_TicksSinceLastLavaDamage(0)
, m_TicksSinceLastFireDamage(0)
+ , m_TicksSinceLastVoidDamage(0)
, m_TicksLeftBurning(0)
, m_WaterSpeed(0, 0, 0)
, m_Width(a_Width)
@@ -253,6 +254,39 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R
+void cEntity::SetRotationFromSpeed(void)
+{
+ const double EPS = 0.0000001;
+ if ((abs(m_Speed.x) < EPS) && (abs(m_Speed.z) < EPS))
+ {
+ // atan2() may overflow or is undefined, pick any number
+ SetRotation(0);
+ return;
+ }
+ SetRotation(atan2(m_Speed.x, m_Speed.z) * 180 / PI);
+}
+
+
+
+
+
+void cEntity::SetPitchFromSpeed(void)
+{
+ const double EPS = 0.0000001;
+ double xz = sqrt(m_Speed.x * m_Speed.x + m_Speed.z * m_Speed.z); // Speed XZ-plane component
+ if ((abs(xz) < EPS) && (abs(m_Speed.y) < EPS))
+ {
+ // atan2() may overflow or is undefined, pick any number
+ SetPitch(0);
+ return;
+ }
+ SetPitch(atan2(m_Speed.y, xz) * 180 / PI);
+}
+
+
+
+
+
void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
{
if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI))
@@ -472,6 +506,11 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
TickBurning(a_Chunk);
}
+ if ((a_Chunk.IsValid()) && (GetPosY() < -46))
+ {
+ TickInVoid(a_Chunk);
+ }
+ else { m_TicksSinceLastVoidDamage = 0; }
}
@@ -491,8 +530,15 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
{
// Outside of the world
- // TODO: Current speed should still be added to the entity position
- // Otherwise TNT explosions in the void will still effect the bottommost layers of the world
+
+ cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
+ // See if we can commit our changes. If not, we will discard them.
+ if (NextChunk != NULL)
+ {
+ SetSpeed(NextSpeed);
+ NextPos += (NextSpeed * a_Dt);
+ SetPosition(NextPos);
+ }
return;
}
@@ -534,7 +580,11 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
bool IsNoAirSurrounding = true;
for (int i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
{
- NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock);
+ if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
+ {
+ // The pickup is too close to an unloaded chunk, bail out of any physics handling
+ return;
+ }
if (!g_BlockIsSolid[GotBlock])
{
NextPos.x += gCrossCoords[i].x;
@@ -545,12 +595,15 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
} // for i - gCrossCoords[]
if (IsNoAirSurrounding)
- { NextPos.y += 0.5; }
+ {
+ NextPos.y += 0.5;
+ }
m_bOnGround = true;
- 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)
@@ -844,6 +897,23 @@ void cEntity::TickBurning(cChunk & a_Chunk)
+void cEntity::TickInVoid(cChunk & a_Chunk)
+{
+ if (m_TicksSinceLastVoidDamage == 20)
+ {
+ TakeDamage(dtInVoid, NULL, 2, 0);
+ m_TicksSinceLastVoidDamage = 0;
+ }
+ else
+ {
+ m_TicksSinceLastVoidDamage++;
+ }
+}
+
+
+
+
+
/// Called when the entity starts burning
void cEntity::OnStartedBurning(void)
{
@@ -1275,6 +1345,25 @@ void cEntity::AddSpeedZ(double a_AddSpeedZ)
+void cEntity::SteerVehicle(float a_Forward, float a_Sideways)
+{
+ if (m_AttachedTo == NULL)
+ {
+ return;
+ }
+ if ((a_Forward != 0) || (a_Sideways != 0))
+ {
+ Vector3d LookVector = GetLookVector();
+ double AddSpeedX = LookVector.x * a_Forward + LookVector.z * a_Sideways;
+ double AddSpeedZ = LookVector.z * a_Forward - LookVector.x * a_Sideways;
+ m_AttachedTo->AddSpeed(AddSpeedX, 0, AddSpeedZ);
+ }
+}
+
+
+
+
+
//////////////////////////////////////////////////////////////////////////
// Get look vector (this is NOT a rotation!)
Vector3d cEntity::GetLookVector(void) const
diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h
index 2d058abae..a2c99d2a0 100644
--- a/source/Entities/Entity.h
+++ b/source/Entities/Entity.h
@@ -92,6 +92,7 @@ public:
etMonster,
etFallingBlock,
etMinecart,
+ etBoat,
etTNT,
etProjectile,
@@ -119,6 +120,7 @@ public:
bool IsPickup (void) const { return (m_EntityType == etPickup); }
bool IsMob (void) const { return (m_EntityType == etMob); }
bool IsMinecart(void) const { return (m_EntityType == etMinecart); }
+ bool IsBoat (void) const { return (m_EntityType == etBoat); }
bool IsTNT (void) const { return (m_EntityType == etTNT); }
/// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true)
@@ -185,6 +187,8 @@ public:
void AddSpeedX (double a_AddSpeedX);
void AddSpeedY (double a_AddSpeedY);
void AddSpeedZ (double a_AddSpeedZ);
+
+ void SteerVehicle(float a_Forward, float a_Sideways);
inline int GetUniqueID(void) const { return m_UniqueID; }
inline bool IsDestroyed(void) const { return !m_IsInitialized; }
@@ -201,6 +205,16 @@ public:
/// Makes this entity take the specified damage. The values are packed into a TDI, knockback calculated, then sent through DoTakeDamage()
void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, int a_FinalDamage, double a_KnockbackAmount);
+ float GetGravity(void) const { return m_Gravity; }
+
+ void SetGravity(float a_Gravity) { m_Gravity = a_Gravity; }
+
+ /// Sets the rotation to match the speed vector (entity goes "face-forward")
+ void SetRotationFromSpeed(void);
+
+ /// Sets the pitch to match the speed vector (entity gies "face-forward")
+ void SetPitchFromSpeed(void);
+
// tolua_end
/// Makes this entity take damage specified in the a_TDI. The TDI is sent through plugins first, then applied
@@ -253,6 +267,9 @@ public:
/// Updates the state related to this entity being on fire
virtual void TickBurning(cChunk & a_Chunk);
+
+ /// Handles when the entity is in the void
+ virtual void TickInVoid(cChunk & a_Chunk);
/// Called when the entity starts burning
virtual void OnStartedBurning(void);
@@ -375,6 +392,9 @@ protected:
/// Time, in ticks, until the entity extinguishes its fire
int m_TicksLeftBurning;
+
+ /// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
+ int m_TicksSinceLastVoidDamage;
virtual void Destroyed(void) {} // Called after the entity has been destroyed
diff --git a/source/Entities/Player.cpp b/source/Entities/Player.cpp
index 8356d588e..04d285b01 100644
--- a/source/Entities/Player.cpp
+++ b/source/Entities/Player.cpp
@@ -220,7 +220,6 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
if (m_IsChargingBow)
{
m_BowCharge += 1;
- LOGD("Player \"%s\" charging bow: %d", m_PlayerName.c_str(), m_BowCharge);
}
if (m_bDirtyPosition)
@@ -611,10 +610,13 @@ void cPlayer::SetSprint(bool a_IsSprinting)
void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- if (m_GameMode == eGameMode_Creative)
+ if (a_TDI.DamageType != dtInVoid)
{
- // No damage / health in creative mode
- return;
+ if (IsGameModeCreative())
+ {
+ // No damage / health in creative mode
+ return;
+ }
}
super::DoTakeDamage(a_TDI);
diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp
index 91b2c97a8..4c8e680d0 100644
--- a/source/Entities/ProjectileEntity.cpp
+++ b/source/Entities/ProjectileEntity.cpp
@@ -8,6 +8,16 @@
#include "../ClientHandle.h"
#include "Player.h"
#include "../LineBlockTracer.h"
+#include "../BoundingBox.h"
+#include "../ChunkMap.h"
+#include "../Chunk.h"
+
+
+
+
+
+/// Converts an angle in radians into a byte representation used by the network protocol
+#define ANGLE_TO_PROTO(X) (Byte)(X * 255 / 360)
@@ -21,20 +31,49 @@ class cProjectileTracerCallback :
{
public:
cProjectileTracerCallback(cProjectileEntity * a_Projectile) :
- m_Projectile(a_Projectile)
+ m_Projectile(a_Projectile),
+ m_SlowdownCoeff(0.99) // Default slowdown when not in water
{
}
+ double GetSlowdownCoeff(void) const { return m_SlowdownCoeff; }
+
protected:
cProjectileEntity * m_Projectile;
+ double m_SlowdownCoeff;
+ // cCallbacks overrides:
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
{
+ /*
+ // DEBUG:
+ LOGD("Hit block %d:%d at {%d, %d, %d} face %d, %s (%s)",
+ a_BlockType, a_BlockMeta,
+ a_BlockX, a_BlockY, a_BlockZ, a_EntryFace,
+ g_BlockIsSolid[a_BlockType] ? "solid" : "non-solid",
+ ItemToString(cItem(a_BlockType, 1, a_BlockMeta)).c_str()
+ );
+ */
+
if (g_BlockIsSolid[a_BlockType])
{
// The projectile hit a solid block
- m_Projectile->OnHitSolidBlock(a_BlockX, a_BlockY, a_BlockZ, a_EntryFace);
- return true;
+ // Calculate the exact hit coords:
+ cBoundingBox bb(a_BlockX, a_BlockX + 1, a_BlockY, a_BlockY + 1, a_BlockZ, a_BlockZ + 1);
+ Vector3d Line1 = m_Projectile->GetPosition();
+ Vector3d Line2 = Line1 + m_Projectile->GetSpeed();
+ double LineCoeff = 0;
+ char Face;
+ if (bb.CalcLineIntersection(Line1, Line2, LineCoeff, Face))
+ {
+ Vector3d Intersection = Line1 + m_Projectile->GetSpeed() * LineCoeff;
+ m_Projectile->OnHitSolidBlock(Intersection, Face);
+ return true;
+ }
+ else
+ {
+ LOGD("WEIRD! block tracer reports a hit, but BBox tracer doesn't. Ignoring the hit.");
+ }
}
// Convey some special effects from special blocks:
@@ -44,12 +83,14 @@ protected:
case E_BLOCK_STATIONARY_LAVA:
{
m_Projectile->StartBurning(30);
+ m_SlowdownCoeff = std::min(m_SlowdownCoeff, 0.9); // Slow down to 0.9* the speed each tick when moving through lava
break;
}
case E_BLOCK_WATER:
case E_BLOCK_STATIONARY_WATER:
{
m_Projectile->StopBurning();
+ m_SlowdownCoeff = std::min(m_SlowdownCoeff, 0.8); // Slow down to 0.8* the speed each tick when moving through water
break;
}
} // switch (a_BlockType)
@@ -64,6 +105,86 @@ protected:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cProjectileEntityCollisionCallback:
+
+class cProjectileEntityCollisionCallback :
+ public cEntityCallback
+{
+public:
+ cProjectileEntityCollisionCallback(cProjectileEntity * a_Projectile, const Vector3d & a_Pos, const Vector3d & a_NextPos) :
+ m_Projectile(a_Projectile),
+ m_Pos(a_Pos),
+ m_NextPos(a_NextPos),
+ m_MinCoeff(1),
+ m_HitEntity(NULL)
+ {
+ }
+
+
+ virtual bool Item(cEntity * a_Entity) override
+ {
+ if (
+ (a_Entity == m_Projectile) || // Do not check collisions with self
+ (a_Entity == m_Projectile->GetCreator()) // Do not check whoever shot the projectile
+ )
+ {
+ // TODO: Don't check creator only for the first 5 ticks
+ // so that arrows stuck in ground and dug up can hurt the player
+ return false;
+ }
+
+ cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
+
+ // Instead of colliding the bounding box with another bounding box in motion, we collide an enlarged bounding box with a hairline.
+ // The results should be good enough for our purposes
+ double LineCoeff;
+ char Face;
+ EntBox.Expand(m_Projectile->GetWidth() / 2, m_Projectile->GetHeight() / 2, m_Projectile->GetWidth() / 2);
+ if (!EntBox.CalcLineIntersection(m_Pos, m_NextPos, LineCoeff, Face))
+ {
+ // No intersection whatsoever
+ return false;
+ }
+
+ // TODO: Some entities don't interact with the projectiles (pickups, falling blocks)
+ // TODO: Allow plugins to interfere about which entities can be hit
+
+ if (LineCoeff < m_MinCoeff)
+ {
+ // The entity is closer than anything we've stored so far, replace it as the potential victim
+ m_MinCoeff = LineCoeff;
+ m_HitEntity = a_Entity;
+ }
+
+ // Don't break the enumeration, we want all the entities
+ return false;
+ }
+
+ /// Returns the nearest entity that was hit, after the enumeration has been completed
+ cEntity * GetHitEntity(void) const { return m_HitEntity; }
+
+ /// Returns the line coeff where the hit was encountered, after the enumeration has been completed
+ double GetMinCoeff(void) const { return m_MinCoeff; }
+
+ /// Returns true if the callback has encountered a true hit
+ bool HasHit(void) const { return (m_MinCoeff < 1); }
+
+protected:
+ cProjectileEntity * m_Projectile;
+ const Vector3d & m_Pos;
+ const Vector3d & m_NextPos;
+ double m_MinCoeff; // The coefficient of the nearest hit on the Pos line
+
+ // Although it's bad(tm) to store entity ptrs from a callback, we can afford it here, because the entire callback
+ // is processed inside the tick thread, so the entities won't be removed in between the calls and the final processing
+ cEntity * m_HitEntity; // The nearest hit entity
+} ;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cProjectileEntity:
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
@@ -85,6 +206,8 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Ve
m_IsInGround(false)
{
SetSpeed(a_Speed);
+ SetRotationFromSpeed();
+ SetPitchFromSpeed();
}
@@ -101,10 +224,12 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
switch (a_Kind)
{
- case pkArrow: return new cArrowEntity (a_Creator, a_X, a_Y, a_Z, Speed);
- case pkEgg: return new cThrownEggEntity (a_Creator, a_X, a_Y, a_Z, Speed);
- case pkEnderPearl: return new cThrownEnderPearlEntity(a_Creator, a_X, a_Y, a_Z, Speed);
- case pkSnowball: return new cThrownSnowballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkArrow: return new cArrowEntity (a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkEgg: return new cThrownEggEntity (a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkEnderPearl: return new cThrownEnderPearlEntity(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkSnowball: return new cThrownSnowballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkGhastFireball: return new cGhastFireballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkFireCharge: return new cFireChargeEntity (a_Creator, a_X, a_Y, a_Z, Speed);
// TODO: the rest
}
@@ -116,26 +241,17 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
-void cProjectileEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
+void cProjectileEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
{
- // 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;
- }
+ // Set the position based on what face was hit:
+ SetPosition(a_HitPos);
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
+ a_HitPos.x, a_HitPos.y, a_HitPos.z,
+ a_HitFace
);
m_IsInGround = true;
@@ -192,20 +308,51 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
// 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))
+ if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
{
- // Nothing in the way, update the position
- SetPosition(NextPos);
+ // Something has been hit, abort all other processing
+ return;
+ }
+ // The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff
+
+ // Test for entity collisions:
+ cProjectileEntityCollisionCallback EntityCollisionCallback(this, Pos, NextPos);
+ a_Chunk.ForEachEntity(EntityCollisionCallback);
+ if (EntityCollisionCallback.HasHit())
+ {
+ // An entity was hit:
+ Vector3d HitPos = Pos + (NextPos - Pos) * EntityCollisionCallback.GetMinCoeff();
+
+ // DEBUG:
+ LOGD("Projectile %d has hit an entity %d (%s) at {%.02f, %.02f, %.02f} (coeff %.03f)",
+ m_UniqueID,
+ EntityCollisionCallback.GetHitEntity()->GetUniqueID(),
+ EntityCollisionCallback.GetHitEntity()->GetClass(),
+ HitPos.x, HitPos.y, HitPos.z,
+ EntityCollisionCallback.GetMinCoeff()
+ );
+
+ OnHitEntity(*(EntityCollisionCallback.GetHitEntity()), HitPos);
}
+ // TODO: Test the entities in the neighboring chunks, too
+
+ // Update the position:
+ SetPosition(NextPos);
- // Add gravity effect to the vertical speed component:
- SetSpeedY(GetSpeedY() + m_Gravity / 20);
+ // Add slowdown and gravity effect to the speed:
+ Vector3d NewSpeed(GetSpeed());
+ NewSpeed.y += m_Gravity / 20;
+ NewSpeed *= TracerCallback.GetSlowdownCoeff();
+ SetSpeed(NewSpeed);
+ SetRotationFromSpeed();
+ SetPitchFromSpeed();
// DEBUG:
- LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
+ LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}, rot {%.02f, %.02f}",
m_UniqueID,
GetPosX(), GetPosY(), GetPosZ(),
- GetSpeedX(), GetSpeedY(), GetSpeedZ()
+ GetSpeedX(), GetSpeedY(), GetSpeedZ(),
+ GetRotation(), GetPitch()
);
}
@@ -216,7 +363,8 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
void cProjectileEntity::SpawnOn(cClientHandle & a_Client)
{
// Default spawning - use the projectile kind to spawn an object:
- a_Client.SendSpawnObject(*this, m_ProjectileKind, 0, 0, 0);
+ a_Client.SendSpawnObject(*this, m_ProjectileKind, 12, ANGLE_TO_PROTO(GetRotation()), ANGLE_TO_PROTO(GetPitch()));
+ a_Client.SendEntityMetadata(*this);
}
@@ -229,12 +377,16 @@ void cProjectileEntity::SpawnOn(cClientHandle & a_Client)
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)
+ m_DamageCoeff(2),
+ m_IsCritical(false)
{
SetSpeed(a_Speed);
SetMass(0.1);
- LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f}",
- m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ()
+ SetRotationFromSpeed();
+ SetPitchFromSpeed();
+ LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f} and rot {%.02f, %.02f}",
+ m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ(),
+ GetRotation(), GetPitch()
);
}
@@ -245,7 +397,8 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a
cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) :
super(pkArrow, &a_Player, a_Player.GetThrowStartPos(), a_Player.GetThrowSpeed(a_Force * 1.5 * 20), 0.5, 0.5),
m_PickupState(psInSurvivalOrCreative),
- m_DamageCoeff(2)
+ m_DamageCoeff(2),
+ m_IsCritical((a_Force >= 1))
{
}
@@ -269,14 +422,43 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
-void cArrowEntity::SpawnOn(cClientHandle & a_Client)
+void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+{
+ super::OnHitSolidBlock(a_HitPos, a_HitFace);
+
+ // Broadcast the position and speed packets before teleporting:
+ BroadcastMovementUpdate();
+
+ // Teleport the entity to the exact hit coords:
+ m_World->BroadcastTeleportEntity(*this);
+}
+
+
+
+
+
+void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
{
- a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0);
+ if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer())
+ {
+ // Not an entity that interacts with an arrow
+ return;
+ }
+
+ int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5);
+ if (m_IsCritical)
+ {
+ Damage += m_World->GetTickRandomNumber(Damage / 2 + 2);
+ }
+ a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1);
+
+ Destroy();
}
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cThrownEggEntity:
@@ -290,7 +472,7 @@ cThrownEggEntity::cThrownEggEntity(cEntity * a_Creator, double a_X, double a_Y,
-void cThrownEggEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
+void cThrownEggEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
{
// TODO: Random-spawn a chicken or four
@@ -314,9 +496,15 @@ cThrownEnderPearlEntity::cThrownEnderPearlEntity(cEntity * a_Creator, double a_X
-void cThrownEnderPearlEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
+void cThrownEnderPearlEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
{
- // TODO: Teleport the creator here, make them take 5 damage
+ // Teleport the creator here, make them take 5 damage:
+ if (m_Creator != NULL)
+ {
+ // TODO: The coords might need some tweaking based on the block face
+ m_Creator->TeleportToCoords(a_HitPos.x + 0.5, a_HitPos.y + 1.7, a_HitPos.z + 0.5);
+ m_Creator->TakeDamage(dtEnderPearl, this, 5, 0);
+ }
Destroy();
}
@@ -338,7 +526,7 @@ cThrownSnowballEntity::cThrownSnowballEntity(cEntity * a_Creator, double a_X, do
-void cThrownSnowballEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
+void cThrownSnowballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
{
// TODO: Apply damage to certain mobs (blaze etc.) and anger all mobs
@@ -349,3 +537,94 @@ void cThrownSnowballEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_Bl
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cGhastFireballEntity :
+
+cGhastFireballEntity::cGhastFireballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
+ super(pkGhastFireball, a_Creator, a_X, a_Y, a_Z, 1, 1)
+{
+ SetSpeed(a_Speed);
+ SetGravity(0);
+}
+
+
+
+
+
+void cGhastFireballEntity::Explode(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ m_World->DoExplosionAt(1, a_BlockX, a_BlockY, a_BlockZ, true, esGhastFireball, this);
+}
+
+
+
+
+
+void cGhastFireballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+{
+ Destroy();
+ Explode((int)floor(a_HitPos.x), (int)floor(a_HitPos.y), (int)floor(a_HitPos.z));
+}
+
+
+
+
+
+void cGhastFireballEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+{
+ Destroy();
+ Explode((int)floor(a_HitPos.x), (int)floor(a_HitPos.y), (int)floor(a_HitPos.z));
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cFireChargeEntity :
+
+cFireChargeEntity::cFireChargeEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
+ super(pkFireCharge, a_Creator, a_X, a_Y, a_Z, 0.3125, 0.3125)
+{
+ SetSpeed(a_Speed);
+ SetGravity(0);
+}
+
+
+
+
+
+void cFireChargeEntity::Explode(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ if (m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR)
+ {
+ m_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 1);
+ }
+}
+
+
+
+
+
+void cFireChargeEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+{
+ Destroy();
+ Explode((int)floor(a_HitPos.x), (int)floor(a_HitPos.y), (int)floor(a_HitPos.z));
+}
+
+
+
+
+
+void cFireChargeEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+{
+ Destroy();
+ Explode((int)floor(a_HitPos.x), (int)floor(a_HitPos.y), (int)floor(a_HitPos.z));
+
+ // TODO: Some entities are immune to hits
+ a_EntityHit.StartBurning(5 * 20); // 5 seconds of burning
+}
+
+
+
+
diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h
index 95dc00abc..547aa174e 100644
--- a/source/Entities/ProjectileEntity.h
+++ b/source/Entities/ProjectileEntity.h
@@ -47,8 +47,11 @@ public:
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);
+ /// Called by the physics blocktracer when the entity hits a solid block, the hit position and the face hit (BLOCK_FACE_) is given
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace);
+
+ /// Called by the physics blocktracer when the entity hits another entity
+ virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) {}
// tolua_begin
@@ -64,6 +67,11 @@ public:
/// Returns true if the projectile has hit the ground and is stuck there
bool IsInGround(void) const { return m_IsInGround; }
+ // tolua_end
+
+ /// Sets the internal InGround flag. To be used by MCA loader only!
+ void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; }
+
protected:
eKind m_ProjectileKind;
@@ -73,8 +81,6 @@ protected:
/// 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;
@@ -128,6 +134,12 @@ public:
/// Returns true if the specified player can pick the arrow up
bool CanPickup(const cPlayer & a_Player) const;
+ /// Returns true if the arrow is set as critical
+ bool IsCritical(void) const { return m_IsCritical; }
+
+ /// Sets the IsCritical flag
+ void SetIsCritical(bool a_IsCritical) { m_IsCritical = a_IsCritical; }
+
// tolua_end
protected:
@@ -137,9 +149,13 @@ protected:
/// The coefficient applied to the damage that the arrow will deal, based on the bow enchantment. 2.0 for normal arrow
double m_DamageCoeff;
+
+ /// If true, the arrow deals more damage
+ bool m_IsCritical;
// cProjectileEntity overrides:
- virtual void SpawnOn(cClientHandle & a_Client) override;
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override;
+ virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
// tolua_begin
} ;
@@ -166,7 +182,7 @@ protected:
// tolua_end
// cProjectileEntity overrides:
- virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override;
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override;
// tolua_begin
@@ -194,7 +210,7 @@ protected:
// tolua_end
// cProjectileEntity overrides:
- virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override;
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override;
// tolua_begin
@@ -218,12 +234,41 @@ public:
cThrownSnowballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
protected:
+
+ // cProjectileEntity overrides:
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override;
+
+ // tolua_begin
+
+} ;
+
+
+
+
+
+class cGhastFireballEntity :
+ public cProjectileEntity
+{
+ typedef cProjectileEntity super;
+
+public:
// tolua_end
+ CLASS_PROTODEF(cGhastFireballEntity);
+
+ cGhastFireballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
+
+protected:
+
+ void Explode(int a_BlockX, int a_BlockY, int a_BlockZ);
+
// cProjectileEntity overrides:
- virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override;
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override;
+ virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
+ // TODO: Deflecting the fireballs by arrow- or sword- hits
+
// tolua_begin
} ;
@@ -232,6 +277,34 @@ protected:
+class cFireChargeEntity :
+ public cProjectileEntity
+{
+ typedef cProjectileEntity super;
+
+public:
+
+ // tolua_end
+
+ CLASS_PROTODEF(cFireChargeEntity);
+
+ cFireChargeEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
+
+protected:
+
+ void Explode(int a_BlockX, int a_BlockY, int a_BlockZ);
+
+ // cProjectileEntity overrides:
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override;
+ virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
+
+ // tolua_begin
+
+} ;
+
+
+
+
// tolua_end
diff --git a/source/Entities/TNTEntity.cpp b/source/Entities/TNTEntity.cpp
index ad3d9ae0c..339107b2e 100644
--- a/source/Entities/TNTEntity.cpp
+++ b/source/Entities/TNTEntity.cpp
@@ -52,7 +52,7 @@ void cTNTEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
Destroy(true);
LOGD("BOOM at {%f,%f,%f}", GetPosX(), GetPosY(), GetPosZ());
- m_World->DoExplosiontAt(4.0, GetPosX() + 0.49, GetPosY() + 0.49, GetPosZ() + 0.49, true, esPrimedTNT, this);
+ m_World->DoExplosionAt(4.0, GetPosX() + 0.49, GetPosY() + 0.49, GetPosZ() + 0.49, true, esPrimedTNT, this);
return;
}
}
diff --git a/source/Items/ItemBoat.h b/source/Items/ItemBoat.h
new file mode 100644
index 000000000..6e3395f1d
--- /dev/null
+++ b/source/Items/ItemBoat.h
@@ -0,0 +1,54 @@
+
+// ItemBoat.h
+
+// Declares the various boat ItemHandlers
+
+
+
+
+
+#pragma once
+
+#include "../Entities/Boat.h"
+
+
+
+
+
+class cItemBoatHandler :
+ public cItemHandler
+{
+ typedef cItemHandler super;
+
+public:
+ cItemBoatHandler(int a_ItemType) :
+ super(a_ItemType)
+ {
+ }
+
+
+
+ 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
+ {
+ if (a_Dir < 0)
+ {
+ return false;
+ }
+
+ double x = (double)a_BlockX + 0.5;
+ double y = (double)a_BlockY + 0.5;
+ double z = (double)a_BlockZ + 0.5;
+
+ cBoat * Boat = NULL;
+
+ Boat = new cBoat (x, y, z);
+ Boat->Initialize(a_World);
+
+ return true;
+ }
+
+} ;
+
+
+
+
diff --git a/source/Items/ItemHandler.cpp b/source/Items/ItemHandler.cpp
index 2ae193d52..08a7b661d 100644
--- a/source/Items/ItemHandler.cpp
+++ b/source/Items/ItemHandler.cpp
@@ -8,6 +8,7 @@
// Handlers:
#include "ItemBed.h"
+#include "ItemBoat.h"
#include "ItemBow.h"
#include "ItemBrewingStand.h"
#include "ItemBucket.h"
@@ -53,7 +54,11 @@ cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
{
if (a_ItemType < 0)
{
- ASSERT(!"Bad item type");
+ // Either nothing (-1), or bad value, both cases should return the air handler
+ if (a_ItemType < -1)
+ {
+ ASSERT(!"Bad item type");
+ }
a_ItemType = 0;
}
@@ -85,6 +90,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_BOAT: return new cItemBoatHandler(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);
diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp
index 87efecd35..082521eee 100644
--- a/source/ManualBindings.cpp
+++ b/source/ManualBindings.cpp
@@ -92,6 +92,21 @@ static int tolua_StringSplit(lua_State * tolua_S)
+static int tolua_StringSplitAndTrim(lua_State * tolua_S)
+{
+ cLuaState LuaState(tolua_S);
+ std::string str = (std::string)tolua_tocppstring(LuaState, 1, 0);
+ std::string delim = (std::string)tolua_tocppstring(LuaState, 2, 0);
+
+ AStringVector Split = StringSplitAndTrim(str, delim);
+ LuaState.Push(Split);
+ return 1;
+}
+
+
+
+
+
static int tolua_LOG(lua_State* tolua_S)
{
const char* str = tolua_tocppstring(tolua_S,1,0);
@@ -621,6 +636,114 @@ static int tolua_ForEach(lua_State * tolua_S)
+static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S)
+{
+ // Exported manually, because tolua would generate useless additional parameters (a_BlockType .. a_BlockSkyLight)
+ // Function signature: GetBlockInfo(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight]
+ #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_isnoobj (tolua_S, 5, &tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ #endif
+ {
+ cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0);
+ int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
+ int BlockY = (int) tolua_tonumber (tolua_S, 3, 0);
+ int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0);
+ #ifndef TOLUA_RELEASE
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'SetSignLines' / 'UpdateSign'", NULL);
+ }
+ #endif
+ {
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta, BlockSkyLight, BlockBlockLight;
+ bool res = self->GetBlockInfo(BlockX, BlockY, BlockZ, BlockType, BlockMeta, BlockSkyLight, BlockBlockLight);
+ tolua_pushboolean(tolua_S, res ? 1 : 0);
+ if (res)
+ {
+ tolua_pushnumber(tolua_S, BlockType);
+ tolua_pushnumber(tolua_S, BlockMeta);
+ tolua_pushnumber(tolua_S, BlockSkyLight);
+ tolua_pushnumber(tolua_S, BlockBlockLight);
+ return 5;
+ }
+ }
+ }
+ return 1;
+
+ #ifndef TOLUA_RELEASE
+tolua_lerror:
+ tolua_error(tolua_S, "#ferror in function 'GetBlockInfo'.", &tolua_err);
+ return 0;
+ #endif
+}
+
+
+
+
+
+static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S)
+{
+ // Exported manually, because tolua would generate useless additional parameters (a_BlockType, a_BlockMeta)
+ // Function signature: GetBlockTypeMeta(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta]
+ #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_isnoobj (tolua_S, 5, &tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ #endif
+ {
+ cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0);
+ int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
+ int BlockY = (int) tolua_tonumber (tolua_S, 3, 0);
+ int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0);
+ #ifndef TOLUA_RELEASE
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'SetSignLines' / 'UpdateSign'", NULL);
+ }
+ #endif
+ {
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ bool res = self->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta);
+ tolua_pushboolean(tolua_S, res ? 1 : 0);
+ if (res)
+ {
+ tolua_pushnumber(tolua_S, BlockType);
+ tolua_pushnumber(tolua_S, BlockMeta);
+ return 3;
+ }
+ }
+ }
+ return 1;
+
+ #ifndef TOLUA_RELEASE
+tolua_lerror:
+ tolua_error(tolua_S, "#ferror in function 'GetBlockTypeMeta'.", &tolua_err);
+ return 0;
+ #endif
+}
+
+
+
+
+
static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
{
// Exported manually, because tolua would generate useless additional return values (a_Line1 .. a_Line4)
@@ -1808,12 +1931,13 @@ static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
void ManualBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S, NULL);
- tolua_function(tolua_S, "StringSplit", tolua_StringSplit);
- tolua_function(tolua_S, "LOG", tolua_LOG);
- tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO);
- tolua_function(tolua_S, "LOGWARN", tolua_LOGWARN);
- tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN);
- tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR);
+ tolua_function(tolua_S, "StringSplit", tolua_StringSplit);
+ tolua_function(tolua_S, "StringSplitAndTrim", tolua_StringSplitAndTrim);
+ tolua_function(tolua_S, "LOG", tolua_LOG);
+ tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO);
+ tolua_function(tolua_S, "LOGWARN", tolua_LOGWARN);
+ tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN);
+ tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR);
tolua_beginmodule(tolua_S, "cLineBlockTracer");
tolua_function(tolua_S, "Trace", tolua_cLineBlockTracer_Trace);
@@ -1839,6 +1963,8 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>);
+ tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo);
+ tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines);
diff --git a/source/Mobs/Monster.cpp b/source/Mobs/Monster.cpp
index 9ae91f1e0..76b9414f7 100644
--- a/source/Mobs/Monster.cpp
+++ b/source/Mobs/Monster.cpp
@@ -15,6 +15,7 @@
#include "../Vector3i.h"
#include "../Vector3d.h"
#include "../Tracer.h"
+#include "../Chunk.h"
// #include "../../iniFile/iniFile.h"
@@ -25,6 +26,8 @@
cMonster::cMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height)
: super(etMob, a_Width, a_Height)
, m_Target(NULL)
+ , m_AttackRate(3)
+ , idle_interval(0)
, m_bMovingToDestination(false)
, m_DestinationTime( 0 )
, m_DestroyTimer( 0 )
@@ -37,10 +40,9 @@ cMonster::cMonster(const AString & a_ConfigName, char a_ProtocolMobType, const A
, m_SeePlayerInterval (0)
, m_EMPersonality(AGGRESSIVE)
, m_AttackDamage(1.0f)
- , m_AttackRange(5.0f)
+ , m_AttackRange(2.0f)
, m_AttackInterval(0)
- , m_AttackRate(3)
- , idle_interval(0)
+ , m_BurnsInDaylight(false)
{
if (!a_ConfigName.empty())
{
@@ -100,6 +102,9 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
return;
}
+ // Burning in daylight
+ HandleDaylightBurning(a_Chunk);
+
HandlePhysics(a_Dt,a_Chunk);
BroadcastMovementUpdate();
@@ -473,3 +478,35 @@ void cMonster::AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned
+
+void cMonster::HandleDaylightBurning(cChunk & a_Chunk)
+{
+ if (!m_BurnsInDaylight)
+ {
+ return;
+ }
+
+ int RelY = (int)floor(GetPosY());
+ if ((RelY < 0) || (RelY >= cChunkDef::Height))
+ {
+ // Outside the world
+ return;
+ }
+
+ int RelX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width;
+ int RelZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width;
+ if (
+ (a_Chunk.GetSkyLight(RelX, RelY, RelZ) == 15) && // In the daylight
+ (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand
+ (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime
+ !IsOnFire() // Not already burning
+ )
+ {
+ // Burn for 100 ticks, then decide again
+ StartBurning(100);
+ }
+}
+
+
+
+
diff --git a/source/Mobs/Monster.h b/source/Mobs/Monster.h
index 755678d39..5f33d4450 100644
--- a/source/Mobs/Monster.h
+++ b/source/Mobs/Monster.h
@@ -107,6 +107,9 @@ public:
void SetAttackDamage(float ad);
void SetSightDistance(float sd);
+ /// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick
+ void SetBurnsInDaylight(bool a_BurnsInDaylight) { a_BurnsInDaylight = a_BurnsInDaylight; }
+
enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState;
enum MPersonality{PASSIVE,AGGRESSIVE,COWARDLY} m_EMPersonality;
@@ -134,8 +137,12 @@ protected:
float m_AttackDamage;
float m_AttackRange;
float m_AttackInterval;
+
+ bool m_BurnsInDaylight;
void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0);
+
+ void HandleDaylightBurning(cChunk & a_Chunk);
} ; // tolua_export
diff --git a/source/Mobs/Skeleton.cpp b/source/Mobs/Skeleton.cpp
index ad4037db9..10dad4065 100644
--- a/source/Mobs/Skeleton.cpp
+++ b/source/Mobs/Skeleton.cpp
@@ -11,24 +11,7 @@
cSkeleton::cSkeleton(void) :
super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8)
{
-}
-
-
-
-
-
-void cSkeleton::Tick(float a_Dt, cChunk & a_Chunk)
-{
- cMonster::Tick(a_Dt, a_Chunk);
-
- if ((GetWorld()->GetBlockSkyLight(GetPosX(), GetPosY(), GetPosZ()) == 15) && (GetWorld()->GetBlock(GetPosX(), GetPosY(), GetPosZ()) != E_BLOCK_SOULSAND))
- {
- if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsOnFire())
- {
- // Burn for 100 ticks, then decide again
- StartBurning(100);
- }
- }
+ SetBurnsInDaylight(true);
}
diff --git a/source/Mobs/Skeleton.h b/source/Mobs/Skeleton.h
index bc541bac2..d0a2da490 100644
--- a/source/Mobs/Skeleton.h
+++ b/source/Mobs/Skeleton.h
@@ -17,7 +17,6 @@ public:
CLASS_PROTODEF(cSkeleton);
- virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
} ;
diff --git a/source/Mobs/Zombie.cpp b/source/Mobs/Zombie.cpp
index f3adf1283..9b238baef 100644
--- a/source/Mobs/Zombie.cpp
+++ b/source/Mobs/Zombie.cpp
@@ -8,28 +8,10 @@
-// They're eating your brains!
-
cZombie::cZombie(void) :
super("Zombie", 54, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8)
{
-}
-
-
-
-
-
-void cZombie::Tick(float a_Dt, cChunk & a_Chunk)
-{
- super::Tick(a_Dt, a_Chunk);
- if ((GetWorld()->GetBlockSkyLight(GetPosX(), GetPosY(), GetPosZ()) == 15) && (GetWorld()->GetBlock(GetPosX(), GetPosY(), GetPosZ()) != E_BLOCK_SOULSAND))
- {
- if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsOnFire())
- {
- // Burn for 100 ticks, then decide again
- StartBurning(100);
- }
- }
+ SetBurnsInDaylight(true);
}
diff --git a/source/Mobs/Zombie.h b/source/Mobs/Zombie.h
index 61f8e3bb8..4835a53c4 100644
--- a/source/Mobs/Zombie.h
+++ b/source/Mobs/Zombie.h
@@ -12,11 +12,10 @@ class cZombie :
typedef cAggressiveMonster super;
public:
- cZombie();
+ cZombie(void);
CLASS_PROTODEF(cZombie);
- virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
} ;
diff --git a/source/OSSupport/Event.cpp b/source/OSSupport/Event.cpp
index 32f780946..cbacbba17 100644
--- a/source/OSSupport/Event.cpp
+++ b/source/OSSupport/Event.cpp
@@ -116,50 +116,3 @@ void cEvent::Set(void)
-
-cEvent::eWaitResult cEvent::Wait(int a_TimeoutMilliSec)
-{
- #ifdef _WIN32
- DWORD res = WaitForSingleObject(m_Event, (DWORD)a_TimeoutMilliSec);
- switch (res)
- {
- case WAIT_OBJECT_0:
- {
- // The semaphore was signalled
- return wrSignalled;
- }
- case WAIT_TIMEOUT:
- {
- // The timeout was hit
- return wrTimeout;
- }
- default:
- {
- LOGWARNING("cEvent: timed-waiting for the event failed: %d, GLE = %d. Continuing, but server may be unstable.", res, GetLastError());
- return wrError;
- }
- }
- #else
- timespec timeout;
- timeout.tv_sec = time(NULL) + a_TimeoutMilliSec / 1000;
- timeout.tv_nsec = (a_TimeoutMilliSec % 1000) * 1000000;
- int res = sem_timedwait(m_Event, &timeout);
- if (res == 0)
- {
- // The semaphore was signalled
- return wrSignalled;
- }
- int err = errno;
- if (err == ETIMEDOUT)
- {
- // The timeout was hit
- return wrTimeout;
- }
- LOGWARNING("cEvent: timed-waiting for the event failed: %i, errno = %i. Continuing, but server may be unstable.", res, err);
- return wrError;
- #endif
-}
-
-
-
-
diff --git a/source/OSSupport/Event.h b/source/OSSupport/Event.h
index 803d73b7e..71f418c0c 100644
--- a/source/OSSupport/Event.h
+++ b/source/OSSupport/Event.h
@@ -19,22 +19,12 @@
class cEvent
{
public:
- enum eWaitResult
- {
- wrSignalled,
- wrTimeout,
- wrError,
- } ;
-
cEvent(void);
~cEvent();
void Wait(void);
void Set (void);
- /// Waits for the semaphore with a timeout
- eWaitResult Wait(int a_TimeoutMilliSec);
-
private:
#ifdef _WIN32
diff --git a/source/Piston.cpp b/source/Piston.cpp
index f4244d177..b5fda1600 100644
--- a/source/Piston.cpp
+++ b/source/Piston.cpp
@@ -270,7 +270,13 @@ bool cPiston::CanPull(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
return false;
}
}
- return CanPush(a_BlockType, a_BlockMeta) || CanBreakPush(a_BlockType, a_BlockMeta);
+
+ if (CanBreakPush(a_BlockType, a_BlockMeta))
+ {
+ return false; // CanBreakPush returns true, but we need false to prevent pulling
+ }
+
+ return CanPush(a_BlockType, a_BlockMeta);
}
diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp
index 4577e0c16..54bd28c9f 100644
--- a/source/Protocol/Protocol125.cpp
+++ b/source/Protocol/Protocol125.cpp
@@ -584,7 +584,7 @@ void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM);
WriteString(PlayerName);
WriteBool (a_IsOnline);
- WriteShort (a_Player.GetClientHandle()->GetPing());
+ WriteShort (a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0);
Flush();
}
diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp
index 26a1a9fad..a06eb0b8b 100644
--- a/source/Protocol/Protocol132.cpp
+++ b/source/Protocol/Protocol132.cpp
@@ -452,8 +452,17 @@ void cProtocol132::SendTabCompletionResults(const AStringVector & a_Results)
void cProtocol132::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
{
- // Not used in 1.3.2
- // Does it unload chunks on its own?
+ // Unloading the chunk is done by sending a "map chunk" packet
+ // with IncludeInitialize set to true and primary bitmap set to 0:
+ cCSLock Lock(m_CSPacket);
+ WriteByte(PACKET_CHUNK_DATA);
+ WriteInt (a_ChunkX);
+ WriteInt (a_ChunkZ);
+ WriteBool(true); // IncludeInitialize
+ WriteShort(0); // Primary bitmap
+ WriteShort(0); // Add bitmap
+ WriteInt(0);
+ Flush();
}
diff --git a/source/Protocol/Protocol16x.cpp b/source/Protocol/Protocol16x.cpp
index 3a640da21..be5b45f19 100644
--- a/source/Protocol/Protocol16x.cpp
+++ b/source/Protocol/Protocol16x.cpp
@@ -213,6 +213,10 @@ int cProtocol161::ParseSteerVehicle(void)
{
m_Client->HandleUnmount();
}
+ else
+ {
+ m_Client->HandleSteerVehicle(Forward, Sideways);
+ }
return PARSE_OK;
}
diff --git a/source/Vector3d.cpp b/source/Vector3d.cpp
index 987c380dc..96ebebab5 100644
--- a/source/Vector3d.cpp
+++ b/source/Vector3d.cpp
@@ -8,16 +8,70 @@
-Vector3d::Vector3d(const Vector3f & v )
- : x( v.x )
- , y( v.y )
- , z( v.z )
+const double Vector3d::EPS = 0.000001; ///< The max difference between two coords for which the coords are assumed equal
+const double Vector3d::NO_INTERSECTION = 1e70; ///< Return value of LineCoeffToPlane() if the line is parallel to the plane
+
+
+
+
+
+Vector3d::Vector3d(const Vector3f & v) :
+ x(v.x),
+ y(v.y),
+ z(v.z)
+{
+}
+
+
+
+
+
+Vector3d::Vector3d(const Vector3f * v) :
+ x(v->x),
+ y(v->y),
+ z(v->z)
{
}
-Vector3d::Vector3d(const Vector3f * v )
- : x( v->x )
- , y( v->y )
- , z( v->z )
+
+
+
+
+double Vector3d::LineCoeffToXYPlane(const Vector3d & a_OtherEnd, double a_Z) const
{
-} \ No newline at end of file
+ if (abs(z - a_OtherEnd.z) < EPS)
+ {
+ return NO_INTERSECTION;
+ }
+ return (a_Z - z) / (a_OtherEnd.z - z);
+}
+
+
+
+
+
+double Vector3d::LineCoeffToXZPlane(const Vector3d & a_OtherEnd, double a_Y) const
+{
+ if (abs(y - a_OtherEnd.y) < EPS)
+ {
+ return NO_INTERSECTION;
+ }
+ return (a_Y - y) / (a_OtherEnd.y - y);
+}
+
+
+
+
+
+double Vector3d::LineCoeffToYZPlane(const Vector3d & a_OtherEnd, double a_X) const
+{
+ if (abs(x - a_OtherEnd.x) < EPS)
+ {
+ return NO_INTERSECTION;
+ }
+ return (a_X - x) / (a_OtherEnd.x - x);
+}
+
+
+
+
diff --git a/source/Vector3d.h b/source/Vector3d.h
index ecc72e421..a06a17c09 100644
--- a/source/Vector3d.h
+++ b/source/Vector3d.h
@@ -3,26 +3,54 @@
#include <math.h>
class Vector3f;
-class Vector3d // tolua_export
-{ // tolua_export
-public: // tolua_export
+
+
+
+// tolua_begin
+
+class Vector3d
+{
+public:
// convert from float
- Vector3d(const Vector3f & v ); // tolua_export
- Vector3d(const Vector3f * v ); // tolua_export
+ Vector3d(const Vector3f & v);
+ Vector3d(const Vector3f * v);
+
+ Vector3d() : x(0), y(0), z(0) {}
+ Vector3d(double a_x, double a_y, double a_z) : x(a_x), y(a_y), z(a_z) {}
+
+ inline void Set(double a_x, double a_y, double a_z) { x = a_x, y = a_y, z = a_z; }
+ inline void Normalize() { double l = 1.0f / Length(); x *= l; y *= l; z *= l; }
+ inline Vector3d NormalizeCopy() { double l = 1.0f / Length(); return Vector3d( x * l, y * l, z * l ); }
+ inline void NormalizeCopy(Vector3d & a_V) { double l = 1.0f / Length(); a_V.Set(x*l, y*l, z*l ); }
+ inline double Length() const { return (double)sqrt( x * x + y * y + z * z ); }
+ inline double SqrLength() const { return x * x + y * y + z * z; }
+ inline double Dot( const Vector3d & a_V ) const { return x * a_V.x + y * a_V.y + z * a_V.z; }
+ inline Vector3d Cross( const Vector3d & v ) const { return Vector3d( y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x ); }
+
+ /** Returns the coefficient for the (a_OtherEnd - this) line to reach the specified Z coord
+ The result satisfies the following equation:
+ (*this + Result * (a_OtherEnd - *this)).z = a_Z
+ If the line is too close to being parallel, this function returns NO_INTERSECTION
+ */
+ double LineCoeffToXYPlane(const Vector3d & a_OtherEnd, double a_Z) const;
- Vector3d() : x(0), y(0), z(0) {} // tolua_export
- Vector3d(double a_x, double a_y, double a_z) : x(a_x), y(a_y), z(a_z) {} // tolua_export
+ /** Returns the coefficient for the (a_OtherEnd - this) line to reach the specified Y coord
+ The result satisfies the following equation:
+ (*this + Result * (a_OtherEnd - *this)).y = a_Y
+ If the line is too close to being parallel, this function returns NO_INTERSECTION
+ */
+ double LineCoeffToXZPlane(const Vector3d & a_OtherEnd, double a_Y) const;
- inline void Set(double a_x, double a_y, double a_z) { x = a_x, y = a_y, z = a_z; } // tolua_export
- inline void Normalize() { double l = 1.0f / Length(); x *= l; y *= l; z *= l; } // tolua_export
- inline Vector3d NormalizeCopy() { double l = 1.0f / Length(); return Vector3d( x * l, y * l, z * l ); } // tolua_export
- inline void NormalizeCopy(Vector3d & a_V) { double l = 1.0f / Length(); a_V.Set(x*l, y*l, z*l ); } // tolua_export
- inline double Length() const { return (double)sqrt( x * x + y * y + z * z ); } // tolua_export
- inline double SqrLength() const { return x * x + y * y + z * z; } // tolua_export
- inline double Dot( const Vector3d & a_V ) const { return x * a_V.x + y * a_V.y + z * a_V.z; } // tolua_export
- inline Vector3d Cross( const Vector3d & v ) const { return Vector3d( y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x ); } // tolua_export
+ /** Returns the coefficient for the (a_OtherEnd - this) line to reach the specified X coord
+ The result satisfies the following equation:
+ (*this + Result * (a_OtherEnd - *this)).x = a_X
+ If the line is too close to being parallel, this function returns NO_INTERSECTION
+ */
+ double LineCoeffToYZPlane(const Vector3d & a_OtherEnd, double a_X) const;
- inline bool Equals( const Vector3d & v ) const { return (x == v.x && y == v.y && z == v.z ); } // tolua_export
+ inline bool Equals(const Vector3d & v) const { return ((x == v.x) && (y == v.y) && (z == v.z)); }
+
+ // tolua_end
void operator += ( const Vector3d& a_V ) { x += a_V.x; y += a_V.y; z += a_V.z; }
void operator += ( Vector3d* a_V ) { x += a_V->x; y += a_V->y; z += a_V->z; }
@@ -30,14 +58,24 @@ 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 double f) const { return Vector3d(x / f, y / f, z / f ); } // tolua_export
+ // tolua_begin
+
+ Vector3d operator + (const Vector3d & v2) const { return Vector3d(x + v2.x, y + v2.y, z + v2.z ); }
+ Vector3d operator + (const Vector3d * v2) const { return Vector3d(x + v2->x, y + v2->y, z + v2->z ); }
+ Vector3d operator - (const Vector3d & v2) const { return Vector3d(x - v2.x, y - v2.y, z - v2.z ); }
+ Vector3d operator - (const Vector3d * v2) const { return Vector3d(x - v2->x, y - v2->y, z - v2->z ); }
+ Vector3d operator * (const double f) const { return Vector3d(x * f, y * f, z * f ); }
+ Vector3d operator * (const Vector3d & v2) const { return Vector3d(x * v2.x, y * v2.y, z * v2.z ); }
+ Vector3d operator / (const double f) const { return Vector3d(x / f, y / f, z / f ); }
+
+ double x, y, z;
+
+ static const double EPS; ///< The max difference between two coords for which the coords are assumed equal
+ static const double NO_INTERSECTION; ///< Return value of LineCoeffToPlane() if the line is parallel to the plane
+} ;
+
+// tolua_end
+
+
- double x, y, z; // tolua_export
-};// tolua_export
diff --git a/source/World.cpp b/source/World.cpp
index 1d403994d..882cf90d2 100644
--- a/source/World.cpp
+++ b/source/World.cpp
@@ -525,7 +525,7 @@ void cWorld::Start(void)
m_LastSave = 0;
m_LastUnload = 0;
- // preallocate some memory for ticking blocks so we don�t need to allocate that often
+ // preallocate some memory for ticking blocks so we don't need to allocate that often
m_BlockTickQueue.reserve(1000);
m_BlockTickQueueCopy.reserve(1000);
@@ -969,7 +969,7 @@ bool cWorld::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback
-void cWorld::DoExplosiontAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData)
+void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData)
{
if (cPluginManager::Get()->CallHookExploding(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData) || (a_ExplosionSize <= 0))
{
@@ -979,7 +979,7 @@ void cWorld::DoExplosiontAt(double a_ExplosionSize, double a_BlockX, double a_Bl
// TODO: Add damage to entities, add support for pickups, and implement block hardiness
Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ);
cVector3iArray BlocksAffected;
- m_ChunkMap->DoExplosiontAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ, BlocksAffected);
+ m_ChunkMap->DoExplosionAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ, BlocksAffected);
BroadcastSoundEffect("random.explode", (int)floor(a_BlockX * 8), (int)floor(a_BlockY * 8), (int)floor(a_BlockZ * 8), 1.0f, 0.6f);
{
cCSLock Lock(m_CSPlayers);
diff --git a/source/World.h b/source/World.h
index 1f82f4efc..16ef6b3ce 100644
--- a/source/World.h
+++ b/source/World.h
@@ -334,10 +334,15 @@ public:
void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData);
NIBBLETYPE GetBlockSkyLight (int a_BlockX, int a_BlockY, int a_BlockZ);
NIBBLETYPE GetBlockBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ);
- bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
- bool GetBlockInfo (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
+
+ // tolua_end
+
+ bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta); // TODO: Exported in ManualBindings.cpp
+ bool GetBlockInfo (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight); // TODO: Exported in ManualBindings.cpp
// TODO: NIBBLETYPE GetBlockActualLight(int a_BlockX, int a_BlockY, int a_BlockZ);
+ // tolua_begin
+
// Vector3i variants:
void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta ); }
BLOCKTYPE GetBlock (const Vector3i & a_Pos ) { return GetBlock( a_Pos.x, a_Pos.y, a_Pos.z ); }
@@ -414,13 +419,13 @@ public:
| esCreeper | cCreeper * |
| esBed | cVector3i * |
| esEnderCrystal | Vector3i * |
- | esGhastFireball | TBD |
+ | esGhastFireball | cGhastFireball * |
| esWitherSkullBlack | TBD |
| esWitherSkullBlue | TBD |
| esWitherBirth | TBD |
| esPlugin | void * |
*/
- void DoExplosiontAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData); // tolua_export
+ void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData); // tolua_export
/// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found
bool DoWithChestAt (int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp
diff --git a/source/WorldStorage/NBTChunkSerializer.cpp b/source/WorldStorage/NBTChunkSerializer.cpp
index baae0dc01..11dc50ee3 100644
--- a/source/WorldStorage/NBTChunkSerializer.cpp
+++ b/source/WorldStorage/NBTChunkSerializer.cpp
@@ -19,6 +19,7 @@
#include "../OSSupport/MakeDir.h"
#include "FastNBT.h"
#include "../Entities/FallingBlock.h"
+#include "../Entities/Boat.h"
#include "../Entities/Minecart.h"
#include "../Mobs/Monster.h"
#include "../Entities/Pickup.h"
@@ -252,6 +253,17 @@ void cNBTChunkSerializer::AddBasicEntity(cEntity * a_Entity, const AString & a_C
+void cNBTChunkSerializer::AddBoatEntity(cBoat * a_Boat)
+{
+ m_Writer.BeginCompound("");
+ AddBasicEntity(a_Boat, "Boat");
+ m_Writer.EndCompound();
+}
+
+
+
+
+
void cNBTChunkSerializer::AddFallingBlockEntity(cFallingBlock * a_FallingBlock)
{
m_Writer.BeginCompound("");
@@ -340,7 +352,7 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
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("inTile", 0); // TODO: Query the block type
m_Writer.AddShort("shake", 0); // TODO: Any shake?
m_Writer.AddByte ("inGround", a_Projectile->IsInGround() ? 1 : 0);
@@ -360,6 +372,7 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
}
case cProjectileEntity::pkFireCharge:
case cProjectileEntity::pkWitherSkull:
+ case cProjectileEntity::pkEnderPearl:
{
m_Writer.BeginList("Motion", TAG_Double);
m_Writer.AddDouble("", a_Projectile->GetSpeedX());
@@ -461,6 +474,7 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity)
switch (a_Entity->GetEntityType())
{
+ case cEntity::etBoat: AddBoatEntity ((cBoat *) 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;
diff --git a/source/WorldStorage/NBTChunkSerializer.h b/source/WorldStorage/NBTChunkSerializer.h
index 481c578f3..9d4ac208c 100644
--- a/source/WorldStorage/NBTChunkSerializer.h
+++ b/source/WorldStorage/NBTChunkSerializer.h
@@ -19,6 +19,7 @@
class cFastNBTWriter;
class cEntity;
class cBlockEntity;
+class cBoat;
class cChestEntity;
class cDispenserEntity;
class cDropperEntity;
@@ -94,6 +95,7 @@ protected:
// Entities:
void AddBasicEntity (cEntity * a_Entity, const AString & a_ClassName);
+ void AddBoatEntity (cBoat * a_Boat);
void AddFallingBlockEntity(cFallingBlock * a_FallingBlock);
void AddMinecartEntity (cMinecart * a_Minecart);
void AddMonsterEntity (cMonster * a_Monster);
diff --git a/source/WorldStorage/WSSAnvil.cpp b/source/WorldStorage/WSSAnvil.cpp
index 3ab64148e..4db1ed106 100644
--- a/source/WorldStorage/WSSAnvil.cpp
+++ b/source/WorldStorage/WSSAnvil.cpp
@@ -23,6 +23,7 @@
#include "../OSSupport/MakeDir.h"
#include "FastNBT.h"
#include "../Mobs/Monster.h"
+#include "../Entities/Boat.h"
#include "../Entities/FallingBlock.h"
#include "../Entities/Minecart.h"
#include "../Entities/Pickup.h"
@@ -911,7 +912,11 @@ void cWSSAnvil::LoadSignFromNBT(cBlockEntityList & a_BlockEntities, const cParse
void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength)
{
- if (strncmp(a_IDTag, "FallingBlock", a_IDTagLength) == 0)
+ if (strncmp(a_IDTag, "Boat", a_IDTagLength) == 0)
+ {
+ LoadBoatFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
+ else if (strncmp(a_IDTag, "FallingBlock", a_IDTagLength) == 0)
{
LoadFallingBlockFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
@@ -952,14 +957,34 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{
LoadMinecartHFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
- if (strncmp(a_IDTag, "Item", a_IDTagLength) == 0)
+ else if (strncmp(a_IDTag, "Item", a_IDTagLength) == 0)
{
LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
- if (strncmp(a_IDTag, "Arrow", a_IDTagLength) == 0)
+ else if (strncmp(a_IDTag, "Arrow", a_IDTagLength) == 0)
{
LoadArrowFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
+ else if (strncmp(a_IDTag, "Snowball", a_IDTagLength) == 0)
+ {
+ LoadSnowballFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
+ else if (strncmp(a_IDTag, "Egg", a_IDTagLength) == 0)
+ {
+ LoadEggFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
+ else if (strncmp(a_IDTag, "Fireball", a_IDTagLength) == 0)
+ {
+ LoadFireballFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
+ else if (strncmp(a_IDTag, "SmallFireball", a_IDTagLength) == 0)
+ {
+ LoadFireChargeFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
+ else if (strncmp(a_IDTag, "ThrownEnderpearl", a_IDTagLength) == 0)
+ {
+ LoadThrownEnderpearlFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
// TODO: other entities
}
@@ -967,6 +992,20 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
+void cWSSAnvil::LoadBoatFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cBoat> Boat(new cBoat(0, 0, 0));
+ if (!LoadEntityBaseFromNBT(*Boat.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+ a_Entities.push_back(Boat.release());
+}
+
+
+
+
+
void cWSSAnvil::LoadFallingBlockFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
// TODO
@@ -1100,7 +1139,7 @@ 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))
+ if (!LoadProjectileBaseFromNBT(*Arrow.get(), a_NBT, a_TagIdx))
{
return;
}
@@ -1136,6 +1175,86 @@ void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
+void cWSSAnvil::LoadSnowballFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cThrownSnowballEntity> Snowball(new cThrownSnowballEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
+ if (!LoadProjectileBaseFromNBT(*Snowball.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ // Store the new snowball in the entities list:
+ a_Entities.push_back(Snowball.release());
+}
+
+
+
+
+
+void cWSSAnvil::LoadEggFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cThrownEggEntity> Egg(new cThrownEggEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
+ if (!LoadProjectileBaseFromNBT(*Egg.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ // Store the new egg in the entities list:
+ a_Entities.push_back(Egg.release());
+}
+
+
+
+
+
+void cWSSAnvil::LoadFireballFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cGhastFireballEntity> Fireball(new cGhastFireballEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
+ if (!LoadProjectileBaseFromNBT(*Fireball.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ // Store the new fireball in the entities list:
+ a_Entities.push_back(Fireball.release());
+}
+
+
+
+
+
+void cWSSAnvil::LoadFireChargeFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cFireChargeEntity> FireCharge(new cFireChargeEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
+ if (!LoadProjectileBaseFromNBT(*FireCharge.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ // Store the new FireCharge in the entities list:
+ a_Entities.push_back(FireCharge.release());
+}
+
+
+
+
+
+void cWSSAnvil::LoadThrownEnderpearlFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cThrownEnderPearlEntity> Enderpearl(new cThrownEnderPearlEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
+ if (!LoadProjectileBaseFromNBT(*Enderpearl.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ // Store the new enderpearl in the entities list:
+ a_Entities.push_back(Enderpearl.release());
+}
+
+
+
+
+
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
{
double Pos[3];
@@ -1167,6 +1286,30 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N
+bool cWSSAnvil::LoadProjectileBaseFromNBT(cProjectileEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ if (!LoadEntityBaseFromNBT(a_Entity, a_NBT, a_TagIdx))
+ {
+ return false;
+ }
+
+ bool IsInGround = false;
+ int InGroundIdx = a_NBT.FindChildByName(a_TagIdx, "inGround");
+ if (InGroundIdx > 0)
+ {
+ IsInGround = (a_NBT.GetByte(InGroundIdx) != 0);
+ }
+ a_Entity.SetIsInGround(IsInGround);
+
+ // TODO: Load inTile, TileCoords
+
+ return true;
+}
+
+
+
+
+
bool cWSSAnvil::LoadDoublesListFromNBT(double * a_Doubles, int a_NumDoubles, const cParsedNBT & a_NBT, int a_TagIdx)
{
if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List) || (a_NBT.GetChildrenType(a_TagIdx) != TAG_Double))
diff --git a/source/WorldStorage/WSSAnvil.h b/source/WorldStorage/WSSAnvil.h
index b2556ab50..7685d2236 100644
--- a/source/WorldStorage/WSSAnvil.h
+++ b/source/WorldStorage/WSSAnvil.h
@@ -18,6 +18,8 @@
// fwd: ItemGrid.h
class cItemGrid;
+class cProjectileEntity;
+
@@ -138,18 +140,27 @@ protected:
void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength);
- void LoadFallingBlockFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadMinecartRFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadMinecartCFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadMinecartFFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
- 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);
+ void LoadBoatFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadFallingBlockFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadMinecartRFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadMinecartCFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadMinecartFFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ 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);
+ void LoadSnowballFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadEggFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadFireballFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadFireChargeFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadThrownEnderpearlFromNBT(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);
+ /// Loads projectile common data from the NBT compound; returns true if successful
+ bool LoadProjectileBaseFromNBT(cProjectileEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIx);
+
/// Loads an array of doubles of the specified length from the specified NBT list tag a_TagIdx; returns true if successful
bool LoadDoublesListFromNBT(double * a_Doubles, int a_NumDoubles, const cParsedNBT & a_NBT, int a_TagIdx);