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