summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua72
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua15
-rw-r--r--MCServer/Plugins/InfoDump.lua31
-rw-r--r--src/Bindings/LuaState.cpp18
-rw-r--r--src/Bindings/LuaState.h97
-rw-r--r--src/Bindings/ManualBindings.cpp258
-rw-r--r--src/Blocks/BlockTrapdoor.h4
-rw-r--r--src/CompositeChat.h17
-rw-r--r--src/Defines.h6
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp8
-rw-r--r--src/World.cpp98
-rw-r--r--src/World.h10
12 files changed, 519 insertions, 115 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index 0b6f33b37..94cdd0063 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -483,6 +483,58 @@ end
},
}, -- cClientHandle
+ cCompositeChat =
+ {
+ Desc = [[
+ Encapsulates a chat message that can contain various formatting, URLs, commands executed on click
+ and commands suggested on click. The chat message can be sent by the regular chat-sending functions,
+ {{cPlayer}}:SendMessage(), {{cWorld}}:BroadcastChat() and {{cRoot}}:BroadcastChat().</p>
+ <p>
+ Note that most of the functions in this class are so-called modifiers - they modify the object and
+ then return the object itself, so that they can be chained one after another.
+ ]],
+ Functions =
+ {
+ constructor =
+ {
+ { Params = "", Return = "", Notes = "Creates an empty chat message" },
+ { Params = "Text", Return = "", Notes = "Creates a chat message containing the specified text, parsed by the ParseText() function. This allows easy migration from old chat messages." },
+ },
+ AddRunCommandPart = { Params = "Text, Command, [Style]", Return = "self", Notes = "Adds a text which, when clicked, runs the specified command. Chaining." },
+ AddSuggestCommandPart = { Params = "Text, Command, [Style]", Return = "self", Notes = "Adds a text which, when clicked, puts the specified command into the player's chat input area. Chaining." },
+ AddTextPart = { Params = "Text, [Style]", Return = "self", Notes = "Adds a regular text. Chaining." },
+ AddUrlPart = { Params = "Text, Url, [Style]", Return = "self", Notes = "Adds a text which, when clicked, opens up a browser at the specified URL. Chaining." },
+ Clear = { Params = "", Return = "", Notes = "Removes all parts from this object" },
+ GetMessageType = { Params = "", Return = "MessageType", Notes = "Returns the MessageType (mtXXX constant) that is associated with this message. When sent to a player, the message will be formatted according to this message type and the player's settings (adding \"[INFO]\" prefix etc.)" },
+ ParseText = { Params = "Text", Return = "self", Notes = "Adds text, while recognizing http and https URLs and old-style formatting codes (\"@2\"). Chaining." },
+ SetMessageType = { Params = "MessageType", Return = "self", Notes = "Sets the MessageType (mtXXX constant) that is associated with this message. When sent to a player, the message will be formatted according to this message type and the player's settings (adding \"[INFO]\" prefix etc.) Chaining." },
+ UnderlineUrls = { Params = "", Return = "self", Notes = "Makes all URL parts contained in the message underlined. Doesn't affect parts added in the future. Chaining." },
+ },
+
+ AdditionalInfo =
+ {
+ {
+ Header = "Chaining example",
+ Contents = [[
+ Sending a chat message that is composed of multiple different parts has been made easy thanks to
+ chaining. Consider the following example that shows how a message containing all kinds of parts
+ is sent (adapted from the Debuggers plugin):
+<pre class="prettyprint lang-lua">
+function OnPlayerJoined(a_Player)
+ -- Send an example composite chat message to the player:
+ a_Player:SendMessage(cCompositeChat()
+ :AddTextPart("Hello, ")
+ :AddUrlPart(a_Player:GetName(), "www.mc-server.org", "u@2") -- Colored underlined link
+ :AddSuggestCommandPart(", and welcome.", "/help", "u") -- Underlined suggest-command
+ :AddRunCommandPart(" SetDay", "/time set 0") -- Regular text that will execute command when clicked
+ :SetMessageType(mtJoin) -- It is a join-message
+ )
+end</pre>
+ ]],
+ },
+ }, -- AdditionalInfo
+ }, -- cCompositeChat
+
cCraftingGrid =
{
Desc = [[
@@ -2701,16 +2753,16 @@ end
IgnoreClasses =
{
- "coroutine",
- "debug",
- "io",
- "math",
- "package",
- "os",
- "string",
- "table",
- "g_Stats",
- "g_TrackedPages",
+ "^coroutine$",
+ "^debug$",
+ "^io$",
+ "^math$",
+ "^package$",
+ "^os$",
+ "^string$",
+ "^table$",
+ "^g_Stats$",
+ "^g_TrackedPages$",
},
IgnoreFunctions =
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 66894d835..329a652cd 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -30,6 +30,7 @@ function Initialize(Plugin)
PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
PM:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded);
PM:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
+ PM:AddHook(cPluginManager.HOOK_PLAYER_JOINED, OnPlayerJoined)
PM:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities");
PM:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities");
@@ -1258,3 +1259,17 @@ end
+
+function OnPlayerJoined(a_Player)
+ -- Test composite chat chaining:
+ a_Player:SendMessage(cCompositeChat()
+ :AddTextPart("Hello, ")
+ :AddUrlPart(a_Player:GetName(), "www.mc-server.org", "u@2")
+ :AddSuggestCommandPart(", and welcome.", "/help", "u")
+ :AddRunCommandPart(" SetDay", "/time set 0")
+ )
+end
+
+
+
+
diff --git a/MCServer/Plugins/InfoDump.lua b/MCServer/Plugins/InfoDump.lua
index e7ed157e3..c61f9c9e6 100644
--- a/MCServer/Plugins/InfoDump.lua
+++ b/MCServer/Plugins/InfoDump.lua
@@ -317,26 +317,19 @@ local function WriteCommandsCategoryGithub(a_Category, f)
if (CategoryName == "") then
CategoryName = "General";
end
- f:write("\n## ", GithubizeString(a_Category.DisplayName or CategoryName), "\n");
+ f:write("\n### ", GithubizeString(a_Category.DisplayName or CategoryName), "\n");
-- Write description:
if (a_Category.Description ~= "") then
- f:write(GithubizeString(a_Category.Description), "\n");
+ f:write(GithubizeString(a_Category.Description), "\n\n");
end
+ f:write("| Command | Permission | Description | \n")
+ f:write("| ------- | ---------- | ----------- | \n")
+
-- Write commands:
- f:write("\n");
for idx2, cmd in ipairs(a_Category.Commands) do
- f:write("\n### ", cmd.CommandString, "\n", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "\n\n");
- if (cmd.Info.Permission ~= nil) then
- f:write("Permission required: **", cmd.Info.Permission, "**\n\n");
- end
- if (cmd.Info.DetailedDescription ~= nil) then
- f:write(GithubizeString(cmd.Info.DetailedDescription));
- end
- if (cmd.Info.ParameterCombinations ~= nil) then
- WriteCommandParameterCombinationsGithub(cmd.CommandString, cmd.Info.ParameterCombinations, f);
- end
+ f:write("|", cmd.CommandString, " | ", cmd.Info.Permission or "", " | ", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "| \n")
end
f:write("\n\n")
end
@@ -537,12 +530,13 @@ local function DumpPermissionsGithub(a_PluginInfo, f)
-- Dump the permissions:
f:write("\n# Permissions\n");
+ f:write("| Permissions | Description | Commands | Recommended groups |\n")
+ f:write("| ----------- | ----------- | -------- | ------------------ |\n")
for idx, perm in ipairs(Permissions) do
- f:write("### ", perm.Name, "\n");
- f:write(GithubizeString(perm.Info.Description or ""));
+ f:write(perm.Name, " | ");
+ f:write(GithubizeString(perm.Info.Description or ""), " | ");
local CommandsAffected = perm.Info.CommandsAffected or {};
if (#CommandsAffected > 0) then
- f:write("\n\nCommands affected:\n - ");
local Affects = {};
for idx2, cmd in ipairs(CommandsAffected) do
if (type(cmd) == "string") then
@@ -551,11 +545,10 @@ local function DumpPermissionsGithub(a_PluginInfo, f)
table.insert(Affects, GetCommandRefGithub(cmd.Name, cmd));
end
end
- f:write(table.concat(Affects, "\n - "));
- f:write("\n");
+ f:write(table.concat(Affects, ", "), " | ");
end
if (perm.Info.RecommendedGroups ~= nil) then
- f:write("\n\nRecommended groups: ", perm.Info.RecommendedGroups, "\n");
+ f:write(perm.Info.RecommendedGroups, " |");
end
f:write("\n");
end
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index a5540df17..1890dcfe5 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -716,7 +716,7 @@ void cLuaState::Push(cBlockEntity * a_BlockEntity)
-void cLuaState::GetReturn(int a_StackPos, bool & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
{
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0);
}
@@ -725,11 +725,17 @@ void cLuaState::GetReturn(int a_StackPos, bool & a_ReturnedVal)
-void cLuaState::GetReturn(int a_StackPos, AString & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
{
- if (lua_isstring(m_LuaState, a_StackPos))
+ size_t len = 0;
+ const char * data = lua_tolstring(m_LuaState, a_StackPos, &len);
+ if (data != NULL)
+ {
+ a_Value.assign(data, len);
+ }
+ else
{
- a_ReturnedVal = tolua_tocppstring(m_LuaState, a_StackPos, a_ReturnedVal.c_str());
+ a_Value.clear();
}
}
@@ -737,7 +743,7 @@ void cLuaState::GetReturn(int a_StackPos, AString & a_ReturnedVal)
-void cLuaState::GetReturn(int a_StackPos, int & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
@@ -749,7 +755,7 @@ void cLuaState::GetReturn(int a_StackPos, int & a_ReturnedVal)
-void cLuaState::GetReturn(int a_StackPos, double & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index dcb660c3f..4a7a6fadb 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -197,6 +197,19 @@ public:
void Push(void * a_Ptr);
void Push(cHopperEntity * a_Hopper);
void Push(cBlockEntity * a_BlockEntity);
+
+ /** Retrieve value at a_StackPos, if it is a valid bool. If not, a_Value is unchanged */
+ void GetStackValue(int a_StackPos, bool & a_Value);
+
+ /** Retrieve value at a_StackPos, if it is a valid string. If not, a_Value is unchanged */
+ void GetStackValue(int a_StackPos, AString & a_Value);
+
+ /** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
+ void GetStackValue(int a_StackPos, int & a_Value);
+
+ /** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
+ void GetStackValue(int a_StackPos, double & a_Value);
+
/** Call any 0-param 0-return Lua function in a single line: */
template <typename FnT>
@@ -270,7 +283,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -292,7 +305,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
ASSERT(InitialTop == lua_gettop(m_LuaState));
return true;
@@ -315,7 +328,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -338,7 +351,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -362,7 +375,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -387,7 +400,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -414,7 +427,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -442,7 +455,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -471,7 +484,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -501,7 +514,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -532,7 +545,7 @@ public:
{
return false;
}
- GetReturn(-1, a_Ret1);
+ GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@@ -553,8 +566,8 @@ public:
{
return false;
}
- GetReturn(-2, a_Ret1);
- GetReturn(-1, a_Ret2);
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@@ -576,8 +589,8 @@ public:
{
return false;
}
- GetReturn(-2, a_Ret1);
- GetReturn(-1, a_Ret2);
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@@ -601,8 +614,8 @@ public:
{
return false;
}
- GetReturn(-2, a_Ret1);
- GetReturn(-1, a_Ret2);
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@@ -627,8 +640,8 @@ public:
{
return false;
}
- GetReturn(-2, a_Ret1);
- GetReturn(-1, a_Ret2);
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@@ -654,8 +667,8 @@ public:
{
return false;
}
- GetReturn(-2, a_Ret1);
- GetReturn(-1, a_Ret2);
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@@ -683,8 +696,8 @@ public:
{
return false;
}
- GetReturn(-2, a_Ret1);
- GetReturn(-1, a_Ret2);
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@@ -713,8 +726,8 @@ public:
{
return false;
}
- GetReturn(-2, a_Ret1);
- GetReturn(-1, a_Ret2);
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@@ -743,9 +756,9 @@ public:
{
return false;
}
- GetReturn(-3, a_Ret1);
- GetReturn(-2, a_Ret2);
- GetReturn(-1, a_Ret3);
+ GetStackValue(-3, a_Ret1);
+ GetStackValue(-2, a_Ret2);
+ GetStackValue(-1, a_Ret3);
lua_pop(m_LuaState, 3);
return true;
}
@@ -775,9 +788,9 @@ public:
{
return false;
}
- GetReturn(-3, a_Ret1);
- GetReturn(-2, a_Ret2);
- GetReturn(-1, a_Ret3);
+ GetStackValue(-3, a_Ret1);
+ GetStackValue(-2, a_Ret2);
+ GetStackValue(-1, a_Ret3);
lua_pop(m_LuaState, 3);
return true;
}
@@ -808,11 +821,11 @@ public:
{
return false;
}
- GetReturn(-5, a_Ret1);
- GetReturn(-4, a_Ret2);
- GetReturn(-3, a_Ret3);
- GetReturn(-2, a_Ret4);
- GetReturn(-1, a_Ret5);
+ GetStackValue(-5, a_Ret1);
+ GetStackValue(-4, a_Ret2);
+ GetStackValue(-3, a_Ret3);
+ GetStackValue(-2, a_Ret4);
+ GetStackValue(-1, a_Ret5);
lua_pop(m_LuaState, 5);
return true;
}
@@ -918,18 +931,6 @@ protected:
/** Pushes a usertype of the specified class type onto the stack */
void PushUserType(void * a_Object, const char * a_Type);
- /** Retrieve value returned at a_StackPos, if it is a valid bool. If not, a_ReturnedVal is unchanged */
- void GetReturn(int a_StackPos, bool & a_ReturnedVal);
-
- /** Retrieve value returned at a_StackPos, if it is a valid string. If not, a_ReturnedVal is unchanged */
- void GetReturn(int a_StackPos, AString & a_ReturnedVal);
-
- /** Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged */
- void GetReturn(int a_StackPos, int & a_ReturnedVal);
-
- /** Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged */
- void GetReturn(int a_StackPos, double & a_ReturnedVal);
-
/**
Calls the function that has been pushed onto the stack by PushFunction(),
with arguments pushed by PushXXX().
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index fcdd728be..9fbc2e842 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -26,6 +26,7 @@
#include "md5/md5.h"
#include "../LineBlockTracer.h"
#include "../WorldStorage/SchematicFileSerializer.h"
+#include "../CompositeChat.h"
@@ -2511,6 +2512,253 @@ static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
+static int tolua_cCompositeChat_AddRunCommandPart(lua_State * tolua_S)
+{
+ // function cCompositeChat:AddRunCommandPart(Message, Command, [Style])
+ // Exported manually to support call-chaining (return *this)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cCompositeChat") ||
+ !L.CheckParamString(2, 3)
+ )
+ {
+ return 0;
+ }
+ cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddRunCommandPart'", NULL);
+ return 0;
+ }
+
+ // Add the part:
+ AString Text, Command, Style;
+ L.GetStackValue(2, Text);
+ L.GetStackValue(3, Command);
+ L.GetStackValue(4, Style);
+ self->AddRunCommandPart(Text, Command, Style);
+
+ // Cut away everything from the stack except for the cCompositeChat instance; return that:
+ lua_settop(L, 1);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cCompositeChat_AddSuggestCommandPart(lua_State * tolua_S)
+{
+ // function cCompositeChat:AddSuggestCommandPart(Message, Command, [Style])
+ // Exported manually to support call-chaining (return *this)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cCompositeChat") ||
+ !L.CheckParamString(2, 3)
+ )
+ {
+ return 0;
+ }
+ cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddSuggestCommandPart'", NULL);
+ return 0;
+ }
+
+ // Add the part:
+ AString Text, Command, Style;
+ L.GetStackValue(2, Text);
+ L.GetStackValue(3, Command);
+ L.GetStackValue(4, Style);
+ self->AddSuggestCommandPart(Text, Command, Style);
+
+ // Cut away everything from the stack except for the cCompositeChat instance; return that:
+ lua_settop(L, 1);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cCompositeChat_AddTextPart(lua_State * tolua_S)
+{
+ // function cCompositeChat:AddTextPart(Message, [Style])
+ // Exported manually to support call-chaining (return *this)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cCompositeChat") ||
+ !L.CheckParamString(2)
+ )
+ {
+ return 0;
+ }
+ cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddTextPart'", NULL);
+ return 0;
+ }
+
+ // Add the part:
+ AString Text, Style;
+ L.GetStackValue(2, Text);
+ L.GetStackValue(3, Style);
+ self->AddTextPart(Text, Style);
+
+ // Cut away everything from the stack except for the cCompositeChat instance; return that:
+ lua_settop(L, 1);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cCompositeChat_AddUrlPart(lua_State * tolua_S)
+{
+ // function cCompositeChat:AddTextPart(Message, Url, [Style])
+ // Exported manually to support call-chaining (return *this)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cCompositeChat") ||
+ !L.CheckParamString(2, 3)
+ )
+ {
+ return 0;
+ }
+ cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddUrlPart'", NULL);
+ return 0;
+ }
+
+ // Add the part:
+ AString Text, Url, Style;
+ L.GetStackValue(2, Text);
+ L.GetStackValue(3, Url);
+ L.GetStackValue(4, Style);
+ self->AddUrlPart(Text, Url, Style);
+
+ // Cut away everything from the stack except for the cCompositeChat instance; return that:
+ lua_settop(L, 1);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cCompositeChat_ParseText(lua_State * tolua_S)
+{
+ // function cCompositeChat:ParseText(TextMessage)
+ // Exported manually to support call-chaining (return *this)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cCompositeChat") ||
+ !L.CheckParamString(2)
+ )
+ {
+ return 0;
+ }
+ cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:ParseText'", NULL);
+ return 0;
+ }
+
+ // Parse the text:
+ AString Text;
+ L.GetStackValue(2, Text);
+ self->ParseText(Text);
+
+ // Cut away everything from the stack except for the cCompositeChat instance; return that:
+ lua_settop(L, 1);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cCompositeChat_SetMessageType(lua_State * tolua_S)
+{
+ // function cCompositeChat:SetMessageType(MessageType)
+ // Exported manually to support call-chaining (return *this)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cCompositeChat") ||
+ !L.CheckParamNumber(2)
+ )
+ {
+ return 0;
+ }
+ cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:SetMessageType'", NULL);
+ return 0;
+ }
+
+ // Set the type:
+ int MessageType;
+ L.GetStackValue(1, MessageType);
+ self->SetMessageType((eMessageType)MessageType);
+
+ // Cut away everything from the stack except for the cCompositeChat instance; return that:
+ lua_settop(L, 1);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cCompositeChat_UnderlineUrls(lua_State * tolua_S)
+{
+ // function cCompositeChat:UnderlineUrls()
+ // Exported manually to support call-chaining (return *this)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (!L.CheckParamUserType(1, "cCompositeChat"))
+ {
+ return 0;
+ }
+ cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
+ if (self == NULL)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:UnderlineUrls'", NULL);
+ return 0;
+ }
+
+ // Call the processing
+ self->UnderlineUrls();
+
+ // Cut away everything from the stack except for the cCompositeChat instance; return that:
+ lua_settop(L, 1);
+ return 1;
+}
+
+
+
+
+
void ManualBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S, NULL);
@@ -2535,6 +2783,16 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
tolua_endmodule(tolua_S);
+ tolua_beginmodule(tolua_S, "cCompositeChat");
+ tolua_function(tolua_S, "AddRunCommandPart", tolua_cCompositeChat_AddRunCommandPart);
+ tolua_function(tolua_S, "AddSuggestCommandPart", tolua_cCompositeChat_AddSuggestCommandPart);
+ tolua_function(tolua_S, "AddTextPart", tolua_cCompositeChat_AddTextPart);
+ tolua_function(tolua_S, "AddUrlPart", tolua_cCompositeChat_AddUrlPart);
+ tolua_function(tolua_S, "ParseText", tolua_cCompositeChat_ParseText);
+ tolua_function(tolua_S, "SetMessageType", tolua_cCompositeChat_SetMessageType);
+ tolua_function(tolua_S, "UnderlineUrls", tolua_cCompositeChat_UnderlineUrls);
+ tolua_endmodule(tolua_S);
+
tolua_beginmodule(tolua_S, "cHopperEntity");
tolua_function(tolua_S, "GetOutputBlockPos", tolua_cHopperEntity_GetOutputBlockPos);
tolua_endmodule(tolua_S);
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 70a369e69..a28861e69 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -36,8 +36,10 @@ public:
{
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x04);
-
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
+
+ cWorld * World = (cWorld *) &a_WorldInterface;
+ World->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
}
virtual bool GetPlacementBlockTypeMeta(
diff --git a/src/CompositeChat.h b/src/CompositeChat.h
index 51600da4f..27319490d 100644
--- a/src/CompositeChat.h
+++ b/src/CompositeChat.h
@@ -124,14 +124,15 @@ public:
/** Removes all parts from the object. */
void Clear(void);
+ // tolua_end
+
+ // The following are exported in ManualBindings in order to support chaining - they return *this in Lua (#755)
+
/** Adds a plain text part, with optional style.
The default style is plain white text. */
void AddTextPart(const AString & a_Message, const AString & a_Style = "");
- // tolua_end
-
- /** Adds a part that is translated client-side, with the formatting parameters and optional style.
- Exported in ManualBindings due to AStringVector usage - Lua uses an array-table of strings. */
+ /** Adds a part that is translated client-side, with the formatting parameters and optional style. */
void AddClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style = "");
// tolua_begin
@@ -155,12 +156,14 @@ public:
/** Sets the message type, which is indicated by prefixes added to the message when serializing. */
void SetMessageType(eMessageType a_MessageType);
- /** Returns the message type set previously by SetMessageType(). */
- eMessageType GetMessageType(void) const { return m_MessageType; }
-
/** Adds the "underline" style to each part that is an URL. */
void UnderlineUrls(void);
+ // tolua_begin
+
+ /** Returns the message type set previously by SetMessageType(). */
+ eMessageType GetMessageType(void) const { return m_MessageType; }
+
// tolua_end
const cParts & GetParts(void) const { return m_Parts; }
diff --git a/src/Defines.h b/src/Defines.h
index 018ecb1d3..6ab2274a4 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -235,8 +235,8 @@ inline eBlockFace MirrorBlockFaceY(eBlockFace a_BlockFace)
case BLOCK_FACE_XP: return BLOCK_FACE_XM;
case BLOCK_FACE_ZM: return BLOCK_FACE_ZP;
case BLOCK_FACE_ZP: return BLOCK_FACE_ZM;
+ default: return a_BlockFace;
}
- return a_BlockFace;
}
@@ -252,8 +252,8 @@ inline eBlockFace RotateBlockFaceCCW(eBlockFace a_BlockFace)
case BLOCK_FACE_XP: return BLOCK_FACE_ZM;
case BLOCK_FACE_ZM: return BLOCK_FACE_XM;
case BLOCK_FACE_ZP: return BLOCK_FACE_XP;
+ default: return a_BlockFace;
}
- return a_BlockFace;
}
@@ -268,8 +268,8 @@ inline eBlockFace RotateBlockFaceCW(eBlockFace a_BlockFace)
case BLOCK_FACE_XP: return BLOCK_FACE_ZP;
case BLOCK_FACE_ZM: return BLOCK_FACE_XP;
case BLOCK_FACE_ZP: return BLOCK_FACE_XM;
+ default: return a_BlockFace;
}
- return a_BlockFace;
}
diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp
index 0640227b0..f377b0aa7 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator.cpp
@@ -937,17 +937,15 @@ void cIncrementalRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, i
{
if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x4);
- m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0);
+ m_World.SetTrapdoorOpen(a_BlockX, a_BlockY, a_BlockZ, true);
SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
- }
+ }
}
else
{
if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0xB); // Take into account that the fourth bit is needed for trapdoors too
- m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0);
+ m_World.SetTrapdoorOpen(a_BlockX, a_BlockY, a_BlockZ, false);
SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
}
}
diff --git a/src/World.cpp b/src/World.cpp
index 01ba5e503..73157b5bf 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -265,8 +265,6 @@ cWorld::cWorld(const AString & a_WorldName) :
// Load the scoreboard
cScoreboardSerializer Serializer(m_WorldName, &m_Scoreboard);
Serializer.Load();
-
- m_MapManager.LoadMapData();
}
@@ -308,25 +306,52 @@ void cWorld::CastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ)
+int cWorld::GetDefaultWeatherInterval(eWeather a_Weather)
+{
+ switch (a_Weather)
+ {
+ case eWeather_Sunny:
+ {
+ return 14400 + (m_TickRand.randInt() % 4800); // 12 - 16 minutes
+ }
+ case eWeather_Rain:
+ {
+ return 9600 + (m_TickRand.randInt() % 7200); // 8 - 14 minutes
+ }
+ case eWeather_ThunderStorm:
+ {
+ return 2400 + (m_TickRand.randInt() % 4800); // 2 - 6 minutes
+ }
+ default:
+ {
+ LOGWARNING("%s: Missing default weather interval for weather %d.", __FUNCTION__, a_Weather);
+ return -1;
+ }
+ } // switch (Weather)
+}
+
+
+
+
+
void cWorld::SetWeather(eWeather a_NewWeather)
{
// Do the plugins agree? Do they want a different weather?
- cRoot::Get()->GetPluginManager()->CallHookWeatherChanging(*this, a_NewWeather);
+ if (cRoot::Get()->GetPluginManager()->CallHookWeatherChanging(*this, a_NewWeather))
+ {
+ m_WeatherInterval = GetDefaultWeatherInterval(m_Weather);
+ return;
+ }
// Set new period for the selected weather:
- switch (a_NewWeather)
+ m_WeatherInterval = GetDefaultWeatherInterval(a_NewWeather);
+
+ // The weather can't be found:
+ if (m_WeatherInterval < 0)
{
- case eWeather_Sunny: m_WeatherInterval = 14400 + (m_TickRand.randInt() % 4800); break; // 12 - 16 minutes
- case eWeather_Rain: m_WeatherInterval = 9600 + (m_TickRand.randInt() % 7200); break; // 8 - 14 minutes
- case eWeather_ThunderStorm: m_WeatherInterval = 2400 + (m_TickRand.randInt() % 4800); break; // 2 - 6 minutes
- default:
- {
- LOGWARNING("Requested unknown weather %d, setting sunny for a minute instead.", a_NewWeather);
- a_NewWeather = eWeather_Sunny;
- m_WeatherInterval = 1200;
- break;
- }
- } // switch (NewWeather)
+ return;
+ }
+
m_Weather = a_NewWeather;
BroadcastWeather(m_Weather);
@@ -626,13 +651,13 @@ void cWorld::Start(void)
m_LastSpawnMonster.insert(std::map<cMonster::eFamily, Int64>::value_type(cMonster::mfAmbient, 0));
m_LastSpawnMonster.insert(std::map<cMonster::eFamily, Int64>::value_type(cMonster::mfWater, 0));
+ m_MapManager.LoadMapData();
// Save any changes that the defaults may have done to the ini file:
if (!IniFile.WriteFile(m_IniFileName))
{
LOGWARNING("Could not write world config to %s", m_IniFileName.c_str());
}
-
}
@@ -2648,6 +2673,47 @@ bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, co
+bool cWorld::IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, Block, Meta);
+ if (Block != E_BLOCK_TRAPDOOR)
+ {
+ return false;
+ }
+
+ return (Meta & 0x4) > 0;
+}
+
+
+
+
+
+bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open)
+{
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, Block, Meta);
+ if (Block != E_BLOCK_TRAPDOOR)
+ {
+ return false;
+ }
+
+ bool IsOpen = (Meta & 0x4) > 0;
+ if (a_Open != IsOpen)
+ {
+ SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta ^ 0x4);
+ BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ)
{
m_ChunkMap->MarkChunkRegenerating(a_ChunkX, a_ChunkZ);
diff --git a/src/World.h b/src/World.h
index 4b74f7aba..93397c014 100644
--- a/src/World.h
+++ b/src/World.h
@@ -139,6 +139,10 @@ public:
BroadcastTimeUpdate();
}
+ /** Returns the default weather interval for the specific weather type.
+ Returns -1 for any unknown weather. */
+ int GetDefaultWeatherInterval(eWeather a_Weather);
+
/** Returns the current game mode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable */
eGameMode GetGameMode(void) const { return m_GameMode; }
@@ -342,6 +346,12 @@ public:
/** Sets the command block command. Returns true if command changed. */
bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export
+ /** Is the trapdoor open? Returns false if there is no trapdoor at the specified coords. */
+ bool IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
+
+ /** Set the state of a trapdoor. Returns true if the trapdoor was update, false if there was no trapdoor at those coords. */
+ bool SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open); // tolua_export
+
/** Regenerate the given chunk: */
void RegenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export