diff options
Diffstat (limited to '')
-rw-r--r-- | src/Bindings/ManualBindings_World.cpp | 588 |
1 files changed, 588 insertions, 0 deletions
diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp new file mode 100644 index 000000000..3ee5ca498 --- /dev/null +++ b/src/Bindings/ManualBindings_World.cpp @@ -0,0 +1,588 @@ + +// ManualBindings_World.cpp + +// Implements the manual Lua API bindings for the cWorld class + +#include "Globals.h" +#include "tolua++/include/tolua++.h" +#include "../World.h" +#include "../Broadcaster.h" +#include "ManualBindings.h" +#include "LuaState.h" +#include "PluginLua.h" +#include "LuaChunkStay.h" + + + + + +static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S) +{ + /* Function signature: + World:BroadcastParticleEffect("Name", PosX, PosY, PosZ, OffX, OffY, OffZ, ParticleData, ParticleAmount, [ExcludeClient], [OptionalParam1], [OptionalParam2] + */ + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamString (2) || + !L.CheckParamNumber (3, 10) + ) + { + return 0; + } + + // Read the params: + cWorld * World = nullptr; + AString Name; + float PosX, PosY, PosZ, OffX, OffY, OffZ; + float ParticleData; + int ParticleAmmount; + cClientHandle * ExcludeClient = nullptr; + L.GetStackValues(1, World, Name, PosX, PosY, PosZ, OffX, OffY, OffZ, ParticleData, ParticleAmmount, ExcludeClient); + if (World == nullptr) + { + LOGWARNING("World:BroadcastParticleEffect(): invalid world parameter"); + L.LogStackTrace(); + return 0; + } + + // Read up to 2 more optional data params: + std::array<int, 2> data; + for (int i = 0; (i < 2) && L.IsParamNumber(11 + i); i++) + { + L.GetStackValue(11 + i, data[i]); + } + + World->GetBroadcaster().BroadcastParticleEffect(Name, Vector3f(PosX, PosY, PosZ), Vector3f(OffX, OffY, OffZ), ParticleData, ParticleAmmount, ExcludeClient); + + return 0; +} + + + + + +static int tolua_cWorld_ChunkStay(lua_State * tolua_S) +{ + /* Function signature: + World:ChunkStay(ChunkCoordTable, OnChunkAvailable, OnAllChunksAvailable) + ChunkCoordTable == { {Chunk1x, Chunk1z}, {Chunk2x, Chunk2z}, ... } + */ + + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType (1, "cWorld") || + !L.CheckParamTable (2) || + !L.CheckParamFunctionOrNil(3, 4) + ) + { + return 0; + } + + cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S); + if (Plugin == nullptr) + { + return 0; + } + + // Read the params: + cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr); + if (World == nullptr) + { + LOGWARNING("World:ChunkStay(): invalid world parameter"); + L.LogStackTrace(); + return 0; + } + + cLuaChunkStay * ChunkStay = new cLuaChunkStay(*Plugin); + + if (!ChunkStay->AddChunks(2)) + { + delete ChunkStay; + ChunkStay = nullptr; + return 0; + } + + ChunkStay->Enable(*World->GetChunkMap(), 3, 4); + return 0; +} + + + + + +static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S) +{ + // Exported manually, because tolua would generate useless additional parameters (a_BlockType .. a_BlockSkyLight) + // Function signature: GetBlockInfo(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight] + + // Check params: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamNumber(2, 4) || + !L.CheckParamEnd(5) + ) + { + return 0; + } + + // Get params: + cWorld * Self = nullptr; + int BlockX, BlockY, BlockZ; + L.GetStackValues(1, Self, BlockX, BlockY, BlockZ); + if (Self == nullptr) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); + } + + // Call the function: + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta, BlockSkyLight, BlockBlockLight; + bool res = Self->GetBlockInfo(BlockX, BlockY, BlockZ, BlockType, BlockMeta, BlockSkyLight, BlockBlockLight); + + // Push the returned values: + L.Push(res); + if (res) + { + L.Push(BlockType); + L.Push(BlockMeta); + L.Push(BlockSkyLight); + L.Push(BlockBlockLight); + return 5; + } + return 1; +} + + + + + +static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S) +{ + // Exported manually, because tolua would generate useless additional parameters (a_BlockType, a_BlockMeta) + // Function signature: GetBlockTypeMeta(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta] + + // Check params: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamNumber(2, 4) || + !L.CheckParamEnd(5) + ) + { + return 0; + } + + // Get params: + cWorld * Self = nullptr; + int BlockX, BlockY, BlockZ; + L.GetStackValues(1, Self, BlockX, BlockY, BlockZ); + if (Self == nullptr) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); + } + + // Call the function: + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + bool res = Self->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta); + + // Push the returned values: + L.Push(res); + if (res) + { + L.Push(BlockType); + L.Push(BlockMeta); + return 3; + } + return 1; +} + + + + + +static int tolua_cWorld_GetSignLines(lua_State * tolua_S) +{ + // Exported manually, because tolua would generate useless additional parameters (a_Line1 .. a_Line4) + + // Check params: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamNumber(2, 4) || + !L.CheckParamEnd(5) + ) + { + return 0; + } + + // Get params: + cWorld * Self = nullptr; + int BlockX, BlockY, BlockZ; + L.GetStackValues(1, Self, BlockX, BlockY, BlockZ); + if (Self == nullptr) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); + } + + // Call the function: + AString Line1, Line2, Line3, Line4; + bool res = Self->GetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); + + // Push the returned values: + L.Push(res); + if (res) + { + L.Push(Line1); + L.Push(Line2); + L.Push(Line3); + L.Push(Line4); + return 5; + } + return 1; +} + + + + + +static int tolua_cWorld_PrepareChunk(lua_State * tolua_S) +{ + /* Function signature: + World:PrepareChunk(ChunkX, ChunkZ, Callback) + */ + + // Check the param types: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType (1, "cWorld") || + !L.CheckParamNumber (2, 3) || + !L.CheckParamFunctionOrNil(4) + ) + { + return 0; + } + + // Read the params: + cWorld * world = nullptr; + int chunkX = 0, chunkZ = 0; + L.GetStackValues(1, world, chunkX, chunkZ); + if (world == nullptr) + { + LOGWARNING("World:PrepareChunk(): invalid world parameter"); + L.LogStackTrace(); + return 0; + } + + // Wrap the Lua callback inside a C++ callback class: + class cCallback: + public cChunkCoordCallback + { + public: + cCallback(lua_State * a_LuaState): + m_LuaState(a_LuaState), + m_Callback(m_LuaState, 4) + { + } + + // cChunkCoordCallback override: + virtual void Call(int a_CBChunkX, int a_CBChunkZ) override + { + if (m_Callback.IsValid()) + { + m_LuaState.Call(m_Callback, a_CBChunkX, a_CBChunkZ); + } + + // This is the last reference of this object, we must delete it so that it doesn't leak: + delete this; + } + + protected: + cLuaState m_LuaState; + cLuaState::cRef m_Callback; + }; + cCallback * callback = new cCallback(tolua_S); + + // Call the chunk preparation: + world->PrepareChunk(chunkX, chunkZ, callback); + return 0; +} + + + + + +class cLuaWorldTask : + public cWorld::cTask, + public cPluginLua::cResettable +{ +public: + cLuaWorldTask(cPluginLua & a_Plugin, int a_FnRef) : + cPluginLua::cResettable(a_Plugin), + m_FnRef(a_FnRef) + { + } + +protected: + int m_FnRef; + + // cWorld::cTask overrides: + virtual void Run(cWorld & a_World) override + { + cCSLock Lock(m_CSPlugin); + if (m_Plugin != nullptr) + { + m_Plugin->Call(m_FnRef, &a_World); + } + } +} ; + + + + + +static int tolua_cWorld_QueueTask(lua_State * tolua_S) +{ + // Binding for cWorld::QueueTask + // Params: function + + // Retrieve the cPlugin from the LuaState: + cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S); + if (Plugin == nullptr) + { + // An error message has been already printed in GetLuaPlugin() + return 0; + } + + // Retrieve the args: + cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr); + if (self == nullptr) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance"); + } + if (!lua_isfunction(tolua_S, 2)) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1"); + } + + // Create a reference to the function: + int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); + if (FnRef == LUA_REFNIL) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1"); + } + + auto task = std::make_shared<cLuaWorldTask>(*Plugin, FnRef); + Plugin->AddResettable(task); + self->QueueTask(task); + return 0; +} + + + + + +static int tolua_cWorld_SetSignLines(lua_State * tolua_S) +{ + // Exported manually, because tolua would generate useless additional return values (a_Line1 .. a_Line4) + + // Check params: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamNumber(2, 4) || + !L.CheckParamString(5, 8) || + !L.CheckParamEnd(9) + ) + { + return 0; + } + + // Get params: + cWorld * Self = nullptr; + int BlockX, BlockY, BlockZ; + AString Line1, Line2, Line3, Line4; + L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); + if (Self == nullptr) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); + } + + // Call the function: + bool res = Self->SetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); + + // Push the returned values: + L.Push(res); + return 1; +} + + + + + +class cLuaScheduledWorldTask : + public cWorld::cTask, + public cPluginLua::cResettable +{ +public: + cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef) : + cPluginLua::cResettable(a_Plugin), + m_FnRef(a_FnRef) + { + } + +protected: + int m_FnRef; + + // cWorld::cTask overrides: + virtual void Run(cWorld & a_World) override + { + cCSLock Lock(m_CSPlugin); + if (m_Plugin != nullptr) + { + m_Plugin->Call(m_FnRef, &a_World); + } + } +}; + + + + + +static int tolua_cWorld_ScheduleTask(lua_State * tolua_S) +{ + // Binding for cWorld::ScheduleTask + // Params: function, Ticks + + // Retrieve the cPlugin from the LuaState: + cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S); + if (Plugin == nullptr) + { + // An error message has been already printed in GetLuaPlugin() + return 0; + } + + // Retrieve the args: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamNumber (2) || + !L.CheckParamFunction(3) + ) + { + return 0; + } + cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr); + if (World == nullptr) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance"); + } + + // Create a reference to the function: + int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); + if (FnRef == LUA_REFNIL) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1"); + } + + int DelayTicks = (int)tolua_tonumber(tolua_S, 2, 0); + + auto task = std::make_shared<cLuaScheduledWorldTask>(*Plugin, FnRef); + Plugin->AddResettable(task); + World->ScheduleTask(DelayTicks, task); + return 0; +} + + + + + + +static int tolua_cWorld_TryGetHeight(lua_State * tolua_S) +{ + /* Exported manually, because tolua would require the out-only param a_Height to be used when calling + Function signature: world:TryGetHeight(a_World, a_BlockX, a_BlockZ) -> IsValid, Height + */ + + // Check params: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamNumber(2, 3) || + !L.CheckParamEnd(4) + ) + { + return 0; + } + + // Get params: + cWorld * self = nullptr; + int BlockX, BlockZ; + L.GetStackValues(1, self, BlockX, BlockZ); + if (self == nullptr) + { + tolua_error(tolua_S, "Invalid 'self' in function 'TryGetHeight'", nullptr); + return 0; + } + + // Call the implementation: + int Height = 0; + bool res = self->TryGetHeight(BlockX, BlockZ, Height); + L.Push(res ? 1 : 0); + if (res) + { + L.Push(Height); + return 2; + } + return 1; +} + + + + + +void cManualBindings::BindWorld(lua_State * tolua_S) +{ + tolua_beginmodule(tolua_S, nullptr); + tolua_beginmodule(tolua_S, "cWorld"); + tolua_function(tolua_S, "BroadcastParticleEffect", tolua_cWorld_BroadcastParticleEffect); + tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay); + tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>); + tolua_function(tolua_S, "DoWithBeaconAt", DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>); + tolua_function(tolua_S, "DoWithChestAt", DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>); + tolua_function(tolua_S, "DoWithDispenserAt", DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>); + tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithXYZ<cWorld, cDropSpenserEntity, &cWorld::DoWithDropSpenserAt>); + tolua_function(tolua_S, "DoWithDropperAt", DoWithXYZ<cWorld, cDropperEntity, &cWorld::DoWithDropperAt>); + tolua_function(tolua_S, "DoWithEntityByID", DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); + tolua_function(tolua_S, "DoWithFurnaceAt", DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>); + tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>); + tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithXYZ<cWorld, cCommandBlockEntity, &cWorld::DoWithCommandBlockAt>); + tolua_function(tolua_S, "DoWithMobHeadAt", DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadAt>); + tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>); + tolua_function(tolua_S, "DoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>); + tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>); + tolua_function(tolua_S, "DoWithPlayerByUUID", DoWith< cWorld, cPlayer, &cWorld::DoWithPlayerByUUID>); + tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>); + tolua_function(tolua_S, "ForEachChestInChunk", ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>); + tolua_function(tolua_S, "ForEachEntity", ForEach< cWorld, cEntity, &cWorld::ForEachEntity>); + tolua_function(tolua_S, "ForEachEntityInBox", ForEachInBox< cWorld, cEntity, &cWorld::ForEachEntityInBox>); + tolua_function(tolua_S, "ForEachEntityInChunk", ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>); + tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>); + tolua_function(tolua_S, "ForEachPlayer", ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>); + tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo); + tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta); + tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines); + tolua_function(tolua_S, "PrepareChunk", tolua_cWorld_PrepareChunk); + tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask); + tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask); + tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines); + tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight); + tolua_endmodule(tolua_S); + tolua_endmodule(tolua_S); +} + + + + |