From 876014b8e8941f6de69f07e3b4cc354e9bdf3e57 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Thu, 7 Jun 2012 21:07:21 +0000 Subject: Bonemeal works on crops, melons, pumpkins, saplings and grass. Plant growing has been refactored into separate functions callable from Lua, too. git-svn-id: http://mc-server.googlecode.com/svn/trunk@573 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Bindings.cpp | 124 ++++++++++++++++++++++++++++++++++++++++++++++- source/Bindings.h | 2 +- source/cChunk.cpp | 10 +++- source/cChunk.h | 3 ++ source/cChunkMap.cpp | 17 +++++++ source/cChunkMap.h | 3 ++ source/cClientHandle.cpp | 36 ++++++++++++-- source/cClientHandle.h | 3 ++ source/cWorld.cpp | 88 +++++++++++++++++++++++++++++++++ source/cWorld.h | 6 +++ 10 files changed, 286 insertions(+), 6 deletions(-) (limited to 'source') diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 1ebe6ceec..ab52bd5a1 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 06/06/12 21:50:56. +** Generated automatically by tolua++-1.0.92 on 06/07/12 23:02:08. */ #ifndef __cplusplus @@ -9884,6 +9884,49 @@ static int tolua_AllToLua_cWorld_GetBlockSkyLight00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: GetBlockTypeMeta of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetBlockTypeMeta00 +static int tolua_AllToLua_cWorld_GetBlockTypeMeta00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnumber(tolua_S,3,0,&tolua_err) || + !tolua_isnumber(tolua_S,4,0,&tolua_err) || + !tolua_isnumber(tolua_S,5,0,&tolua_err) || + !tolua_isnumber(tolua_S,6,0,&tolua_err) || + !tolua_isnoobj(tolua_S,7,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); + int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0)); + int a_BlockY = ((int) tolua_tonumber(tolua_S,3,0)); + int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0)); + char a_BlockType = ((char) tolua_tonumber(tolua_S,5,0)); + unsigned char a_BlockMeta = ((unsigned char) tolua_tonumber(tolua_S,6,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetBlockTypeMeta'", NULL); +#endif + { + self->GetBlockTypeMeta(a_BlockX,a_BlockY,a_BlockZ,a_BlockType,a_BlockMeta); + tolua_pushnumber(tolua_S,(lua_Number)a_BlockType); + tolua_pushnumber(tolua_S,(lua_Number)a_BlockMeta); + } + } + return 2; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetBlockTypeMeta'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: DigBlock of class cWorld */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_DigBlock00 static int tolua_AllToLua_cWorld_DigBlock00(lua_State* tolua_S) @@ -10208,6 +10251,82 @@ static int tolua_AllToLua_cWorld_GrowTreeByBiome00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: GrowPlant of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GrowPlant00 +static int tolua_AllToLua_cWorld_GrowPlant00(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_isnoobj(tolua_S,5,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); + int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0)); + int a_BlockY = ((int) tolua_tonumber(tolua_S,3,0)); + int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GrowPlant'", NULL); +#endif + { + self->GrowPlant(a_BlockX,a_BlockY,a_BlockZ); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GrowPlant'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GrowMelonPumpkin of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GrowMelonPumpkin00 +static int tolua_AllToLua_cWorld_GrowMelonPumpkin00(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); + int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0)); + int a_BlockY = ((int) tolua_tonumber(tolua_S,3,0)); + int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0)); + char a_BlockType = ((char) tolua_tonumber(tolua_S,5,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GrowMelonPumpkin'", NULL); +#endif + { + self->GrowMelonPumpkin(a_BlockX,a_BlockY,a_BlockZ,a_BlockType); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GrowMelonPumpkin'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: GetBiomeAt of class cWorld */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetBiomeAt00 static int tolua_AllToLua_cWorld_GetBiomeAt00(lua_State* tolua_S) @@ -18029,6 +18148,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"SetBlockMeta",tolua_AllToLua_cWorld_SetBlockMeta00); tolua_function(tolua_S,"SetBlockMeta",tolua_AllToLua_cWorld_SetBlockMeta01); tolua_function(tolua_S,"GetBlockSkyLight",tolua_AllToLua_cWorld_GetBlockSkyLight00); + tolua_function(tolua_S,"GetBlockTypeMeta",tolua_AllToLua_cWorld_GetBlockTypeMeta00); tolua_function(tolua_S,"DigBlock",tolua_AllToLua_cWorld_DigBlock00); tolua_function(tolua_S,"SendBlockTo",tolua_AllToLua_cWorld_SendBlockTo00); tolua_function(tolua_S,"GetSpawnX",tolua_AllToLua_cWorld_GetSpawnX00); @@ -18038,6 +18158,8 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"GrowTree",tolua_AllToLua_cWorld_GrowTree00); tolua_function(tolua_S,"GrowTreeFromSapling",tolua_AllToLua_cWorld_GrowTreeFromSapling00); tolua_function(tolua_S,"GrowTreeByBiome",tolua_AllToLua_cWorld_GrowTreeByBiome00); + tolua_function(tolua_S,"GrowPlant",tolua_AllToLua_cWorld_GrowPlant00); + tolua_function(tolua_S,"GrowMelonPumpkin",tolua_AllToLua_cWorld_GrowMelonPumpkin00); tolua_function(tolua_S,"GetBiomeAt",tolua_AllToLua_cWorld_GetBiomeAt00); tolua_function(tolua_S,"GetName",tolua_AllToLua_cWorld_GetName00); tolua_function(tolua_S,"SaveAllChunks",tolua_AllToLua_cWorld_SaveAllChunks00); diff --git a/source/Bindings.h b/source/Bindings.h index 568a4625f..3de48f101 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 06/06/12 21:50:56. +** Generated automatically by tolua++-1.0.92 on 06/07/12 23:02:09. */ /* Exported function */ diff --git a/source/cChunk.cpp b/source/cChunk.cpp index eba434ed1..aaef14cf3 100644 --- a/source/cChunk.cpp +++ b/source/cChunk.cpp @@ -659,7 +659,15 @@ void cChunk::TickMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, int a_BlockIdx FastSetBlock(m_BlockTickX, m_BlockTickY, m_BlockTickZ, a_BlockType, ++Meta); return; } - + GrowMelonPumpkin(a_RelX, a_RelY, a_RelZ, a_BlockType, a_TickRandom); +} + + + + + +void cChunk::GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_TickRandom) +{ // Convert the stem BlockType into produce BlockType BLOCKTYPE ProduceType; switch (a_BlockType) diff --git a/source/cChunk.h b/source/cChunk.h index 6fe4e77f7..3c01b08e5 100644 --- a/source/cChunk.h +++ b/source/cChunk.h @@ -235,6 +235,9 @@ private: void TickMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, int a_BlockIdx, BLOCKTYPE a_BlockType, MTRand & a_TickRandom); void TickFarmland (int a_RelX, int a_RelY, int a_RelZ); + /// Grows a melon or a pumpkin next to the block specified (assumed to be the stem) + void GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_Random); + /// Same as GetBlock(), but relative coords needn't be in this chunk (uses m_ChunkMap in such a case); returns true on success; only usable in Tick() bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta); diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp index 1db55485b..1638e2b06 100644 --- a/source/cChunkMap.cpp +++ b/source/cChunkMap.cpp @@ -1084,6 +1084,23 @@ void cChunkMap::GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty) +void cChunkMap::GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, MTRand & a_Rand) +{ + int ChunkX, ChunkZ; + cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ); + if (Chunk != NULL) + { + Chunk->GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_Rand); + } +} + + + + + void cChunkMap::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ) { int ChunkX, ChunkZ; diff --git a/source/cChunkMap.h b/source/cChunkMap.h index 659e5c17b..da5a5066f 100644 --- a/source/cChunkMap.h +++ b/source/cChunkMap.h @@ -151,6 +151,9 @@ public: /// Returns the number of valid chunks and the number of dirty chunks void GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty); + /// Grows a melon or a pumpkin next to the block specified (assumed to be the stem) + void GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, MTRand & a_Rand); + /// Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ); diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 96ee3fcbd..4c4461201 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -977,6 +977,7 @@ void cClientHandle::HandleBlockPlace(cPacket_BlockPlace * a_Packet) cDoors::ChangeDoor(m_Player->GetWorld(), a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ); break; } + default: { break; @@ -1211,12 +1212,12 @@ void cClientHandle::HandleBlockPlace(cPacket_BlockPlace * a_Packet) } case E_ITEM_SIGN: { - LOG("Sign Dir: %i", a_Packet->m_Direction); + LOGD("Sign Dir: %i", a_Packet->m_Direction); if (a_Packet->m_Direction == 1) { - LOG("Player Rotation: %f", m_Player->GetRotation()); + LOGD("Player Rotation: %f", m_Player->GetRotation()); MetaData = cSign::RotationToMetaData(m_Player->GetRotation()); - LOG("Sign rotation %i", MetaData); + LOGD("Sign rotation %i", MetaData); a_Packet->m_ItemType = E_BLOCK_SIGN_POST; } else @@ -1261,6 +1262,15 @@ void cClientHandle::HandleBlockPlace(cPacket_BlockPlace * a_Packet) a_Packet->m_ItemType = E_BLOCK_PUMPKIN_STEM; break; } + case E_ITEM_DYE: + { + // Handle bonemeal and dyes on sheep + if (HandleDyes(a_Packet)) + { + return; + } + break; + } default: { break; @@ -1557,6 +1567,26 @@ void cClientHandle::HandleKeepAlive(cPacket_KeepAlive * a_Packet) +bool cClientHandle::HandleDyes(cPacket_BlockPlace * a_Packet) +{ + cItem & Equipped = m_Player->GetInventory().GetEquippedItem(); + + // TODO: Handle coloring the sheep, too + + // Handle growing the plants: + if (Equipped.m_ItemHealth == E_META_DYE_WHITE) + { + cWorld * World = m_Player->GetWorld(); + World->GrowPlant(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ); + } + + return false; +} + + + + + bool cClientHandle::CheckBlockInteractionsRate(void) { ASSERT(m_Player != NULL); diff --git a/source/cClientHandle.h b/source/cClientHandle.h index 96b3ae08a..a8939f299 100644 --- a/source/cClientHandle.h +++ b/source/cClientHandle.h @@ -204,6 +204,9 @@ private: void HandleRespawn (void); void HandleDisconnect (cPacket_Disconnect * a_Packet); void HandleKeepAlive (cPacket_KeepAlive * a_Packet); + + /// Handles rclk with a dye; returns true if normal rclk processing should continue + bool HandleDyes(cPacket_BlockPlace * a_Packet); /// Returns true if the rate block interactions is within a reasonable limit (bot protection) bool CheckBlockInteractionsRate(void); diff --git a/source/cWorld.cpp b/source/cWorld.cpp index 7288dc303..fb2517a80 100644 --- a/source/cWorld.cpp +++ b/source/cWorld.cpp @@ -844,6 +844,94 @@ void cWorld::GrowTreeImage(const sSetBlockVector & a_Blocks) +void cWorld::GrowPlant(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta); + switch (BlockType) + { + case E_BLOCK_CROPS: + { + if (BlockMeta < 7) + { + FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, 7); + } + break; + } + + case E_BLOCK_MELON_STEM: + case E_BLOCK_PUMPKIN_STEM: + { + if (BlockMeta < 7) + { + FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, 7); + } + else + { + GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, BlockType); + } + break; + } + + case E_BLOCK_SAPLING: + { + GrowTreeFromSapling(a_BlockX, a_BlockY, a_BlockZ, BlockMeta); + break; + } + + case E_BLOCK_GRASS: + { + MTRand r1; + for (int i = 0; i < 60; i++) + { + int OfsX = (r1.randInt(3) + r1.randInt(3) + r1.randInt(3) + r1.randInt(3)) / 2 - 3; + int OfsY = r1.randInt(3) + r1.randInt(3) - 3; + int OfsZ = (r1.randInt(3) + r1.randInt(3) + r1.randInt(3) + r1.randInt(3)) / 2 - 3; + BLOCKTYPE Ground = GetBlock(a_BlockX + OfsX, a_BlockY + OfsY, a_BlockZ + OfsZ); + if (Ground != E_BLOCK_GRASS) + { + continue; + } + BLOCKTYPE Above = GetBlock(a_BlockX + OfsX, a_BlockY + OfsY + 1, a_BlockZ + OfsZ); + if (Above != E_BLOCK_AIR) + { + continue; + } + BLOCKTYPE SpawnType; + NIBBLETYPE SpawnMeta = 0; + switch (r1.randInt(10)) + { + case 0: SpawnType = E_BLOCK_YELLOW_FLOWER; break; + case 1: SpawnType = E_BLOCK_RED_ROSE; break; + default: + { + SpawnType = E_BLOCK_TALL_GRASS; + SpawnMeta = E_META_TALL_GRASS_GRASS; + break; + } + } // switch (random spawn block) + FastSetBlock(a_BlockX + OfsX, a_BlockY + OfsY + 1, a_BlockZ + OfsZ, SpawnType, SpawnMeta); + } // for i - 50 times + break; + } + } // switch (BlockType) +} + + + + + +void cWorld::GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockType) +{ + MTRand Rand; + m_ChunkMap->GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, Rand); +} + + + + + int cWorld::GetBiomeAt (int a_BlockX, int a_BlockZ) { return m_ChunkMap->GetBiomeAt(a_BlockX, a_BlockZ); diff --git a/source/cWorld.h b/source/cWorld.h index 0fca98771..85823f27e 100644 --- a/source/cWorld.h +++ b/source/cWorld.h @@ -243,6 +243,12 @@ public: void GrowTreeByBiome (int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export void GrowTreeImage(const sSetBlockVector & a_Blocks); + + /// Grows the plant at the specified block to its ripe stage (bonemeal used) + void GrowPlant(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export + + /// Grows a melon or a pumpkin next to the block specified (assumed to be the stem) + void GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockType); // tolua_export int GetBiomeAt (int a_BlockX, int a_BlockZ); // tolua_export -- cgit v1.2.3