From 086c8b1834bfca6a4af912abbd13fd570f7b0b33 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 16 Dec 2015 15:04:47 +0100 Subject: Revised the explosion-related Lua API and docs. Fixes #2746. --- Server/Plugins/APIDump/APIDesc.lua | 15 +- Server/Plugins/APIDump/Hooks/OnExploded.lua | 17 +-- Server/Plugins/APIDump/Hooks/OnExploding.lua | 23 +-- .../Plugins/APIDump/Writing-a-Cuberite-plugin.html | 7 +- Server/Plugins/APIDump/main_APIDump.lua | 2 +- src/Bindings/LuaState.cpp | 66 ++++----- src/Bindings/LuaState.h | 4 +- src/Bindings/ManualBindings_World.cpp | 162 ++++++++++++++++----- src/Bindings/PluginLua.cpp | 48 +++--- src/BlockID.h | 24 ++- src/World.h | 19 +-- 11 files changed, 243 insertions(+), 144 deletions(-) diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index 67689a2a5..be9f60662 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -2858,6 +2858,18 @@ end TrimString = {Params = "string", Return = "string", Notes = "Trims whitespace at both ends of the string"}, md5 = {Params = "string", Return = "string", Notes = "OBSOLETE, use the {{cCryptoHash}} functions instead.
Converts a string to a raw binary md5 hash."}, }, + Constants = + { + esBed = { Notes = "A bed explosion. The SourceData param is the {{Vector3i|position}} of the bed." }, + esEnderCrystal = { Notes = "An ender crystal entity explosion. The SourceData param is the {{cEntity|ender crystal entity}} object." }, + esGhastFireball = { Notes = "A ghast fireball explosion. The SourceData param is the {{cGhastFireballEntity|ghast fireball entity}} object." }, + esMonster = { Notes = "A monster explosion (creeper). The SourceData param is the {{cMonster|monster entity}} object." }, + esOther = { Notes = "Any other explosion. The SourceData param is unused." }, + esPlugin = { Notes = "An explosion started by a plugin, without any further information. The SourceData param is unused. "}, + esPrimedTNT = { Notes = "A TNT explosion. The SourceData param is the {{cTNTEntity|TNT entity}} object."}, + esWitherBirth = { Notes = "An explosion at a wither's birth. The SourceData param is the {{cMonster|wither entity}} object." }, + esWitherSkull = { Notes = "A wither skull explosion. The SourceData param is the {{cWitherSkullEntity|wither skull entity}} object." }, + }, ConstantGroups = { BlockTypes = @@ -2961,7 +2973,7 @@ end These constants are used to differentiate the various sources of explosions. They are used in the {{OnExploded|HOOK_EXPLODED}} hook, {{OnExploding|HOOK_EXPLODING}} hook and in the {{cWorld}}:DoExplosionAt() function. These constants also dictate the type of the additional - data provided with the explosions, such as the exploding {{cCreeper|creeper}} entity or the + data provided with the explosions, such as the exploding creeper {{cEntity|entity}} or the {{Vector3i|coords}} of the exploding bed. ]], }, @@ -3037,6 +3049,7 @@ end "cHopperEntity.__cBlockEntityWindowOwner__", "cLuaWindow.__cItemGrid__cListener__", "Globals._CuberiteInternal_.*", -- Ignore all internal Cuberite constants + "Globals.esMax", }, IgnoreVariables = diff --git a/Server/Plugins/APIDump/Hooks/OnExploded.lua b/Server/Plugins/APIDump/Hooks/OnExploded.lua index 6a01542ab..daca31237 100644 --- a/Server/Plugins/APIDump/Hooks/OnExploded.lua +++ b/Server/Plugins/APIDump/Hooks/OnExploded.lua @@ -11,20 +11,7 @@ return

The explosion carries with it the type of its source - whether it's a creeper exploding, or TNT, etc. It also carries the identification of the actual source. The exact type of the identification - depends on the source kind: - - - - - - - - - - - - -
SourceSourceData TypeNotes
esPrimedTNT{{cTNTEntity}}An exploding primed TNT entity
esCreeper{{cCreeper}}An exploding creeper or charged creeper
esBed{{Vector3i}}A bed exploding in the Nether or in the End. The bed coords are given.
esEnderCrystal{{Vector3i}}An ender crystal exploding upon hit. The block coords are given.
esGhastFireball{{cGhastFireballEntity}}A ghast fireball hitting ground or an {{cEntity|entity}}.
esWitherSkullBlackTBDA black wither skull hitting ground or an {{cEntity|entity}}.
esWitherSkullBlueTBDA blue wither skull hitting ground or an {{cEntity|entity}}.
esWitherBirthTBDA wither boss being created
esOtherTBDAny other previously unspecified type.
esPluginobjectAn explosion created by a plugin. The plugin may specify any kind of data.

+ depends on the source kind, see the {{Globals#ExplosionSource|esXXX}} constants' descriptions for details. ]], Params = { @@ -35,7 +22,7 @@ return { Name = "Y", Type = "number", Notes = "Y-coord of the explosion center" }, { Name = "Z", Type = "number", Notes = "Z-coord of the explosion center" }, { Name = "Source", Type = "eExplosionSource", Notes = "Source of the explosion. See the table above." }, - { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the table above." }, + { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the {{Globals#ExplosionSource|esXXX}} constants' descriptions." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function diff --git a/Server/Plugins/APIDump/Hooks/OnExploding.lua b/Server/Plugins/APIDump/Hooks/OnExploding.lua index e21b41be0..873202dc3 100644 --- a/Server/Plugins/APIDump/Hooks/OnExploding.lua +++ b/Server/Plugins/APIDump/Hooks/OnExploding.lua @@ -11,20 +11,7 @@ return

The explosion carries with it the type of its source - whether it's a creeper exploding, or TNT, etc. It also carries the identification of the actual source. The exact type of the identification - depends on the source kind: - - - - - - - - - - - - -
SourceSourceData TypeNotes
esPrimedTNT{{cTNTEntity}}An exploding primed TNT entity
esCreeper{{cCreeper}}An exploding creeper or charged creeper
esBed{{Vector3i}}A bed exploding in the Nether or in the End. The bed coords are given.
esEnderCrystal{{Vector3i}}An ender crystal exploding upon hit. The block coords are given.
esGhastFireball{{cGhastFireballEntity}}A ghast fireball hitting ground or an {{cEntity|entity}}.
esWitherSkullBlackTBDA black wither skull hitting ground or an {{cEntity|entity}}.
esWitherSkullBlueTBDA blue wither skull hitting ground or an {{cEntity|entity}}.
esWitherBirthTBDA wither boss being created
esOtherTBDAny other previously unspecified type.
esPluginobjectAn explosion created by a plugin. The plugin may specify any kind of data.

+ depends on the source kind, see the {{Globals#ExplosionSource|esXXX}} constants' descriptions for details ]], Params = { @@ -35,12 +22,16 @@ return { Name = "Y", Type = "number", Notes = "Y-coord of the explosion center" }, { Name = "Z", Type = "number", Notes = "Z-coord of the explosion center" }, { Name = "Source", Type = "eExplosionSource", Notes = "Source of the explosion. See the table above." }, - { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the table above." }, + { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the {{Globals#ExplosionSource|esXXX}} constants' description." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called, and finally Cuberite will process the explosion - destroy blocks and push + hurt entities. If the function - returns true, no other callback is called for this event and the explosion will not occur. + returns true, no other callback is called for this event and the explosion will not occur.

+

+ The hook handler may return up to two more values after the initial bool. The second returned value + overrides the CanCauseFire parameter for subsequent hook calls and the final explosion, the third + returned value overrides the ExplosionSize parameter for subsequent hook calls and the final explosion. ]], }, -- HOOK_EXPLODING } diff --git a/Server/Plugins/APIDump/Writing-a-Cuberite-plugin.html b/Server/Plugins/APIDump/Writing-a-Cuberite-plugin.html index 2b6af0d82..a75a925b3 100644 --- a/Server/Plugins/APIDump/Writing-a-Cuberite-plugin.html +++ b/Server/Plugins/APIDump/Writing-a-Cuberite-plugin.html @@ -209,10 +209,11 @@ function Explode(Split, Player) -- Create a callback ExplodePlayer with parameter Explodee, which Cuberite calls for every player on the server local HasExploded = false local ExplodePlayer = function(Explodee) - -- If the player we are currently at is the one we specified as the parameter + -- If the player name matches exactly if (Explodee:GetName() == Split[2]) then - -- Create an explosion at the same position as they are; see API docs for further details of this function - Player:GetWorld():DoExplosionAt(Explodee:GetPosX(), Explodee:GetPosY(), Explodee:GetPosZ(), false, esPlugin) + -- Create an explosion of force level 2 at the same position as they are + -- see API docs for further details of this function + Player:GetWorld():DoExplosionAt(2, Explodee:GetPosX(), Explodee:GetPosY(), Explodee:GetPosZ(), false, esPlugin) Player:SendMessageSuccess(Split[2] .. " was successfully exploded") HasExploded = true; return true -- Signalize to Cuberite that we do not need to call this callback for any more players diff --git a/Server/Plugins/APIDump/main_APIDump.lua b/Server/Plugins/APIDump/main_APIDump.lua index 68c843016..872fa60f4 100644 --- a/Server/Plugins/APIDump/main_APIDump.lua +++ b/Server/Plugins/APIDump/main_APIDump.lua @@ -786,7 +786,7 @@ local function WriteHtmlClass(a_ClassAPI, a_ClassMenu) cf:write("

"); cf:write(LinkifyString(group.TextBefore or "", Source)); WriteConstantTable(group.Constants, a_InheritedName or a_ClassAPI.Name); - cf:write(LinkifyString(group.TextAfter or "", Source), "

"); + cf:write(LinkifyString(group.TextAfter or "", Source), "


"); end end end diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index f5b2cac4a..953b6f17b 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -807,25 +807,6 @@ void cLuaState::Push(UInt32 a_Value) -void cLuaState::Push(void * a_Ptr) -{ - UNUSED(a_Ptr); - ASSERT(IsValid()); - - // Investigate the cause of this - what is the callstack? - // One code path leading here is the OnHookExploding / OnHookExploded with exotic parameters. Need to decide what to do with them - LOGWARNING("Lua engine: attempting to push a plain pointer, pushing nil instead."); - LOGWARNING("This indicates an unimplemented part of MCS bindings"); - LogStackTrace(); - - lua_pushnil(m_LuaState); - m_NumCurrentFunctionArgs += 1; -} - - - - - void cLuaState::Push(std::chrono::milliseconds a_Value) { ASSERT(IsValid()); @@ -838,20 +819,6 @@ void cLuaState::Push(std::chrono::milliseconds a_Value) -/* -void cLuaState::PushUserType(void * a_Object, const char * a_Type) -{ - ASSERT(IsValid()); - - tolua_pushusertype(m_LuaState, a_Object, a_Type); - m_NumCurrentFunctionArgs += 1; -} -*/ - - - - - bool cLuaState::GetStackValue(int a_StackPos, AString & a_Value) { size_t len = 0; @@ -1197,6 +1164,39 @@ bool cLuaState::CheckParamNumber(int a_StartParam, int a_EndParam) +bool cLuaState::CheckParamBool(int a_StartParam, int a_EndParam) +{ + ASSERT(IsValid()); + + if (a_EndParam < 0) + { + a_EndParam = a_StartParam; + } + + tolua_Error tolua_err; + for (int i = a_StartParam; i <= a_EndParam; i++) + { + if (tolua_isboolean(m_LuaState, i, 0, &tolua_err)) + { + continue; + } + // Not the correct parameter + lua_Debug entry; + VERIFY(lua_getstack(m_LuaState, 0, &entry)); + VERIFY(lua_getinfo (m_LuaState, "n", &entry)); + AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != nullptr) ? entry.name : "?"); + tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); + return false; + } // for i - Param + + // All params checked ok + return true; +} + + + + + bool cLuaState::CheckParamString(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 6b600e150..f66605332 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -259,7 +259,6 @@ public: void Push(int a_Value); void Push(long a_Value); void Push(const UInt32 a_Value); - void Push(void * a_Ptr); void Push(std::chrono::milliseconds a_time); // GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged. @@ -375,6 +374,9 @@ public: /** Returns true if the specified parameters on the stack are numbers; also logs warning if not */ bool CheckParamNumber(int a_StartParam, int a_EndParam = -1); + /** Returns true if the specified parameters on the stack are bools; also logs warning if not */ + bool CheckParamBool(int a_StartParam, int a_EndParam = -1); + /** Returns true if the specified parameters on the stack are strings; also logs warning if not */ bool CheckParamString(int a_StartParam, int a_EndParam = -1); diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp index 20fe880c1..225e71af5 100644 --- a/src/Bindings/ManualBindings_World.cpp +++ b/src/Bindings/ManualBindings_World.cpp @@ -110,6 +110,99 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S) + +static int tolua_cWorld_DoExplosionAt(lua_State * tolua_S) +{ + /* Function signature: + World:DoExplosionAt(ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceType, [SourceData]) + */ + + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType (1, "cWorld") || + !L.CheckParamNumber (2, 5) || + !L.CheckParamBool (6) || + !L.CheckParamNumber (7) || + !L.CheckParamEnd (9) + ) + { + return 0; + } + + // Read the params: + cWorld * World; + double ExplosionSize; + int BlockX, BlockY, BlockZ; + bool CanCauseFire; + int SourceTypeInt; + if (!L.GetStackValues(1, World, ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceTypeInt)) + { + LOGWARNING("World:DoExplosionAt(): invalid parameters"); + L.LogStackTrace(); + return 0; + } + if ((SourceTypeInt < 0) || (SourceTypeInt >= esMax)) + { + LOGWARNING("World:DoExplosionAt(): Invalid source type"); + L.LogStackTrace(); + return 0; + } + eExplosionSource SourceType; + void * SourceData; + switch (SourceTypeInt) + { + case esBed: + { + // esBed receives a Vector3i SourceData param: + Vector3i * pos = nullptr; + L.GetStackValue(8, pos); + SourceType = esBed; + SourceData = pos; + break; + } + + case esEnderCrystal: + case esGhastFireball: + case esMonster: + case esPrimedTNT: + case esWitherBirth: + case esWitherSkull: + { + // These all receive a cEntity descendant SourceData param: + cEntity * ent = nullptr; + L.GetStackValue(8, ent); + SourceType = static_cast(SourceTypeInt); + SourceData = ent; + break; + } + + case esOther: + case esPlugin: + { + // esOther and esPlugin ignore their SourceData params + SourceType = static_cast(SourceTypeInt); + SourceData = nullptr; + break; + } + + default: + { + LOGWARNING("cWorld:DoExplosionAt(): invalid SourceType parameter: %d", SourceTypeInt); + L.LogStackTrace(); + return 0; + } + } + + // Create the actual explosion: + World->DoExplosionAt(ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceType, SourceData); + + return 0; +} + + + + + static int tolua_cWorld_ForEachLoadedChunk(lua_State * tolua_S) { // Exported manually, because tolua doesn't support converting functions to functor types. @@ -576,41 +669,42 @@ 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); - tolua_function(tolua_S, "DoWithBeaconAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithBrewingstandAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithChestAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithDispenserAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithDropperAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithEntityByID", DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); - tolua_function(tolua_S, "DoWithFurnaceAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithMobHeadAt", DoWithXYZ); - tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithXYZ); - 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); + tolua_function(tolua_S, "BroadcastParticleEffect", tolua_cWorld_BroadcastParticleEffect); + tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay); + tolua_function(tolua_S, "DoExplosionAt", tolua_cWorld_DoExplosionAt); + tolua_function(tolua_S, "DoWithBeaconAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithBrewingstandAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithChestAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithDispenserAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithDropperAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithEntityByID", DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); + tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithFurnaceAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithMobHeadAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithXYZ); + tolua_function(tolua_S, "DoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>); + tolua_function(tolua_S, "DoWithPlayerByUUID", DoWith< cWorld, cPlayer, &cWorld::DoWithPlayerByUUID>); + tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>); + tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachInChunk); tolua_function(tolua_S, "ForEachBrewingstandInChunk", ForEachInChunk); - tolua_function(tolua_S, "ForEachChestInChunk", ForEachInChunk); - 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); - tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachInChunk); - tolua_function(tolua_S, "ForEachPlayer", ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>); - tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk); - 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_function(tolua_S, "ForEachChestInChunk", ForEachInChunk); + 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); + tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachInChunk); + tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk); + 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); } diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index 3038264d2..1b7a18ff1 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -667,16 +667,20 @@ bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_Can { switch (a_Source) { - case esOther: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; - case esPrimedTNT: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res); break; - case esMonster: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res); break; - case esBed: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res); break; - case esEnderCrystal: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res); break; - case esGhastFireball: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; - case esWitherSkullBlack: - case esWitherSkullBlue: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; - case esWitherBirth: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; - case esPlugin: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; + case esBed: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res); break; + case esEnderCrystal: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res); break; + case esGhastFireball: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res); break; + case esMonster: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res); break; + case esOther: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res); break; + case esPlugin: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res); break; + case esPrimedTNT: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res); break; + case esWitherBirth: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res); break; + case esWitherSkull: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res); break; + case esMax: + { + ASSERT(!"Invalid explosion source"); + return false; + } } if (res) { @@ -703,16 +707,20 @@ bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool & { switch (a_Source) { - case esOther: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esPrimedTNT: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esMonster: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esBed: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esEnderCrystal: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esGhastFireball: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esWitherSkullBlack: - case esWitherSkullBlue: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esWitherBirth: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - case esPlugin: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esBed: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esEnderCrystal: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esGhastFireball: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast(a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esMonster: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esOther: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esPlugin: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esPrimedTNT: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esWitherBirth: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esWitherSkull: m_LuaState.Call(static_cast(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, reinterpret_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esMax: + { + ASSERT(!"Invalid explosion source"); + return false; + } } if (res) { diff --git a/src/BlockID.h b/src/BlockID.h index 98c296249..1a43d4b64 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -1051,18 +1051,30 @@ enum eDamageType +/** The source of an explosion. +Also dictates the type of the additional data passed to the explosion handlers: +| esBed | Vector3i * | Bed exploding in the Nether or in the End +| esEnderCrystal | cEnderCrystal * | +| esGhastFireball | cGhastFireballEntity * | +| esMonster | cMonster * | +| esOther | nullptr | Any other explosion unaccounted for +| esPlugin | nullptr | Explosion primarily attributed to a plugin +| esPrimedTNT | cTNTEntity * | +| esWitherBirth | cMonster * | +| esWitherSkull | cProjectileEntity * | +*/ enum eExplosionSource { - esOther, - esPrimedTNT, - esMonster, esBed, esEnderCrystal, esGhastFireball, - esWitherSkullBlack, - esWitherSkullBlue, - esWitherBirth, + esMonster, + esOther, esPlugin, + esPrimedTNT, + esWitherBirth, + esWitherSkull, + esMax, } ; diff --git a/src/World.h b/src/World.h index 5f1ce393b..aca7f2b3f 100644 --- a/src/World.h +++ b/src/World.h @@ -517,20 +517,11 @@ public: /** Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true */ bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp - /** Does an explosion with the specified strength at the specified coordinate - a_SourceData exact type depends on the a_Source: - | esOther | void * | - | esPrimedTNT | cTNTEntity * | - | esMonster | cMonster * | - | esBed | cVector3i * | - | esEnderCrystal | Vector3i * | - | esGhastFireball | cGhastFireball * | - | esWitherSkullBlack | TBD | - | esWitherSkullBlue | TBD | - | esWitherBirth | cMonster * | - | esPlugin | void * | - */ - virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) override; // tolua_export + /** Does an explosion with the specified strength at the specified coordinates. + Executes the HOOK_EXPLODING and HOOK_EXPLODED hooks as part of the processing. + a_SourceData exact type depends on the a_Source, see the declaration of the esXXX constants in BlockID.h for details. + Exported to Lua manually in ManualBindings_World.cpp in order to support the variable a_SourceData param. */ + virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) override; /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */ virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) override; // Exported in ManualBindings.cpp -- cgit v1.2.3