summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/Core/README.md93
-rw-r--r--MCServer/Plugins/Core/console.lua9
-rw-r--r--MCServer/Plugins/Core/give.lua74
-rw-r--r--MCServer/Plugins/Core/item.lua24
-rw-r--r--MCServer/Plugins/Core/main.lua10
-rw-r--r--MCServer/Plugins/Core/time.lua4
-rw-r--r--MCServer/Plugins/HookNotify/HookNotify.lua36
-rw-r--r--source/AllToLua.pkg1
-rw-r--r--source/Bindings.cpp34
-rw-r--r--source/Bindings.h2
-rw-r--r--source/Entity.cpp10
-rw-r--r--source/Entity.h3
-rw-r--r--source/FallingBlock.cpp10
-rw-r--r--source/FallingBlock.h2
-rw-r--r--source/LuaState.cpp13
-rw-r--r--source/LuaState.h2
-rw-r--r--source/Minecart.cpp10
-rw-r--r--source/Minecart.h2
-rw-r--r--source/Pickup.cpp10
-rw-r--r--source/Pickup.h2
-rw-r--r--source/Player.cpp54
-rw-r--r--source/Player.h15
-rw-r--r--source/Plugin.cpp45
-rw-r--r--source/Plugin.h4
-rw-r--r--source/PluginManager.cpp82
-rw-r--r--source/PluginManager.h18
-rw-r--r--source/Plugin_NewLua.cpp115
-rw-r--r--source/Plugin_NewLua.h4
-rw-r--r--source/TNTEntity.cpp10
-rw-r--r--source/TNTEntity.h2
-rw-r--r--source/World.cpp14
31 files changed, 617 insertions, 97 deletions
diff --git a/MCServer/Plugins/Core/README.md b/MCServer/Plugins/Core/README.md
index d840459a0..418c23b87 100644
--- a/MCServer/Plugins/Core/README.md
+++ b/MCServer/Plugins/Core/README.md
@@ -1,23 +1,70 @@
-Core Plugin (Forked)
-===========
-
-A fork of MCServer's Core plugin.
-
-**New Features:**
-* Simplified commands, such as 'gotoworld' -> 'portal'
-* Simplified and combined LUA files, such as 'listworlds.lua & gotoworld.lua' -> 'worlds-portal.lua'
-* Fixed 'tp' command not working due to typography errors
-* Fixed 'arithmetic on nil value' on startup due to inactivation of world limiter
-* Massive overhaul / redesign of webadmin GUI interface.
- * Added jQuery transition effect
- * Completely redesigned CSS
- * Added new logo
- * Made HTML5 compliant
-* Beautified 'help' menu
-* Rewrite of death messages - fixed strange grammar and edited to more faithfully reflect Vanilla
-* Added 'unban' console command
-
-**How to Use**
-
-Simply copy all LUA files into Plugins/Core (delete existing files first, except banned.ini and whitelist.ini!)
-Then, copy webadmin to MCServer root directory (delete existing directory first!)
+MCServer Core Plugin
+====================
+
+The Core plugin for MCServer provides the default utility commands and also a lot of WebAdmin goodness.
+
+Commands
+--------
+
+ * /back
+ * /ban
+ * /downfall
+ * /give
+ * /gm
+ * /groups
+ * /help
+ * /i
+ * /item
+ * /kick
+ * /locate
+ * /me
+ * /motd
+ * /plugins
+ * /portal
+ * /rank
+ * /regen
+ * /reload
+ * /save-all
+ * /spawn
+ * /stop
+ * /time
+ * /top
+ * /tp
+ * /tpa
+ * /tpaccept
+ * /unban
+ * /viewdistance
+ * /worlds
+
+**Also, console commands:**
+
+ * ban
+ * banlist
+ * getversion
+ * help
+ * list
+ * listgroups
+ * numchunks
+ * players
+ * rank
+ * reload
+ * say
+ * setversion
+ * unban
+ * unload
+
+Contributors
+------------
+
+FakeTruth
+xoft
+tigerw
+bearbin
+tonibm19
+
+(If you want your name here, please submit a PR after you've done your contributions.)
+
+How to Use
+----------
+
+Core should be installed in MCServer by default.
diff --git a/MCServer/Plugins/Core/console.lua b/MCServer/Plugins/Core/console.lua
index 59a60ae62..8fd548612 100644
--- a/MCServer/Plugins/Core/console.lua
+++ b/MCServer/Plugins/Core/console.lua
@@ -5,21 +5,22 @@ function InitConsoleCommands()
-- Please keep the list alpha-sorted
PluginMgr:BindConsoleCommand("ban", HandleConsoleBan, " ~ Bans a player by name");
- PluginMgr:BindConsoleCommand("unban", HandleConsoleUnban, " ~ Unbans a player by name");
- PluginMgr:BindConsoleCommand("banlist", HandleConsoleBanList, " - Lists all players banned by name");
PluginMgr:BindConsoleCommand("banlist ips", HandleConsoleBanList, " - Lists all players banned by IP");
+ PluginMgr:BindConsoleCommand("banlist", HandleConsoleBanList, " - Lists all players banned by name");
+ PluginMgr:BindConsoleCommand("getversion", HandleConsoleVersion, " - Gets server version reported to 1.4+ clients");
PluginMgr:BindConsoleCommand("help", HandleConsoleHelp, " - Lists all commands");
PluginMgr:BindConsoleCommand("list", HandleConsoleList, " - Lists all players in a machine-readable format");
PluginMgr:BindConsoleCommand("listgroups", HandleConsoleListGroups, " - Shows a list of all the groups");
PluginMgr:BindConsoleCommand("numchunks", HandleConsoleNumChunks, " - Shows number of chunks currently loaded");
PluginMgr:BindConsoleCommand("players", HandleConsolePlayers, " - Lists all connected players");
- PluginMgr:BindConsoleCommand("getversion", HandleConsoleVersion, " - Gets server version reported to 1.4+ clients");
- PluginMgr:BindConsoleCommand("setversion", HandleConsoleVersion, " ~ Sets server version reported to 1.4+ clients");
PluginMgr:BindConsoleCommand("rank", HandleConsoleRank, " ~ Add a player to a group");
PluginMgr:BindConsoleCommand("reload", HandleConsoleReload, " - Reloads all plugins");
PluginMgr:BindConsoleCommand("save-all", HandleConsoleSaveAll, " - Saves all chunks");
PluginMgr:BindConsoleCommand("say", HandleConsoleSay, " - Sends a chat message to all players");
+ PluginMgr:BindConsoleCommand("setversion", HandleConsoleVersion, " ~ Sets server version reported to 1.4+ clients");
+ PluginMgr:BindConsoleCommand("unban", HandleConsoleUnban, " ~ Unbans a player by name");
PluginMgr:BindConsoleCommand("unload", HandleConsoleUnload, " - Unloads all unused chunks");
+
end
function HandleConsoleBan(Split)
diff --git a/MCServer/Plugins/Core/give.lua b/MCServer/Plugins/Core/give.lua
index d1c7ae59f..ba3a1eb41 100644
--- a/MCServer/Plugins/Core/give.lua
+++ b/MCServer/Plugins/Core/give.lua
@@ -1,39 +1,65 @@
function HandleGiveCommand(Split, Player)
- if ((#Split ~= 2) and (#Split ~=3)) then
- Player:SendMessage(cChatColor.Yellow .. "[INFO] " .. cChatColor.White .. "Usage: /give [ItemType/Name:Dmg] <Amount>" );
- return true;
+
+ -- Make sure there are a correct number of arguments.
+ if #Split ~= 3 and #Split ~= 4 and #Split ~= 5 then
+ Player:SendMessage( cChatColor.Yellow .. "[INFO] " .. cChatColor.White .. "Usage: /give <player> <item> [amount] [meta]" )
+ return true
end
- local Item = cItem();
- local FoundItem = StringToItem(Split[2], Item);
-
- if not(IsValidItem(Item.m_ItemType)) then -- StringToItem does not check if item is valid
+ -- Get the item from the arguments and check it's valid.
+ local Item = cItem()
+ if #Split == 5 then
+ local FoundItem = StringToItem(Split[3] .. ":" .. Split[5], Item)
+ else
+ local FoundItem = StringToItem(Split[3], Item)
+ end
+ if not IsValidItem(Item.m_ItemType) then -- StringToItem does not check if item is valid
FoundItem = false
end
- if not(FoundItem) then
+ if not FoundItem then
Player:SendMessage(cChatColor.Rose .. "[INFO] " .. cChatColor.White .. "Invalid item id or name!" )
return true
end
- local ItemAmount = 1;
- if (#Split == 3) then
- ItemAmount = tonumber(Split[3]);
- if ((ItemAmount == nil) or (ItemAmount < 1) or (ItemAmount > 512)) then
- Player:SendMessage(cChatColor.Rose .. "[INFO] " .. cChatColor.White .. "Invalid amount!" );
- return true;
+ -- Work out how many items the user wants.
+ local ItemAmount = 1
+ if #Split > 3 then
+ ItemAmount = tonumber(Split[4])
+ if ItemAmount == nil or ItemAmount < 1 or ItemAmount > 512 then
+ Player:SendMessage(cChatColor.Rose .. "[INFO] " .. cChatColor.White .. "Invalid amount!" )
+ return true
end
end
- Item.m_ItemCount = ItemAmount;
+ Item.m_ItemCount = ItemAmount
- local ItemsGiven = Player:GetInventory():AddItem(Item);
- if (ItemsGiven == ItemAmount) then
- Player:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. "There you go!" );
- LOG("Gave " .. Player:GetName() .. " " .. Item.m_ItemCount .. " times " .. Item.m_ItemType .. ":" .. Item.m_ItemDamage);
- else
- Player:SendMessage(cChatColor.Rose .. "[INFO] " .. cChatColor.White .. "Not enough space in inventory, only gave " .. ItemsGiven);
- LOG("Player " .. Player:GetName() .. " asked for " .. Item.m_ItemCount .. " times " .. Item.m_ItemType .. ":" .. Item.m_ItemDamage ..", but only could fit " .. ItemsGiven);
+ -- Get the playername from the split.
+ local playerName = Split[2]
+
+ local function giveItems(newPlayer)
+ local ItemsGiven = newPlayer:GetInventory():AddItem(Item)
+ if ItemsGiven == ItemAmount then
+ newPlayer:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. "You were given " .. Item.m_ItemCount .. " of " .. Item.m_ItemType .. "." )
+ if not newPlayer == Player then
+ Player:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. "Items given!" )
+ end
+ LOG("Gave " .. newPlayer:GetName() .. " " .. Item.m_ItemCount .. " times " .. Item.m_ItemType .. ":" .. Item.m_ItemDamage)
+ else
+ Player:SendMessage( cChatColor.Rose .. "[INFO] " .. cChatColor.White .. "Not enough space in inventory, only gave " .. ItemsGiven)
+ LOG( "Player " .. Player:GetName() .. " asked for " .. Item.m_ItemCount .. " times " .. Item.m_ItemType .. ":" .. Item.m_ItemDamage ..", but only could fit " .. ItemsGiven )
+ end
+ return true
+ end
+
+ -- Finally give the items to the player.
+ itemStatus = cRoot:Get():FindAndDoWithPlayer(playerName, giveItems)
+
+ -- Check to make sure that giving items was successful.
+ if not itemStatus then
+ Player:SendMessage( cChatColor.Rose .. "[INFO] " .. cChatColor.White .. "There was no player that matched your query.")
end
- return true;
-end \ No newline at end of file
+
+ return true
+
+end
diff --git a/MCServer/Plugins/Core/item.lua b/MCServer/Plugins/Core/item.lua
new file mode 100644
index 000000000..b665e5208
--- /dev/null
+++ b/MCServer/Plugins/Core/item.lua
@@ -0,0 +1,24 @@
+function HandleItemCommand(Split, Player)
+
+ if ((#Split ~= 2) and (#Split ~=3)) then
+ Player:SendMessage(cChatColor.Yellow .. "[INFO] " .. cChatColor.White .. "Usage: /i <item>[:meta] [amount]" )
+ return true
+ end
+
+ itemSplit = StringSplit(Split[2], ":")
+
+ newSplit[1] = "/give"
+ newSplit[2] = Player:GetName()
+ newSplit[3] = itemSplit[1]
+ if Split[3] ~= nil then
+ newSplit[4] = Split[3]
+ else
+ newSplit[4] = 1
+ end
+ if itemSplit[2] ~= nil then
+ newSplit[5] = itemSplit[2]
+ end
+
+ HandleGiveCommand(newSplit, Player)
+ return true
+end \ No newline at end of file
diff --git a/MCServer/Plugins/Core/main.lua b/MCServer/Plugins/Core/main.lua
index 3fd9c6585..9c476a48c 100644
--- a/MCServer/Plugins/Core/main.lua
+++ b/MCServer/Plugins/Core/main.lua
@@ -29,12 +29,16 @@ function Initialize(Plugin)
--BIND COMMANDS
PluginManager:BindCommand("/back", "core.back", HandleBackCommand, " - Return to your last position");
PluginManager:BindCommand("/ban", "core.ban", HandleBanCommand, " ~ Ban a player");
- PluginManager:BindCommand("/give", "core.give", HandleGiveCommand, " ~ Give yourself an item");
+ PluginManager:BindCommand("/downfall", "core.downfall", HandleDownfallCommand, " - Toggles the weather");
+ PluginManager:BindCommand("/give", "core.give", HandleGiveCommand, " ~ Give someone an item");
PluginManager:BindCommand("/gm", "core.changegm", HandleChangeGMCommand, " ~ Change your gamemode");
+ PluginManager:BindCommand("/groups", "core.groups", HandleGroupsCommand, " - Shows a list of all the groups");
PluginManager:BindCommand("/help", "core.help", HandleHelpCommand, " ~ Show available commands");
+ PluginManager:BindCommand("/i", "core.give", HandleItemCommand, "")
+ PluginManager:BindCommand("/item", "core.give", HandleItemCommand, " - Give yourself an item.")
PluginManager:BindCommand("/kick", "core.kick", HandleKickCommand, " ~ Kick a player");
- PluginManager:BindCommand("/groups", "core.groups", HandleGroupsCommand, " - Shows a list of all the groups");
PluginManager:BindCommand("/locate", "core.locate", HandleLocateCommand, " - Show your current server coordinates");
+ PluginManager:BindCommand("/me", "core.me", HandleMeCommand, " ~ Tell what you are doing");
PluginManager:BindCommand("/motd", "core.motd", HandleMOTDCommand, " - Show message of the day");
PluginManager:BindCommand("/plugins", "core.plugins", HandlePluginsCommand, " - Show list of plugins");
PluginManager:BindCommand("/portal", "core.portal", HandlePortalCommand, " ~ Move to a different world");
@@ -45,8 +49,6 @@ function Initialize(Plugin)
PluginManager:BindCommand("/spawn", "core.spawn", HandleSpawnCommand, " - Return to the spawn");
PluginManager:BindCommand("/stop", "core.stop", HandleStopCommand, " - Stops the server");
PluginManager:BindCommand("/time", "core.time", HandleTimeCommand, " ~ Sets the time of day");
- PluginManager:BindCommand("/downfall", "core.downfall", HandleDownfallCommand, " - Toggles the weather");
- PluginManager:BindCommand("/me", "core.me", HandleMeCommand, " ~ Tell what you are doing");
PluginManager:BindCommand("/top", "core.top", HandleTopCommand, " - Teleport yourself to the top most block");
PluginManager:BindCommand("/tp", "core.teleport", HandleTPCommand, " ~ Teleport yourself to a player");
PluginManager:BindCommand("/tpa", "core.teleport", HandleTPACommand, " ~ Ask to teleport yourself to a player");
diff --git a/MCServer/Plugins/Core/time.lua b/MCServer/Plugins/Core/time.lua
index b5d3c991a..fd2816f23 100644
--- a/MCServer/Plugins/Core/time.lua
+++ b/MCServer/Plugins/Core/time.lua
@@ -9,7 +9,7 @@ function HandleTimeCommand( Split, Player )
Server:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. "Time was set to daytime" )
elseif( string.upper( Split[2] ) == "NIGHT") then
Player:GetWorld():SetTimeOfDay( 12000 + 1000 )
- Server:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. "Time was set to nighttime" )
+ Server:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. "Time was set to night time" )
elseif( string.upper(Split[2]) == "SET" ) and ( tonumber(Split[3]) ~= nil) then
Player:GetWorld():SetTimeOfDay( tonumber(Split[3]) )
Server:SendMessage(cChatColor.Green .. "[INFO] " .. cChatColor.White .. "Time was set to " .. Split[3] )
@@ -20,4 +20,4 @@ function HandleTimeCommand( Split, Player )
Player:SendMessage(cChatColor.Yellow .. "[INFO] " .. cChatColor.White .. "Usage: /time [Day/Night/Set/Add]" )
end
return true
-end \ No newline at end of file
+end
diff --git a/MCServer/Plugins/HookNotify/HookNotify.lua b/MCServer/Plugins/HookNotify/HookNotify.lua
index 09759451d..6badc63e7 100644
--- a/MCServer/Plugins/HookNotify/HookNotify.lua
+++ b/MCServer/Plugins/HookNotify/HookNotify.lua
@@ -45,6 +45,10 @@ function Initialize(Plugin)
PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_USING_ITEM);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_POST_CRAFTING);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_PRE_CRAFTING);
+ PluginManager:AddHook(Plugin, cPluginManager.HOOK_SPAWNED_ENTITY);
+ PluginManager:AddHook(Plugin, cPluginManager.HOOK_SPAWNED_MONSTER);
+ PluginManager:AddHook(Plugin, cPluginManager.HOOK_SPAWNING_ENTITY);
+ PluginManager:AddHook(Plugin, cPluginManager.HOOK_SPAWNING_MONSTER);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_TAKE_DAMAGE);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_UPDATED_SIGN);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_UPDATING_SIGN);
@@ -358,6 +362,38 @@ end
+function OnSpawnedEntity(...)
+ LogHook("OnSpawnedEntity", unpack(arg));
+end
+
+
+
+
+
+function OnSpawnedMonster(...)
+ LogHook("OnSpawnedMonster", unpack(arg));
+end
+
+
+
+
+
+function OnSpawningEntity(...)
+ LogHook("OnSpawningEntity", unpack(arg));
+end
+
+
+
+
+
+function OnSpawningMonster(...)
+ LogHook("OnSpawningMonster", unpack(arg));
+end
+
+
+
+
+
function OnUpdatedSign(...)
LogHook("OnUpdatedSign", unpack(arg));
end
diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg
index cd22aba0a..360901ecb 100644
--- a/source/AllToLua.pkg
+++ b/source/AllToLua.pkg
@@ -59,6 +59,7 @@ $cfile "Generating/ChunkDesc.h"
$cfile "CraftingRecipes.h"
$cfile "UI/Window.h"
$cfile "LuaWindow.h"
+$cfile "Mobs/Monster.h"
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index fd953e29d..653c01f7f 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/07/13 12:06:03.
+** Generated automatically by tolua++-1.0.92 on 08/08/13 09:04:23.
*/
#ifndef __cplusplus
@@ -59,6 +59,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
#include "CraftingRecipes.h"
#include "UI/Window.h"
#include "LuaWindow.h"
+#include "Mobs/Monster.h"
/* function to release collected object via destructor */
#ifdef __cplusplus
@@ -203,6 +204,7 @@ static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"TakeDamageInfo");
tolua_usertype(tolua_S,"cPlugin_NewLua");
+ tolua_usertype(tolua_S,"cMonster");
tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cCraftingRecipe");
tolua_usertype(tolua_S,"cPlugin");
@@ -8256,10 +8258,11 @@ static int tolua_AllToLua_cPlayer_Initialize00(lua_State* tolua_S)
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Initialize'", NULL);
#endif
{
- self->Initialize(a_World);
+ bool tolua_ret = (bool) self->Initialize(a_World);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
}
}
- return 0;
+ return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'Initialize'.",&tolua_err);
@@ -10087,12 +10090,15 @@ static int tolua_AllToLua_cPlayer_SetSprint00(lua_State* tolua_S)
class Lua__cPlayer : public cPlayer, public ToluaBase {
public:
- void Initialize( cWorld* a_World) {
+ bool Initialize( cWorld* a_World) {
if (push_method("Initialize", tolua_AllToLua_cPlayer_Initialize00)) {
tolua_pushusertype(lua_state, (void*)a_World, "cWorld");
- ToluaBase::dbcall(lua_state, 2, 0);
+ ToluaBase::dbcall(lua_state, 2, 1);
+ bool tolua_ret = ( bool )tolua_toboolean(lua_state, -1, 0);
+ lua_pop(lua_state, 1);
+ return tolua_ret;
} else {
- return ( void ) cPlayer:: Initialize(a_World);
+ return ( bool ) cPlayer:: Initialize(a_World);
};
};
void MoveTo( const Vector3d& a_NewPos) {
@@ -10296,8 +10302,8 @@ public:
};
};
- void cPlayer__Initialize( cWorld* a_World) {
- return ( void )cPlayer::Initialize(a_World);
+ bool cPlayer__Initialize( cWorld* a_World) {
+ return ( bool )cPlayer::Initialize(a_World);
};
void cPlayer__MoveTo( const Vector3d& a_NewPos) {
return ( void )cPlayer::MoveTo(a_NewPos);
@@ -10415,10 +10421,11 @@ static int tolua_AllToLua_Lua__cPlayer_cPlayer__Initialize00(lua_State* tolua_S)
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'cPlayer__Initialize'", NULL);
#endif
{
- self->cPlayer__Initialize(a_World);
+ bool tolua_ret = (bool) self->cPlayer__Initialize(a_World);
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
}
}
- return 0;
+ return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'cPlayer__Initialize'.",&tolua_err);
@@ -29527,6 +29534,10 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"HOOK_PLAYER_USING_ITEM",cPluginManager::HOOK_PLAYER_USING_ITEM);
tolua_constant(tolua_S,"HOOK_POST_CRAFTING",cPluginManager::HOOK_POST_CRAFTING);
tolua_constant(tolua_S,"HOOK_PRE_CRAFTING",cPluginManager::HOOK_PRE_CRAFTING);
+ tolua_constant(tolua_S,"HOOK_SPAWNED_ENTITY",cPluginManager::HOOK_SPAWNED_ENTITY);
+ tolua_constant(tolua_S,"HOOK_SPAWNED_MONSTER",cPluginManager::HOOK_SPAWNED_MONSTER);
+ tolua_constant(tolua_S,"HOOK_SPAWNING_ENTITY",cPluginManager::HOOK_SPAWNING_ENTITY);
+ tolua_constant(tolua_S,"HOOK_SPAWNING_MONSTER",cPluginManager::HOOK_SPAWNING_MONSTER);
tolua_constant(tolua_S,"HOOK_TAKE_DAMAGE",cPluginManager::HOOK_TAKE_DAMAGE);
tolua_constant(tolua_S,"HOOK_TICK",cPluginManager::HOOK_TICK);
tolua_constant(tolua_S,"HOOK_UPDATED_SIGN",cPluginManager::HOOK_UPDATED_SIGN);
@@ -30341,6 +30352,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetContents",tolua_AllToLua_cLuaWindow_GetContents00);
tolua_variable(tolua_S,"__cItemGrid__cListener__",tolua_get_cLuaWindow___cItemGrid__cListener__,NULL);
tolua_endmodule(tolua_S);
+ tolua_cclass(tolua_S,"cMonster","cMonster","cPawn",NULL);
+ tolua_beginmodule(tolua_S,"cMonster");
+ tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cLineBlockTracer","cLineBlockTracer","",NULL);
tolua_beginmodule(tolua_S,"cLineBlockTracer");
tolua_endmodule(tolua_S);
diff --git a/source/Bindings.h b/source/Bindings.h
index a5654c062..b53029f08 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/07/13 12:06:04.
+** Generated automatically by tolua++-1.0.92 on 08/08/13 09:04:23.
*/
/* Exported function */
diff --git a/source/Entity.cpp b/source/Entity.cpp
index 2c822d0cc..8afdfdb95 100644
--- a/source/Entity.cpp
+++ b/source/Entity.cpp
@@ -129,14 +129,22 @@ const char * cEntity::GetParentClass(void) const
-void cEntity::Initialize(cWorld * a_World)
+bool cEntity::Initialize(cWorld * a_World)
{
+ if (cPluginManager::Get()->CallHookSpawningEntity(*a_World, *this))
+ {
+ return false;
+ }
+
LOGD("Initializing entity #%d (%s) at {%.02f, %.02f, %.02f}",
m_UniqueID, GetClass(), m_Pos.x, m_Pos.y, m_Pos.z
);
m_IsInitialized = true;
m_World = a_World;
m_World->AddEntity(this);
+
+ cPluginManager::Get()->CallHookSpawnedEntity(*a_World, *this);
+ return true;
}
diff --git a/source/Entity.h b/source/Entity.h
index bd66df5f5..c9d26e1a1 100644
--- a/source/Entity.h
+++ b/source/Entity.h
@@ -107,7 +107,8 @@ public:
cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
virtual ~cEntity();
- virtual void Initialize(cWorld * a_World);
+ /// Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed)
+ virtual bool Initialize(cWorld * a_World);
// tolua_begin
diff --git a/source/FallingBlock.cpp b/source/FallingBlock.cpp
index 5dc99c771..05766ae01 100644
--- a/source/FallingBlock.cpp
+++ b/source/FallingBlock.cpp
@@ -22,10 +22,14 @@ cFallingBlock::cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_Block
-void cFallingBlock::Initialize(cWorld * a_World)
+bool cFallingBlock::Initialize(cWorld * a_World)
{
- super::Initialize(a_World);
- a_World->BroadcastSpawnEntity(*this);
+ if (super::Initialize(a_World))
+ {
+ a_World->BroadcastSpawnEntity(*this);
+ return true;
+ }
+ return false;
}
diff --git a/source/FallingBlock.h b/source/FallingBlock.h
index 887ae6268..492931fa3 100644
--- a/source/FallingBlock.h
+++ b/source/FallingBlock.h
@@ -30,7 +30,7 @@ public:
NIBBLETYPE GetBlockMeta(void) const { return m_BlockMeta; }
// cEntity overrides:
- virtual void Initialize(cWorld * a_World) override;
+ 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/LuaState.cpp b/source/LuaState.cpp
index 664ba8147..d4beb249b 100644
--- a/source/LuaState.cpp
+++ b/source/LuaState.cpp
@@ -396,6 +396,19 @@ void cLuaState::PushObject(cEntity * a_Entity)
+void cLuaState::PushObject(cMonster * a_Monster)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Monster, "cMonster");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
void cLuaState::PushObject(cItem * a_Item)
{
ASSERT(IsValid());
diff --git a/source/LuaState.h b/source/LuaState.h
index 6820f1777..15dbdbc0e 100644
--- a/source/LuaState.h
+++ b/source/LuaState.h
@@ -36,6 +36,7 @@ extern "C"
class cWorld;
class cPlayer;
class cEntity;
+class cMonster;
class cItem;
class cItems;
class cClientHandle;
@@ -145,6 +146,7 @@ public:
void PushObject(cWorld * a_World);
void PushObject(cPlayer * a_Player);
void PushObject(cEntity * a_Entity);
+ void PushObject(cMonster * a_Monster);
void PushObject(cItem * a_Item);
void PushObject(cItems * a_Items);
void PushObject(cClientHandle * a_ClientHandle);
diff --git a/source/Minecart.cpp b/source/Minecart.cpp
index bae56d582..cffa1b6e0 100644
--- a/source/Minecart.cpp
+++ b/source/Minecart.cpp
@@ -22,10 +22,14 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
-void cMinecart::Initialize(cWorld * a_World)
+bool cMinecart::Initialize(cWorld * a_World)
{
- super::Initialize(a_World);
- a_World->BroadcastSpawnEntity(*this);
+ if (super::Initialize(a_World))
+ {
+ a_World->BroadcastSpawnEntity(*this);
+ return true;
+ }
+ return false;
}
diff --git a/source/Minecart.h b/source/Minecart.h
index b7b4c2b04..e205a4963 100644
--- a/source/Minecart.h
+++ b/source/Minecart.h
@@ -33,7 +33,7 @@ public:
} ;
// cEntity overrides:
- virtual void Initialize(cWorld * a_World) override;
+ 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/Pickup.cpp b/source/Pickup.cpp
index 36322bcfb..217af969c 100644
--- a/source/Pickup.cpp
+++ b/source/Pickup.cpp
@@ -41,10 +41,14 @@ cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem
-void cPickup::Initialize(cWorld * a_World)
+bool cPickup::Initialize(cWorld * a_World)
{
- super::Initialize(a_World);
- a_World->BroadcastSpawnEntity(*this);
+ if (super::Initialize(a_World))
+ {
+ a_World->BroadcastSpawnEntity(*this);
+ return true;
+ }
+ return false;
}
diff --git a/source/Pickup.h b/source/Pickup.h
index f37618d2d..dcdc02137 100644
--- a/source/Pickup.h
+++ b/source/Pickup.h
@@ -26,7 +26,7 @@ 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 void Initialize(cWorld * a_World) override;
+ 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/Player.cpp b/source/Player.cpp
index bbf39f789..fb752ed87 100644
--- a/source/Player.cpp
+++ b/source/Player.cpp
@@ -40,6 +40,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_IP("")
, m_LastBlockActionTime( 0 )
, m_LastBlockActionCnt( 0 )
+ , m_AirLevel( MAX_AIR_LEVEL )
+ , m_AirTickTimer( DROWNING_TICKS )
, m_bVisible( true )
, m_LastGroundHeight( 0 )
, m_bTouchGround( false )
@@ -121,10 +123,14 @@ cPlayer::~cPlayer(void)
-void cPlayer::Initialize(cWorld * a_World)
+bool cPlayer::Initialize(cWorld * a_World)
{
- super::Initialize(a_World);
- GetWorld()->AddPlayer(this);
+ if (super::Initialize(a_World))
+ {
+ GetWorld()->AddPlayer(this);
+ return true;
+ }
+ return false;
}
@@ -174,6 +180,10 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
}
super::Tick(a_Dt, a_Chunk);
+
+ //handle air drowning stuff
+ HandleAir(a_Chunk);
+
if (m_bDirtyPosition)
{
// Apply food exhaustion from movement:
@@ -1196,7 +1206,7 @@ bool cPlayer::LoadFromDisk()
}
m_Health = root.get("health", 0).asInt();
-
+ m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
m_FoodTickTimer = root.get("foodTickTimer", 0).asInt();
@@ -1242,6 +1252,7 @@ bool cPlayer::SaveToDisk()
root["rotation"] = JSON_PlayerRotation;
root["inventory"] = JSON_Inventory;
root["health"] = m_Health;
+ root["air"] = m_AirLevel;
root["food"] = m_FoodLevel;
root["foodSaturation"] = m_FoodSaturationLevel;
root["foodTickTimer"] = m_FoodTickTimer;
@@ -1309,7 +1320,42 @@ void cPlayer::UseEquippedItem()
}
+void cPlayer::HandleAir(cChunk & a_Chunk)
+{
+ // Ref.: http://www.minecraftwiki.net/wiki/Chunk_format
+ // see if the player is /submerged/ water (block above is water)
+ // Get the type of block the player's standing in:
+ BLOCKTYPE BlockIn;
+ int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width;
+ int RelY = (int)floor(m_LastPosY + 1.1);
+ int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width;
+ // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk
+ VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn));
+ if (IsBlockWater(BlockIn))
+ {
+ // either reduce air level or damage player
+ if(m_AirLevel < 1)
+ {
+ if(m_AirTickTimer < 1)
+ {
+ // damage player
+ TakeDamage(dtDrowning, NULL, 1, 1, 0);
+ // reset timer
+ m_AirTickTimer = DROWNING_TICKS;
+ }else{
+ m_AirTickTimer -= 1;
+ }
+ }else{
+ // reduce air supply
+ m_AirLevel -= 1;
+ }
+ }else{
+ // set the air back to maximum
+ m_AirLevel = MAX_AIR_LEVEL;
+ m_AirTickTimer = DROWNING_TICKS;
+ }
+}
void cPlayer::HandleFood(void)
diff --git a/source/Player.h b/source/Player.h
index eea8c1596..542656b5a 100644
--- a/source/Player.h
+++ b/source/Player.h
@@ -29,6 +29,8 @@ public:
MAX_HEALTH = 20,
MAX_FOOD_LEVEL = 20,
EATING_TICKS = 30, ///< Number of ticks it takes to eat an item
+ MAX_AIR_LEVEL = 300,
+ DROWNING_TICKS = 10, //number of ticks per heart of damage
} ;
// tolua_end
@@ -38,7 +40,7 @@ public:
cPlayer(cClientHandle * a_Client, const AString & a_PlayerName);
virtual ~cPlayer();
- virtual void Initialize(cWorld * a_World); // tolua_export
+ virtual bool Initialize(cWorld * a_World); // tolua_export
virtual void SpawnOn(cClientHandle & a_Client) override;
@@ -160,6 +162,8 @@ public:
int GetFoodTickTimer (void) const { return m_FoodTickTimer; }
double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; }
int GetFoodPoisonedTicksRemaining(void) const { return m_FoodPoisonedTicksRemaining; }
+
+ int GetAirLevel (void) const { return m_AirLevel; }
/// Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore
bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); }
@@ -267,6 +271,11 @@ protected:
std::string m_PlayerName;
std::string m_LoadedWorldName;
+ /// Player's air level (for swimming)
+ int m_AirLevel;
+ /// used to time ticks between damage taken via drowning/suffocation
+ int m_AirTickTimer;
+
bool m_bVisible;
// Food-related variables:
@@ -329,7 +338,6 @@ protected:
/// The world tick in which eating will be finished. -1 if not eating
Int64 m_EatingFinishTick;
-
virtual void Destroyed(void);
/// Filters out damage for creative mode
@@ -338,6 +346,9 @@ protected:
/// Called in each tick to handle food-related processing
void HandleFood(void);
+ /// Called in each tick to handle air-related processing i.e. drowning
+ void HandleAir(cChunk & a_Chunk);
+
/// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block)
void ApplyFoodExhaustionFromMovement(cChunk & a_Chunk);
} ; // tolua_export
diff --git a/source/Plugin.cpp b/source/Plugin.cpp
index 20943b916..76110321a 100644
--- a/source/Plugin.cpp
+++ b/source/Plugin.cpp
@@ -5,6 +5,7 @@
#include "Player.h"
#include "World.h"
#include "CommandOutput.h"
+#include "Mobs/Monster.h"
@@ -478,6 +479,50 @@ bool cPlugin::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Gr
+bool cPlugin::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
+{
+ UNUSED(a_World);
+ UNUSED(a_Entity);
+ return false;
+}
+
+
+
+
+
+bool cPlugin::OnSpawnedMonster(cWorld & a_World, cMonster & a_Monster)
+{
+ UNUSED(a_World);
+ UNUSED(a_Monster);
+ return false;
+}
+
+
+
+
+
+bool cPlugin::OnSpawningEntity(cWorld & a_World, cEntity & a_Entity)
+{
+ UNUSED(a_World);
+ UNUSED(a_Entity);
+ return false;
+}
+
+
+
+
+
+bool cPlugin::OnSpawningMonster(cWorld & a_World, cMonster & a_Monster)
+{
+ UNUSED(a_World);
+ UNUSED(a_Monster);
+ return false;
+}
+
+
+
+
+
bool cPlugin::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TakeDamageInfo)
{
UNUSED(a_Receiver);
diff --git a/source/Plugin.h b/source/Plugin.h
index 0f68273ee..f3d7a1c56 100644
--- a/source/Plugin.h
+++ b/source/Plugin.h
@@ -80,6 +80,10 @@ public:
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
+ virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity);
+ virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster);
+ virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity);
+ virtual bool OnSpawningMonster (cWorld & a_World, cMonster & a_Monster);
virtual bool OnTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TakeDamageInfo);
virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
diff --git a/source/PluginManager.cpp b/source/PluginManager.cpp
index 16b4056f4..5a81cccbc 100644
--- a/source/PluginManager.cpp
+++ b/source/PluginManager.cpp
@@ -888,6 +888,88 @@ bool cPluginManager::CallHookPreCrafting(const cPlayer * a_Player, const cCrafti
+bool cPluginManager::CallHookSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_SPAWNED_ENTITY);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnSpawnedEntity(a_World, a_Entity))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+bool cPluginManager::CallHookSpawnedMonster(cWorld & a_World, cMonster & a_Monster)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_SPAWNED_MONSTER);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnSpawnedMonster(a_World, a_Monster))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+bool cPluginManager::CallHookSpawningEntity(cWorld & a_World, cEntity & a_Entity)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_SPAWNING_ENTITY);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnSpawningEntity(a_World, a_Entity))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+bool cPluginManager::CallHookSpawningMonster(cWorld & a_World, cMonster & a_Monster)
+{
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_SPAWNING_MONSTER);
+ if (Plugins == m_Hooks.end())
+ {
+ return false;
+ }
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnSpawningMonster(a_World, a_Monster))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginManager::CallHookTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_TAKE_DAMAGE);
diff --git a/source/PluginManager.h b/source/PluginManager.h
index 26bd34dc5..6c3fa81fe 100644
--- a/source/PluginManager.h
+++ b/source/PluginManager.h
@@ -15,9 +15,12 @@ class cWorld;
// fwd: ChunkDesc.h
class cChunkDesc;
-// fwd: Entityes/Entity.h
+// fwd: Entities/Entity.h
class cEntity;
+// fwd: Mobs/Monster.h
+class cMonster;
+
// fwd: Player.h
class cPlayer;
@@ -82,6 +85,10 @@ public: // tolua_export
HOOK_PLAYER_USING_ITEM,
HOOK_POST_CRAFTING,
HOOK_PRE_CRAFTING,
+ HOOK_SPAWNED_ENTITY,
+ HOOK_SPAWNED_MONSTER,
+ HOOK_SPAWNING_ENTITY,
+ HOOK_SPAWNING_MONSTER,
HOOK_TAKE_DAMAGE,
HOOK_TICK,
HOOK_UPDATED_SIGN,
@@ -116,8 +123,9 @@ public: // tolua_export
void ReloadPlugins(); // tolua_export
void AddHook( cPlugin* a_Plugin, PluginHook a_Hook ); // tolua_export
- unsigned int GetNumPlugins() const; // tolua_export
-
+ unsigned int GetNumPlugins() const; // tolua_export
+
+ // Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort
bool CallHookBlockToPickups (cWorld * a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups);
bool CallHookChat (cPlayer * a_Player, AString & a_Message);
bool CallHookChunkAvailable (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
@@ -151,6 +159,10 @@ public: // tolua_export
bool CallHookPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
+ bool CallHookSpawnedEntity (cWorld & a_World, cEntity & a_Entity);
+ bool CallHookSpawnedMonster (cWorld & a_World, cMonster & a_Monster);
+ bool CallHookSpawningEntity (cWorld & a_World, cEntity & a_Entity);
+ bool CallHookSpawningMonster (cWorld & a_World, cMonster & a_Monster);
bool CallHookTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TDI);
bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
diff --git a/source/Plugin_NewLua.cpp b/source/Plugin_NewLua.cpp
index 704bb3a95..a85d5aae9 100644
--- a/source/Plugin_NewLua.cpp
+++ b/source/Plugin_NewLua.cpp
@@ -1102,6 +1102,117 @@ bool cPlugin_NewLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid
+bool cPlugin_NewLua::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
+{
+ cCSLock Lock(m_CriticalSection);
+ const char * FnName = GetHookFnName(cPluginManager::HOOK_SPAWNED_ENTITY);
+ ASSERT(FnName != NULL);
+ if (!m_LuaState.PushFunction(FnName))
+ {
+ return false;
+ }
+
+ m_LuaState.PushObject(&a_World);
+ m_LuaState.PushObject(&a_Entity);
+
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+
+ bool bRetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
+ lua_pop(m_LuaState, 1);
+ return bRetVal;
+}
+
+
+
+
+
+bool cPlugin_NewLua::OnSpawnedMonster(cWorld & a_World, cMonster & a_Monster)
+{
+ cCSLock Lock(m_CriticalSection);
+ const char * FnName = GetHookFnName(cPluginManager::HOOK_SPAWNED_MONSTER);
+ ASSERT(FnName != NULL);
+ if (!m_LuaState.PushFunction(FnName))
+ {
+ return false;
+ }
+
+ m_LuaState.PushObject(&a_World);
+ m_LuaState.PushObject(&a_Monster);
+
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+
+ bool bRetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
+ lua_pop(m_LuaState, 1);
+ return bRetVal;
+ return false;
+}
+
+
+
+
+
+bool cPlugin_NewLua::OnSpawningEntity(cWorld & a_World, cEntity & a_Entity)
+{
+ cCSLock Lock(m_CriticalSection);
+ const char * FnName = GetHookFnName(cPluginManager::HOOK_SPAWNING_ENTITY);
+ ASSERT(FnName != NULL);
+ if (!m_LuaState.PushFunction(FnName))
+ {
+ return false;
+ }
+
+ m_LuaState.PushObject(&a_World);
+ m_LuaState.PushObject(&a_Entity);
+
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+
+ bool bRetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
+ lua_pop(m_LuaState, 1);
+ return bRetVal;
+ return false;
+}
+
+
+
+
+
+bool cPlugin_NewLua::OnSpawningMonster(cWorld & a_World, cMonster & a_Monster)
+{
+ cCSLock Lock(m_CriticalSection);
+ const char * FnName = GetHookFnName(cPluginManager::HOOK_SPAWNING_MONSTER);
+ ASSERT(FnName != NULL);
+ if (!m_LuaState.PushFunction(FnName))
+ {
+ return false;
+ }
+
+ m_LuaState.PushObject(&a_World);
+ m_LuaState.PushObject(&a_Monster);
+
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+
+ bool bRetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
+ lua_pop(m_LuaState, 1);
+ return bRetVal;
+ return false;
+}
+
+
+
+
+
bool cPlugin_NewLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI)
{
cCSLock Lock(m_CriticalSection);
@@ -1482,6 +1593,10 @@ const char * cPlugin_NewLua::GetHookFnName(cPluginManager::PluginHook a_Hook)
case cPluginManager::HOOK_PLAYER_USING_ITEM: return "OnPlayerUsingItem";
case cPluginManager::HOOK_POST_CRAFTING: return "OnPostCrafting";
case cPluginManager::HOOK_PRE_CRAFTING: return "OnPreCrafting";
+ case cPluginManager::HOOK_SPAWNED_ENTITY: return "OnSpawnedEntity";
+ case cPluginManager::HOOK_SPAWNED_MONSTER: return "OnSpawnedMonster";
+ case cPluginManager::HOOK_SPAWNING_ENTITY: return "OnSpawningEntity";
+ case cPluginManager::HOOK_SPAWNING_MONSTER: return "OnSpawningMonster";
case cPluginManager::HOOK_TAKE_DAMAGE: return "OnTakeDamage";
case cPluginManager::HOOK_TICK: return "OnTick";
case cPluginManager::HOOK_UPDATED_SIGN: return "OnUpdatedSign";
diff --git a/source/Plugin_NewLua.h b/source/Plugin_NewLua.h
index d31a62601..ba66a9047 100644
--- a/source/Plugin_NewLua.h
+++ b/source/Plugin_NewLua.h
@@ -68,6 +68,10 @@ public:
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
+ virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) override;
+ virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster) override;
+ virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) override;
+ virtual bool OnSpawningMonster (cWorld & a_World, cMonster & a_Monster) override;
virtual bool OnTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) override;
virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override;
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override;
diff --git a/source/TNTEntity.cpp b/source/TNTEntity.cpp
index e431464b3..25e8f19ce 100644
--- a/source/TNTEntity.cpp
+++ b/source/TNTEntity.cpp
@@ -29,10 +29,14 @@ cTNTEntity::cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec) :
-void cTNTEntity::Initialize(cWorld * a_World)
+bool cTNTEntity::Initialize(cWorld * a_World)
{
- super::Initialize(a_World);
- a_World->BroadcastSpawnEntity(*this);
+ if (super::Initialize(a_World))
+ {
+ a_World->BroadcastSpawnEntity(*this);
+ return true;
+ }
+ return false;
}
diff --git a/source/TNTEntity.h b/source/TNTEntity.h
index 5dbfd2d43..a8487b66f 100644
--- a/source/TNTEntity.h
+++ b/source/TNTEntity.h
@@ -20,7 +20,7 @@ public:
cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec);
// cEntity overrides:
- virtual void Initialize(cWorld * a_World) override;
+ 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/World.cpp b/source/World.cpp
index 699767d5e..6a83da489 100644
--- a/source/World.cpp
+++ b/source/World.cpp
@@ -2414,14 +2414,24 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, int a_EntityTy
default:
{
- LOGWARNING("cWorld::SpawnMob(): Unhandled entity type: %d. Not spawning.", a_EntityType);
+ LOGWARNING("%s: Unhandled entity type: %d. Not spawning.", __FUNCTION__, a_EntityType);
return -1;
}
}
Monster->SetPosition(a_PosX, a_PosY, a_PosZ);
Monster->SetHealth(Monster->GetMaxHealth());
- Monster->Initialize(this);
+ if (cPluginManager::Get()->CallHookSpawningMonster(*this, *Monster))
+ {
+ delete Monster;
+ return -1;
+ }
+ if (!Monster->Initialize(this))
+ {
+ delete Monster;
+ return -1;
+ }
BroadcastSpawnEntity(*Monster);
+ cPluginManager::Get()->CallHookSpawnedMonster(*this, *Monster);
return Monster->GetUniqueID();
}