diff options
-rw-r--r-- | MCServer/Plugins/APIDump/APIDesc.lua | 72 | ||||
-rw-r--r-- | MCServer/Plugins/Debuggers/Debuggers.lua | 15 | ||||
-rw-r--r-- | MCServer/Plugins/InfoDump.lua | 31 | ||||
-rw-r--r-- | src/Bindings/LuaState.cpp | 18 | ||||
-rw-r--r-- | src/Bindings/LuaState.h | 97 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 258 | ||||
-rw-r--r-- | src/Blocks/BlockTrapdoor.h | 4 | ||||
-rw-r--r-- | src/CompositeChat.h | 17 | ||||
-rw-r--r-- | src/Defines.h | 6 | ||||
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator.cpp | 8 | ||||
-rw-r--r-- | src/World.cpp | 98 | ||||
-rw-r--r-- | src/World.h | 10 |
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 |