From 16f3355bbbd2170dd8f836885f5c887ff65c5f7d Mon Sep 17 00:00:00 2001 From: Debucquoy Anthony tonitch Date: Tue, 25 Oct 2022 13:42:04 +0200 Subject: [PATCH 01/13] rework of the color code with & and standard codes (#5416) * adding build* to gitignore and tags for ctags * Notation Changes * Adding & Parser * Avoid crash when & as first character * Looking for @ in the rest of the project * Formating style * Modifying test to reflect new behaviours * Adding a check for the first part * fixup! Adding & Parser style changes * Update APIDesk.lua * Update src/CompositeChat.cpp Co-authored-by: x12xx12x <44411062+12xx12@users.noreply.github.com> * explaination on the antishlash with ampersand * adding old deprecated formating * Update src/CompositeChat.cpp Co-authored-by: x12xx12x <44411062+12xx12@users.noreply.github.com> * Update src/CompositeChat.cpp * Update src/CompositeChat.cpp Co-authored-by: Debucquoy Co-authored-by: x12xx12x <44411062+12xx12@users.noreply.github.com> --- .gitignore | 4 + Server/Plugins/APIDump/APIDesc.lua | 19 ++- src/Bindings/ManualBindings.cpp | 2 +- src/CompositeChat.cpp | 191 ++++++++-------------- src/CompositeChat.h | 27 ++- tests/CompositeChat/CompositeChatTest.cpp | 18 +- 6 files changed, 105 insertions(+), 156 deletions(-) diff --git a/.gitignore b/.gitignore index e271cc0195..170ef36972 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/ +build*/ nbproject/ ipch/ Win32/ @@ -122,3 +123,6 @@ build-cuberite # clang-tidy tidy-build run-clang-tidy.py + +# ctags output +tags diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index 03fb319903..f920a8f5bf 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -2228,18 +2228,21 @@ end Chaining example below for details.

Each part of the composite chat message takes a "Style" parameter, this is a string that describes - the formatting. It uses the following strings, concatenated together: + the formatting. It uses the "standard" minecraft format code without the '&' symbole, concatenated + together: - - - - - - + + + + + + +
StringStyle
bBold text
iItalic text
uUnderlined text
sStrikethrough text
oObfuscated text
@Xcolor [0–9a–f], same as dye meta
lBold text
oItalic text
nUnderlined text
mStrikethrough text
kObfuscated text
rReset Style
[0-9a-f]colors
+ You can escape the '&' character with an antislash in front of it. as follow: `I love Choco\&chips` The following picture, taken from the Minecraft Wiki, illustrates the color codes:

- + ]], Functions = { diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index f5517dc843..40ab0467b4 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -3949,7 +3949,7 @@ static int tolua_cCompositeChat_AddRunCommandPart(lua_State * tolua_S) } // Add the part: - AString Text, Command, Style = "u@a"; + AString Text, Command, Style = "na"; L.GetStackValue(2, Text); L.GetStackValue(3, Command); L.GetStackValue(4, Style); diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp index 46712a0f52..94ed781977 100644 --- a/src/CompositeChat.cpp +++ b/src/CompositeChat.cpp @@ -96,50 +96,52 @@ void cCompositeChat::AddShowAchievementPart(const AString & a_PlayerName, const - +/** +* Parse the input message to add colors or link then add it to the object. +* +* It detects every & of the message and the next character for it to colorize. +* It detect : in the text to detect link structures. +* +* @param a_ParseText The input text to parse +*/ void cCompositeChat::ParseText(const AString & a_ParseText) { size_t len = a_ParseText.length(); - size_t first = 0; // First character of the currently parsed block + size_t cursor = 0; AString CurrentStyle; AString CurrentText; + for (size_t i = 0; i < len; i++) { switch (a_ParseText[i]) { - case '@': + case '&': //< Color code { - // Color code - i++; - if (i >= len) + if ((i != 0) && (a_ParseText[i-1] == '\\')) { - // Not enough following text - break; + CurrentText.append(a_ParseText, cursor, i - cursor - 1).append("&"); + AddTextPart(CurrentText, CurrentStyle); + CurrentText.clear(); + cursor = ++i; + continue; } - if (a_ParseText[i] == '@') + + if (cursor < i) { - // "@@" escape, just put a "@" into the current text and keep parsing as text - if (i > first + 1) - { - CurrentText.append(a_ParseText.c_str() + first, i - first - 1); - } - first = i + 1; - continue; + CurrentText.append(a_ParseText, cursor, i - cursor); + AddTextPart(CurrentText, CurrentStyle); + CurrentText.clear(); + } + i++; + cursor = i + 1; + + if (a_ParseText[i] == 'r') + { + CurrentStyle = ""; } else { - // True color code. Create a part for the CurrentText and start parsing anew: - if (i >= first) - { - CurrentText.append(a_ParseText.c_str() + first, i - first - 1); - first = i + 1; - } - if (!CurrentText.empty()) - { - AddTextPart(CurrentText, CurrentStyle); - CurrentText.clear(); - } - AddStyle(CurrentStyle, a_ParseText.substr(i - 1, 2)); + CurrentStyle.push_back(a_ParseText[i]); } break; } @@ -157,15 +159,15 @@ void cCompositeChat::ParseText(const AString & a_ParseText) { size_t PrefixLen = Prefix.size(); if ( - (i >= first + PrefixLen) && // There is enough space in front of the colon for the prefix + (i >= cursor + PrefixLen) && // There is enough space in front of the colon for the prefix (std::string_view(a_ParseText).substr(i - PrefixLen, PrefixLen) == Prefix) // the prefix matches ) { // Add everything before this as a text part: - if (i > first + PrefixLen) + if (i > cursor+ PrefixLen) { - CurrentText.append(a_ParseText.c_str() + first, i - first - PrefixLen); - first = i - PrefixLen; + CurrentText.append(a_ParseText.c_str() + cursor, i - cursor - PrefixLen); + cursor= i - PrefixLen; } if (!CurrentText.empty()) { @@ -181,8 +183,8 @@ void cCompositeChat::ParseText(const AString & a_ParseText) break; } } - AddUrlPart(a_ParseText.substr(first, i - first), a_ParseText.substr(first, i - first), CurrentStyle); - first = i; + AddUrlPart(a_ParseText.substr(cursor, i - cursor), a_ParseText.substr(cursor, i - cursor), CurrentStyle); + cursor = i; break; } } // for Prefix - LinkPrefix[] @@ -190,9 +192,11 @@ void cCompositeChat::ParseText(const AString & a_ParseText) } // case ':' } // switch (a_ParseText[i]) } // for i - a_ParseText[] - if (first < len) + if (cursor < len) { - AddTextPart(a_ParseText.substr(first, len - first), CurrentStyle); + CurrentText.clear(); + CurrentText.append(a_ParseText, cursor, len - cursor); + AddTextPart(CurrentText, CurrentStyle); } } @@ -218,7 +222,7 @@ void cCompositeChat::UnderlineUrls(void) { [](TextPart & a_Part) { }, [](ClientTranslatedPart & a_Part) { }, - [](UrlPart & a_Part) { a_Part.Style += 'u'; }, + [](UrlPart & a_Part) { a_Part.Style += 'n'; }, [](RunCommandPart & a_Part) { }, [](SuggestCommandPart & a_Part) { }, [](ShowAchievementPart & a_Part) { }, @@ -276,29 +280,6 @@ eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType) -void cCompositeChat::AddStyle(AString & a_Style, const AString & a_AddStyle) -{ - if (a_AddStyle.empty()) - { - return; - } - if (a_AddStyle[0] == '@') - { - size_t idx = a_Style.find('@'); - if ((idx != AString::npos) && (idx != a_Style.length())) - { - a_Style.erase(idx, 2); - } - a_Style.append(a_AddStyle); - return; - } - a_Style.append(a_AddStyle); -} - - - - - AString cCompositeChat::CreateJsonString(bool a_ShouldUseChatPrefixes) const { Json::Value Message; @@ -404,70 +385,34 @@ void cCompositeChat::AddChatPartStyle(Json::Value & a_Value, const AString & a_P { switch (a_PartStyle[i]) { - case 'b': - { - // bold - a_Value["bold"] = Json::Value(true); - break; - } - - case 'i': - { - // italic - a_Value["italic"] = Json::Value(true); - break; - } - - case 'u': - { - // Underlined - a_Value["underlined"] = Json::Value(true); - break; - } + case 'k': a_Value["obfuscated"] = Json::Value(true); break; + case 'l': a_Value["bold"] = Json::Value(true); break; + case 's': // Deprecated + LOGERROR("Value s in AddChatPartStyle() is deprecated"); + case 'm': a_Value["strikethrough"] = Json::Value(true); break; + case 'u': // Deprecated + LOGERROR("Value u in AddChatPartStyle() is deprecated"); + case 'n': a_Value["underlined"] = Json::Value(true); break; + case 'i': // Deprecated + LOGERROR("Value i in AddChatPartStyle() is deprecated"); + case 'o': a_Value["italic"] = Json::Value(true); break; + case '0': a_Value["color"] = Json::Value("black"); break; + case '1': a_Value["color"] = Json::Value("dark_blue"); break; + case '2': a_Value["color"] = Json::Value("dark_green"); break; + case '3': a_Value["color"] = Json::Value("dark_aqua"); break; + case '4': a_Value["color"] = Json::Value("dark_red"); break; + case '5': a_Value["color"] = Json::Value("dark_purple"); break; + case '6': a_Value["color"] = Json::Value("gold"); break; + case '7': a_Value["color"] = Json::Value("gray"); break; + case '8': a_Value["color"] = Json::Value("dark_gray"); break; + case '9': a_Value["color"] = Json::Value("blue"); break; + case 'a': a_Value["color"] = Json::Value("green"); break; + case 'b': a_Value["color"] = Json::Value("aqua"); break; + case 'c': a_Value["color"] = Json::Value("red"); break; + case 'd': a_Value["color"] = Json::Value("light_purple"); break; + case 'e': a_Value["color"] = Json::Value("yellow"); break; + case 'f': a_Value["color"] = Json::Value("white"); break; - case 's': - { - // strikethrough - a_Value["strikethrough"] = Json::Value(true); - break; - } - - case 'o': - { - // obfuscated - a_Value["obfuscated"] = Json::Value(true); - break; - } - - case '@': - { - // Color, specified by the next char: - i++; - if (i >= len) - { - // String too short, didn't contain a color - break; - } - switch (a_PartStyle[i]) - { - case '0': a_Value["color"] = Json::Value("black"); break; - case '1': a_Value["color"] = Json::Value("dark_blue"); break; - case '2': a_Value["color"] = Json::Value("dark_green"); break; - case '3': a_Value["color"] = Json::Value("dark_aqua"); break; - case '4': a_Value["color"] = Json::Value("dark_red"); break; - case '5': a_Value["color"] = Json::Value("dark_purple"); break; - case '6': a_Value["color"] = Json::Value("gold"); break; - case '7': a_Value["color"] = Json::Value("gray"); break; - case '8': a_Value["color"] = Json::Value("dark_gray"); break; - case '9': a_Value["color"] = Json::Value("blue"); break; - case 'a': a_Value["color"] = Json::Value("green"); break; - case 'b': a_Value["color"] = Json::Value("aqua"); break; - case 'c': a_Value["color"] = Json::Value("red"); break; - case 'd': a_Value["color"] = Json::Value("light_purple"); break; - case 'e': a_Value["color"] = Json::Value("yellow"); break; - case 'f': a_Value["color"] = Json::Value("white"); break; - } // switch (color) - } // case '@' } // switch (Style[i]) } // for i - a_PartStyle[] } diff --git a/src/CompositeChat.h b/src/CompositeChat.h index 78c8e0c9b7..4150bccc4e 100644 --- a/src/CompositeChat.h +++ b/src/CompositeChat.h @@ -21,12 +21,13 @@ Each part corresponds roughly to the behavior supported by the client messaging: - clickable commands (suggest) Each part has a text assigned to it that can be styled. The style is specified using a string, each character / character combination in the string specifies the style to use: - - b = bold - - i = italic - - u = underlined - - s = strikethrough - - o = obfuscated - - @X = color X (X is 0 - 9 or a - f, same as dye meta + - (char from 0 - 9 or a - f) = color X + - k = obfuscated + - l = bold + - m = strikethrough + - n = underlined + - o = italic + - r = reset If the protocol version doesn't support all the features, it degrades gracefully. */ class cCompositeChat @@ -102,7 +103,7 @@ class cCompositeChat cCompositeChat(void); /** Creates a new chat message and parses the text into parts. - Recognizes "http:" and "https:" links and @color-codes. + Recognizes "http:" and "https:" links and &format-character. Uses ParseText() for the actual parsing. Exported manually due to ToLua++ generating extra output parameter. */ cCompositeChat(const AString & a_ParseText, eMessageType a_MessageType = mtCustom); @@ -121,15 +122,15 @@ class cCompositeChat /** Adds a part that opens an URL when clicked. The default style is underlined light blue text. */ - void AddUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style = "u@c"); + void AddUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style = "nc"); /** Adds a part that runs a command when clicked. The default style is underlined light green text. */ - void AddRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style = "u@a"); + void AddRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style = "na"); /** Adds a part that suggests a command (enters it into the chat message area, but doesn't send) when clicked. The default style is underlined yellow text. */ - void AddSuggestCommandPart(const AString & a_Text, const AString & a_SuggestedCommand, const AString & a_Style = "u@b"); + void AddSuggestCommandPart(const AString & a_Text, const AString & a_SuggestedCommand, const AString & a_Style = "nb"); /** Adds a part that fully formats a specified achievement using client translatable strings Takes achievement name and player awarded to. Displays as {player} has earned the achievement {achievement_name}. @@ -137,7 +138,7 @@ class cCompositeChat void AddShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style = ""); /** Parses text into various parts, adds those. - Recognizes "http:" and "https:" URLs and @color-codes. */ + Recognizes "http:" and "https:" URLs and &color-codes. */ void ParseText(const AString & a_ParseText); /** Adds the "underline" style to each part that is an URL. */ @@ -185,8 +186,4 @@ class cCompositeChat /** Additional data pertaining to message type, for example, the name of a mtPrivateMsg sender */ AString m_AdditionalMessageTypeData; - - /** Adds a_AddStyle to a_Style; overwrites the existing style if appropriate. - If the style already contains something that a_AddStyle overrides, it is erased first. */ - void AddStyle(AString & a_Style, const AString & a_AddStyle); } ; // tolua_export diff --git a/tests/CompositeChat/CompositeChatTest.cpp b/tests/CompositeChat/CompositeChatTest.cpp index 636a5c95ae..ca05e79a2a 100644 --- a/tests/CompositeChat/CompositeChatTest.cpp +++ b/tests/CompositeChat/CompositeChatTest.cpp @@ -14,7 +14,7 @@ static void TestParser1(void) { cCompositeChat Msg; - Msg.ParseText("Testing @2color codes and http://links parser"); + Msg.ParseText("Testing &2color codes and http://links parser"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 4); @@ -22,13 +22,13 @@ static void TestParser1(void) TEST_EQUAL(std::get(Parts[0]).Style, ""); TEST_TRUE(std::holds_alternative(Parts[1])); - TEST_EQUAL(std::get(Parts[1]).Style, "@2"); + TEST_EQUAL(std::get(Parts[1]).Style, "2"); TEST_TRUE(std::holds_alternative(Parts[2])); - TEST_EQUAL(std::get(Parts[2]).Style, "@2"); + TEST_EQUAL(std::get(Parts[2]).Style, "2"); TEST_TRUE(std::holds_alternative(Parts[3])); - TEST_EQUAL(std::get(Parts[3]).Style, "@2"); + TEST_EQUAL(std::get(Parts[3]).Style, "2"); } @@ -38,21 +38,21 @@ static void TestParser1(void) static void TestParser2(void) { cCompositeChat Msg; - Msg.ParseText("@3Advanced stuff: @5overriding color codes and http://links.with/@4color-in-them handling"); + Msg.ParseText("&3Advanced stuff: &5overriding color codes and http://links.with/&4color-in-them handling"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 4); TEST_TRUE(std::holds_alternative(Parts[0])); - TEST_EQUAL(std::get(Parts[0]).Style, "@3"); + TEST_EQUAL(std::get(Parts[0]).Style, "3"); TEST_TRUE(std::holds_alternative(Parts[1])); - TEST_EQUAL(std::get(Parts[1]).Style, "@5"); + TEST_EQUAL(std::get(Parts[1]).Style, "35"); TEST_TRUE(std::holds_alternative(Parts[2])); - TEST_EQUAL(std::get(Parts[2]).Style, "@5"); + TEST_EQUAL(std::get(Parts[2]).Style, "35"); TEST_TRUE(std::holds_alternative(Parts[3])); - TEST_EQUAL(std::get(Parts[3]).Style, "@5"); + TEST_EQUAL(std::get(Parts[3]).Style, "35"); } From 21ec3ebe26bff24b5fc6d96f86a441c9c9628247 Mon Sep 17 00:00:00 2001 From: plan1231 <47790831+plan1231@users.noreply.github.com> Date: Fri, 28 Oct 2022 09:54:02 -0400 Subject: [PATCH 02/13] Kick clients when resource pack rejected (#5440) --- CONTRIBUTORS | 1 + src/ClientHandle.cpp | 13 +++++++++++++ src/ClientHandle.h | 1 + src/Protocol/Protocol_1_10.cpp | 1 + src/Protocol/Protocol_1_8.cpp | 2 ++ src/Server.cpp | 1 + src/Server.h | 4 ++++ 7 files changed, 23 insertions(+) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 314182d9e7..3c6d838e2b 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -65,6 +65,7 @@ NiLSPACE (formerly STR_Warrior) npresley0506 p-mcgowan Persson-dev +plan1231 pokechu22 ProjectBM pwnOrbitals diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 5a2e1d6206..7fc678de00 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1884,6 +1884,19 @@ void cClientHandle::HandleUseItem(bool a_UsedMainHand) +void cClientHandle::HandleResourcePack(UInt8 a_Status) +{ + // Kick player if client declined the resource pack + if ((a_Status == 1) && cRoot::Get()->GetServer()->ShouldRequireResourcePack()) + { + Kick("You must accept the resource pack"); + } +} + + + + + void cClientHandle::HandleRespawn(void) { if (m_Player->GetHealth() > 0) diff --git a/src/ClientHandle.h b/src/ClientHandle.h index c5949b57b7..a452d765af 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -377,6 +377,7 @@ class cClientHandle // tolua_export void HandlePluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message); + void HandleResourcePack (UInt8 a_Status); void HandleRespawn (void); void HandleRightClick (Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_Cursor, bool a_UsedMainHand); void HandleSlotSelected (Int16 a_SlotNum); diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp index 4f89cf6bdf..2e0eb52a79 100644 --- a/src/Protocol/Protocol_1_10.cpp +++ b/src/Protocol/Protocol_1_10.cpp @@ -341,6 +341,7 @@ cProtocol::Version cProtocol_1_10_0::GetProtocolVersion() const void cProtocol_1_10_0::HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); + m_Client->HandleResourcePack(Status); } diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index cbb13e68e4..e949d61169 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -2595,6 +2595,8 @@ void cProtocol_1_8_0::HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Hash); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); + + m_Client->HandleResourcePack(Status); } diff --git a/src/Server.cpp b/src/Server.cpp index 880ed6c727..36964d41cd 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -157,6 +157,7 @@ bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_Shoul m_MaxPlayers = static_cast(a_Settings.GetValueSetI("Server", "MaxPlayers", 100)); m_bIsHardcore = a_Settings.GetValueSetB("Server", "HardcoreEnabled", false); m_bAllowMultiLogin = a_Settings.GetValueSetB("Server", "AllowMultiLogin", false); + m_RequireResourcePack = a_Settings.GetValueSetB("Server", "RequireResourcePack", false); m_ResourcePackUrl = a_Settings.GetValueSet("Server", "ResourcePackUrl", ""); m_CustomRedirectUrl = a_Settings.GetValueSet("Server", "CustomRedirectUrl", "https://youtu.be/dQw4w9WgXcQ"); diff --git a/src/Server.h b/src/Server.h index 479fbb8651..171d68d48c 100644 --- a/src/Server.h +++ b/src/Server.h @@ -94,6 +94,9 @@ class cServer // tolua_end + /** Returns true if clients must accept resource pack. This is read from the settings. */ + bool ShouldRequireResourcePack(void) { return m_RequireResourcePack; } + const AString & GetResourcePackUrl(void) { return m_ResourcePackUrl; } std::string_view GetCustomRedirectUrl(void) { return m_CustomRedirectUrl; } @@ -223,6 +226,7 @@ class cServer AString m_FaviconData; size_t m_MaxPlayers; bool m_bIsHardcore; + bool m_RequireResourcePack; AString m_ResourcePackUrl; AString m_CustomRedirectUrl; From 3b2a501524eb4cd23e53cf5ddb04ea8a615f0460 Mon Sep 17 00:00:00 2001 From: x12xx12x <44411062+12xx12@users.noreply.github.com> Date: Fri, 28 Oct 2022 18:29:52 +0200 Subject: [PATCH 03/13] Update Core Plugin (#5453) --- Server/Plugins/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/Plugins/Core b/Server/Plugins/Core index 6d8a62087a..27185c6388 160000 --- a/Server/Plugins/Core +++ b/Server/Plugins/Core @@ -1 +1 @@ -Subproject commit 6d8a62087aae6aa9c272b137d1f1a0fcada66ce6 +Subproject commit 27185c638834da6a852bc3ea831b8229f45934f1 From 5907df680861e19091018c33979ebabe53d7ed72 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 3 Nov 2022 00:52:37 +0000 Subject: [PATCH 04/13] Chunk: Optimise idle ticking * Instead of chunks ticking player objects, and the player object in turn ticking its client handle, let the world tick the client handles. This means we no longer need to maintain a special-case for chunks that shouldn't be ticking, but still need to process players. Partially reverts to the state before 054a89dd. --- src/Chunk.cpp | 15 --------------- src/ChunkMap.cpp | 5 ++++- src/Entities/Player.cpp | 9 --------- src/World.cpp | 13 +++++++++++++ src/World.h | 3 +++ 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 4bf4557d92..c9bd1dbcff 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -684,21 +684,6 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner) void cChunk::Tick(std::chrono::milliseconds a_Dt) { - const auto ShouldTick = ShouldBeTicked(); - - // If we are not valid, tick players and bailout - if (!ShouldTick) - { - for (const auto & Entity : m_Entities) - { - if (Entity->IsPlayer()) - { - Entity->Tick(a_Dt, *this); - } - } - return; - } - TickBlocks(); // Tick all block entities in this chunk: diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 16e8fa2670..7dd7901fd5 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1347,7 +1347,10 @@ void cChunkMap::Tick(std::chrono::milliseconds a_Dt) // Do the magic of updating the world: for (auto & Chunk : m_Chunks) { - Chunk.second.Tick(a_Dt); + if (Chunk.second.ShouldBeTicked()) + { + Chunk.second.Tick(a_Dt); + } } // Finally, only after all chunks are ticked, tell the client about all aggregated changes: diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 04a7f9be0d..9f4fcb971b 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -3156,8 +3156,6 @@ void cPlayer::SpawnOn(cClientHandle & a_Client) void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { - m_ClientHandle->Tick(a_Dt); - if (m_ClientHandle->IsDestroyed()) { Destroy(); @@ -3182,13 +3180,6 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) } } - if (!a_Chunk.IsValid()) - { - // Players are ticked even if the parent chunk is invalid. - // We've processed as much as we can, bail: - return; - } - ASSERT((GetParentChunk() != nullptr) && (GetParentChunk()->IsValid())); ASSERT(a_Chunk.IsValid()); diff --git a/src/World.cpp b/src/World.cpp index 57ba656e89..1af7650e69 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1033,6 +1033,7 @@ void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_La Player->GetClientHandle()->ProcessProtocolIn(); } + TickClients(a_Dt); TickQueuedChunkDataSets(); TickQueuedBlocks(); m_ChunkMap.Tick(a_Dt); @@ -1072,6 +1073,18 @@ void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_La +void cWorld::TickClients(const std::chrono::milliseconds a_Dt) +{ + for (const auto Player : m_Players) + { + Player->GetClientHandle()->Tick(a_Dt); + } +} + + + + + void cWorld::TickWeather(float a_Dt) { UNUSED(a_Dt); diff --git a/src/World.h b/src/World.h index ea995ebdcf..b6511edf55 100644 --- a/src/World.h +++ b/src/World.h @@ -1107,6 +1107,9 @@ class cWorld // tolua_export void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec); + /** Ticks all clients that are in this world. */ + void TickClients(std::chrono::milliseconds a_Dt); + /** Handles the weather in each tick */ void TickWeather(float a_Dt); From 7a73fd467cfadfe3b3a5cf43d3eea9392f4c7f34 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 8 Nov 2022 22:14:45 +0000 Subject: [PATCH 05/13] Protocol: Use correct calculation for delta movements (#5455) * Protocol: Use correct calculation for delta movements --- src/ByteBuffer.cpp | 18 +++++++++++++++ src/ByteBuffer.h | 9 +++++++- src/Entities/Entity.cpp | 5 ++--- src/Protocol/Protocol_1_8.cpp | 41 +++++++++++++++-------------------- src/Protocol/Protocol_1_8.h | 5 ----- src/Protocol/Protocol_1_9.cpp | 16 +++++++++----- 6 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index 46f2ba0d48..8121fc3efe 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -214,6 +214,24 @@ size_t cByteBuffer::GetReadableSpace(void) const +bool cByteBuffer::CanBEInt8Represent(int a_Value) +{ + return (-128 <= a_Value) && (a_Value <= 127); +} + + + + + +bool cByteBuffer::CanBEInt16Represent(int a_Value) +{ + return (-32768 <= a_Value) && (a_Value <= 32767); +} + + + + + bool cByteBuffer::CanReadBytes(size_t a_Count) const { CHECK_THREAD diff --git a/src/ByteBuffer.h b/src/ByteBuffer.h index 1d108fca22..6648871327 100644 --- a/src/ByteBuffer.h +++ b/src/ByteBuffer.h @@ -31,6 +31,7 @@ their own synchronization. class cByteBuffer { public: + cByteBuffer(size_t a_BufferSize); ~cByteBuffer(); @@ -47,7 +48,13 @@ class cByteBuffer size_t GetReadableSpace(void) const; /** Returns the current data start index. For debugging purposes. */ - size_t GetDataStart(void) const { return m_DataStart; } + size_t GetDataStart(void) const { return m_DataStart; } + + /** Returns if the given value can fit in a protocol big-endian 8 bit integer. */ + static bool CanBEInt8Represent(int a_Value); + + /** Returns if the given value can fit in a protocol big-endian 16 bit integer. */ + static bool CanBEInt16Represent(int a_Value); /** Returns true if the specified amount of bytes are available for reading */ bool CanReadBytes(size_t a_Count) const; diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 0718da06c5..c46f9e6446 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1970,7 +1970,7 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude) return; } - if (GetSpeed().SqrLength() > 0.001) + if (m_Speed.HasNonZeroLength()) { // Movin' m_World->BroadcastEntityVelocity(*this, a_Exclude); @@ -1986,8 +1986,7 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude) m_bHasSentNoSpeed = true; } - Vector3i Diff = (GetPosition() * 32.0).Floor() - (m_LastSentPosition * 32.0).Floor(); - if (Diff.HasNonZeroLength()) // Have we moved? + if ((m_Position - m_LastSentPosition).HasNonZeroLength()) // Have we moved? { m_World->BroadcastEntityPosition(*this, a_Exclude); diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index e949d61169..d56375a8d8 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -579,12 +579,15 @@ void cProtocol_1_8_0::SendEntityPosition(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - const auto Delta = (a_Entity.GetPosition() - a_Entity.GetLastSentPosition()) * 32; + const auto Delta = (a_Entity.GetPosition() * 32).Floor() - (a_Entity.GetLastSentPosition() * 32).Floor(); - // Limitations of a byte - static const auto Max = std::numeric_limits::max(); - - if ((std::abs(Delta.x) <= Max) && (std::abs(Delta.y) <= Max) && (std::abs(Delta.z) <= Max)) + // Ensure that the delta has enough precision and is within range of a BEInt8: + if ( + Delta.HasNonZeroLength() && + cByteBuffer::CanBEInt8Represent(Delta.x) && + cByteBuffer::CanBEInt8Represent(Delta.y) && + cByteBuffer::CanBEInt8Represent(Delta.z) + ) { const auto Move = static_cast>(Delta); @@ -613,8 +616,16 @@ void cProtocol_1_8_0::SendEntityPosition(const cEntity & a_Entity) return; } - // Too big a movement, do a teleport - SendEntityTeleport(a_Entity); + // Too big or small a movement, do a teleport. + + cPacketizer Pkt(*this, pktTeleportEntity); + Pkt.WriteVarInt32(a_Entity.GetUniqueID()); + Pkt.WriteFPInt(a_Entity.GetPosX()); + Pkt.WriteFPInt(a_Entity.GetPosY()); + Pkt.WriteFPInt(a_Entity.GetPosZ()); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(a_Entity.IsOnGround()); } @@ -4202,22 +4213,6 @@ void cProtocol_1_8_0::HandlePacket(cByteBuffer & a_Buffer) -void cProtocol_1_8_0::SendEntityTeleport(const cEntity & a_Entity) -{ - cPacketizer Pkt(*this, pktTeleportEntity); - Pkt.WriteVarInt32(a_Entity.GetUniqueID()); - Pkt.WriteFPInt(a_Entity.GetPosX()); - Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteFPInt(a_Entity.GetPosZ()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(a_Entity.IsOnGround()); -} - - - - - void cProtocol_1_8_0::StartEncryption(const Byte * a_Key) { m_Encryptor.Init(a_Key, a_Key); diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index eaa8813beb..ed13399ef0 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -270,10 +270,5 @@ class cProtocol_1_8_0: /** Handle a complete packet stored in the given buffer. */ void HandlePacket(cByteBuffer & a_Buffer); - /** Sends an entity teleport packet. - Mitigates a 1.8 bug where the position in the entity spawn packet is ignored, - and so entities don't show up until a teleport is sent. */ - void SendEntityTeleport(const cEntity & a_Entity); - void StartEncryption(const Byte * a_Key); } ; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index dd2133f774..9a4bcdc4a0 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -307,12 +307,15 @@ void cProtocol_1_9_0::SendEntityPosition(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - const auto Delta = (a_Entity.GetPosition() - a_Entity.GetLastSentPosition()) * 32 * 128; + const auto Delta = (a_Entity.GetPosition() * 32 * 128).Floor() - (a_Entity.GetLastSentPosition() * 32 * 128).Floor(); - // Limitations of a short - static const auto Max = std::numeric_limits::max(); - - if ((std::abs(Delta.x) <= Max) && (std::abs(Delta.y) <= Max) && (std::abs(Delta.z) <= Max)) + // Ensure that the delta has enough precision and is within range of a BEInt16: + if ( + Delta.HasNonZeroLength() && + cByteBuffer::CanBEInt16Represent(Delta.x) && + cByteBuffer::CanBEInt16Represent(Delta.y) && + cByteBuffer::CanBEInt16Represent(Delta.z) + ) { const auto Move = static_cast>(Delta); @@ -341,7 +344,8 @@ void cProtocol_1_9_0::SendEntityPosition(const cEntity & a_Entity) return; } - // Too big a movement, do a teleport + // Too big or small a movement, do a teleport. + cPacketizer Pkt(*this, pktTeleportEntity); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEDouble(a_Entity.GetPosX()); From fd36c0493a0945d272358cbae9782119316553cc Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 9 Nov 2022 10:32:56 +0100 Subject: [PATCH 06/13] Fixed nonsensical comment. --- src/Protocol/Protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index f1d85f0144..4bcbd4f1a4 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -330,7 +330,7 @@ class cProtocol Pose }; - // TODO: these constants should be in WebServer + /** The protocol version number, received from the client in the Handshake packet. */ enum class Version { v1_8_0 = 47, From 70daa63478493b4269cf487fffec47e9ad040dce Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 9 Nov 2022 16:18:05 +0100 Subject: [PATCH 07/13] Added support for favicons of any filesize. (#5457) --- src/Protocol/ProtocolRecognizer.cpp | 29 ++++++++++++++--------------- src/Protocol/ProtocolRecognizer.h | 4 ++-- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 7dbfbda8ca..ffe839dac9 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -146,8 +146,6 @@ void cMultiVersionProtocol::HandleIncomingDataInOldPingResponseStage(cClientHand return; } - cByteBuffer OutPacketBuffer(6 KiB); - // Handle server list ping packets for (;;) { @@ -166,11 +164,11 @@ void cMultiVersionProtocol::HandleIncomingDataInOldPingResponseStage(cClientHand if ((PacketID == 0x00) && (PacketLen == 1)) // Request packet { - HandlePacketStatusRequest(a_Client, OutPacketBuffer); + HandlePacketStatusRequest(a_Client); } else if ((PacketID == 0x01) && (PacketLen == 9)) // Ping packet { - HandlePacketStatusPing(a_Client, OutPacketBuffer); + HandlePacketStatusPing(a_Client); } else { @@ -412,7 +410,7 @@ UInt32 cMultiVersionProtocol::GetPacketID(cProtocol::ePacketType a_PacketType) -void cMultiVersionProtocol::HandlePacketStatusRequest(cClientHandle & a_Client, cByteBuffer & a_Out) +void cMultiVersionProtocol::HandlePacketStatusRequest(cClientHandle & a_Client) { cServer * Server = cRoot::Get()->GetServer(); AString ServerDescription = Server->GetDescription(); @@ -445,20 +443,20 @@ void cMultiVersionProtocol::HandlePacketStatusRequest(cClientHandle & a_Client, { ResponseValue["favicon"] = Printf("data:image/png;base64,%s", Favicon.c_str()); } - AString Response = JsonUtils::WriteFastString(ResponseValue); - VERIFY(a_Out.WriteVarInt32(GetPacketID(cProtocol::ePacketType::pktStatusResponse))); - VERIFY(a_Out.WriteVarUTF8String(Response)); - - SendPacket(a_Client, a_Out); + // Send the response in a packet: + cByteBuffer out(Response.size() + 12); // String + 2x VarInt + extra space for safety + VERIFY(out.WriteVarInt32(GetPacketID(cProtocol::ePacketType::pktStatusResponse))); + VERIFY(out.WriteVarUTF8String(Response)); + SendPacket(a_Client, out); } -void cMultiVersionProtocol::HandlePacketStatusPing(cClientHandle & a_Client, cByteBuffer & a_Out) +void cMultiVersionProtocol::HandlePacketStatusPing(cClientHandle & a_Client) { Int64 Timestamp; if (!m_Buffer.ReadBEInt64(Timestamp)) @@ -466,8 +464,9 @@ void cMultiVersionProtocol::HandlePacketStatusPing(cClientHandle & a_Client, cBy return; } - VERIFY(a_Out.WriteVarInt32(GetPacketID(cProtocol::ePacketType::pktPingResponse))); - VERIFY(a_Out.WriteBEInt64(Timestamp)); - - SendPacket(a_Client, a_Out); + // Send the ping response packet: + cByteBuffer out(16); // VarInt + Int64 + extra space for safety + VERIFY(out.WriteVarInt32(GetPacketID(cProtocol::ePacketType::pktPingResponse))); + VERIFY(out.WriteBEInt64(Timestamp)); + SendPacket(a_Client, out); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 8b7848199d..4309ee8ba0 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -74,10 +74,10 @@ class cMultiVersionProtocol static UInt32 GetPacketID(cProtocol::ePacketType a_PacketType); /* Status handler for unrecognised versions. */ - void HandlePacketStatusRequest(cClientHandle & a_Client, cByteBuffer & a_Out); + void HandlePacketStatusRequest(cClientHandle & a_Client); /* Ping handler for unrecognised versions. */ - void HandlePacketStatusPing(cClientHandle & a_Client, cByteBuffer & a_Out); + void HandlePacketStatusPing(cClientHandle & a_Client); /** Buffer for received protocol data. */ cByteBuffer m_Buffer; From a7f287e572866403f1f68984f61b3a650b0e798a Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Tue, 15 Nov 2022 22:48:44 +0000 Subject: [PATCH 08/13] Remove Travis from GETTING-STARTED.md --- GETTING-STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GETTING-STARTED.md b/GETTING-STARTED.md index 016659a492..53ac9d8bab 100644 --- a/GETTING-STARTED.md +++ b/GETTING-STARTED.md @@ -117,7 +117,7 @@ Issues that should be easy to get started with are tagged as [easy][6] in GitHub Other good places to get started are: - - Cleaning up some of the compiler warnings. Check [Travis CI][7] for a list of them. + - Cleaning up some of the compiler warnings. Check [our CI][7] for a list of them. - Writing some plugins: They are written in lua, with excellent API documentation available via [APIDump][8]. The [Core plugin][9] should also help quite a bit here. Special Things @@ -131,6 +131,6 @@ Special Things [4]: https://github.com/cuberite/cuberite/blob/master/CONTRIBUTING.md [5]: https://github.com/cuberite/cuberite/blob/master/COMPILING.md [6]: https://github.com/cuberite/cuberite/issues?q=is%3Aopen+is%3Aissue+label%3Aeffort%2Feasy -[7]: https://travis-ci.org/cuberite/cuberite +[7]: https://builds.cuberite.org/job/cuberite/job/master/lastSuccessfulBuild/console [8]: https://api.cuberite.org/ [9]: https://github.com/cuberite/Core From 8a763d3bedac3eabee9c1ca022be53038ba3fc54 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 18 Nov 2022 13:28:21 +0000 Subject: [PATCH 09/13] MojangAPI: Update certificates (#5456) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * MojangAPI: Update certificates * Fixes 2115 (again). * Fixes #4832. * 🌺 --- src/Protocol/MojangAPI.cpp | 165 ++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 94 deletions(-) diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp index 6b89992166..d1914f4d30 100644 --- a/src/Protocol/MojangAPI.cpp +++ b/src/Protocol/MojangAPI.cpp @@ -43,103 +43,80 @@ const int MAX_PER_QUERY = 100; static cX509CertPtr GetCACerts(void) { static const char CertString[] = - // GeoTrust root CA cert - // Currently used for signing *.mojang.com's cert - // Exported from Mozilla Firefox's built-in CA repository + // DigiCert Global Root CA (sessionserver.mojang.com) + // Downloaded from https://www.digicert.com/kb/digicert-root-certificates.htm "-----BEGIN CERTIFICATE-----\n" - "MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n" - "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\n" - "YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG\n" - "EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg\n" - "R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9\n" - "9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq\n" - "fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv\n" - "iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU\n" - "1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+\n" - "bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW\n" - "MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA\n" - "ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l\n" - "uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn\n" - "Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS\n" - "tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF\n" - "PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un\n" - "hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV\n" - "5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==\n" - "-----END CERTIFICATE-----\n\n" - - // Equifax root CA cert - // Exported from Mozilla Firefox's built-in CA repository - "-----BEGIN CERTIFICATE-----\n" - "MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV\n" - "UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy\n" - "dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1\n" - "MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx\n" - "dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B\n" - "AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f\n" - "BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A\n" - "cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC\n" - "AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ\n" - "MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm\n" - "aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw\n" - "ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj\n" - "IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF\n" - "MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA\n" - "A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y\n" - "7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh\n" - "1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n" - "-----END CERTIFICATE-----\n\n" - - // Starfield G2 cert - // This is the data of the root certs for Starfield Technologies, the CA that used to sign sessionserver.mojang.com's cert - // Downloaded from https://certs.starfieldtech.com/repository/ + "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" + "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" + "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" + "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" + "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" + "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" + "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" + "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" + "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" + "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" + "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" + "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" + "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" + "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" + "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" + "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" + "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" + "-----END CERTIFICATE-----\n" + + // Amazon Root CA 1 (api.mojang.com) + // Downloaded from https://www.amazontrust.com/repository/ "-----BEGIN CERTIFICATE-----\n" - "MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n" - "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n" - "HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\n" - "ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw\n" - "MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n" - "b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\n" - "aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp\n" - "Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" - "ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\n" - "nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1\n" - "HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N\n" - "Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN\n" - "dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0\n" - "HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\n" - "BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G\n" - "CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU\n" - "sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3\n" - "4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n" - "8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K\n" - "pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\n" - "mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n" - "-----END CERTIFICATE-----\n\n" - - // Starfield original (G1) cert: + "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n" + "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" + "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n" + "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" + "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n" + "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n" + "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n" + "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n" + "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n" + "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n" + "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n" + "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n" + "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n" + "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n" + "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n" + "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n" + "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n" + "rqXRfboQnoZsG4q5WTP468SQvvG5\n" + "-----END CERTIFICATE-----\n" + + // AAA Certificate Services (authserver.ely.by GH#4832) + // Downloaded from https://www.tbs-certificates.co.uk/FAQ/en/Comodo_AAA_Certificate_Services.html "-----BEGIN CERTIFICATE-----\n" - "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n" - "MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n" - "U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n" - "NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n" - "ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n" - "ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n" - "DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n" - "8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n" - "+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n" - "X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n" - "K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n" - "1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n" - "A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n" - "zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n" - "YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n" - "bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n" - "DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n" - "L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n" - "eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n" - "xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n" - "VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n" - "WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n" + "MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb\n" + "MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow\n" + "GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj\n" + "YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL\n" + "MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" + "BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM\n" + "GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP\n" + "ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua\n" + "BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe\n" + "3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4\n" + "YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR\n" + "rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm\n" + "ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU\n" + "oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF\n" + "MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v\n" + "QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t\n" + "b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF\n" + "AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q\n" + "GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz\n" + "Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2\n" + "G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi\n" + "l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3\n" + "smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==\n" "-----END CERTIFICATE-----\n" ; From b0376367562d6c2c9f69d3b16b3c62bf7c353c78 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 26 Dec 2022 16:54:25 +0100 Subject: [PATCH 10/13] Changed Windows instructions to build out-of-source. --- COMPILING.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/COMPILING.md b/COMPILING.md index 030121ad46..a83257627c 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -33,7 +33,13 @@ If you're using Git to get the source, use the following command to set up the l git clone --recursive https://github.com/cuberite/cuberite.git ``` -Now that you have the source, it's time to prepare the project files for your favorite compiler. Open a command window in the folder with the source and type in `cmake .` . This will run CMake, it will auto-detect your Visual Studio version and produce the appropriate project and solution files. +Now that you have the source, it's time to prepare the project files for your favorite compiler. Open a command window in the folder with the source and type in: +``` +mkdir build +cd build +cmake .. +``` +This creates a `build` folder where the build will take place, then runs CMake, which will auto-detect your Visual Studio version and produce the appropriate project and solution files. Finally, open the newly created file, `Cuberite.sln`, in your Visual Studio. From 7fdfb8644169a25805afd32f00ced38c1c14cec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Havl=C3=AD=C4=8Dek?= <80639037+havel06@users.noreply.github.com> Date: Wed, 25 Jan 2023 21:46:34 +0100 Subject: [PATCH 11/13] Allow certain blocks to be placed on top of upside-down stairs/slabs (#5468) * Placing certain blocks on top of upside down slabs and stairs * remove TODO * fix style errors * IsAnyStairType helper function * Block placement on stairs and slabs --- src/BlockInfo.h | 1 - src/Blocks/BlockButton.h | 37 +++++++++++++++++++- src/Blocks/BlockComparator.h | 17 ++++++---- src/Blocks/BlockLever.h | 26 +++++++++++++- src/Blocks/BlockPressurePlate.h | 20 +++++++++-- src/Blocks/BlockRail.h | 30 +++++++++++++++-- src/Blocks/BlockRedstoneRepeater.h | 19 +++++++---- src/Blocks/BlockRedstoneWire.h | 20 +++++++---- src/Blocks/BlockStairs.h | 29 ++++++++++++++-- src/Blocks/BlockTorch.h | 54 ++++++++++++++++++------------ 10 files changed, 202 insertions(+), 51 deletions(-) diff --git a/src/BlockInfo.h b/src/BlockInfo.h index a15868abeb..7d2781847c 100644 --- a/src/BlockInfo.h +++ b/src/BlockInfo.h @@ -65,7 +65,6 @@ class cBlockInfo - bool IsBlockWater(BLOCKTYPE a_BlockType); bool IsBlockIce(BLOCKTYPE a_BlockType); diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h index d703d73bd4..1a141eff35 100644 --- a/src/Blocks/BlockButton.h +++ b/src/Blocks/BlockButton.h @@ -1,10 +1,15 @@ #pragma once #include "BlockHandler.h" +#include "BlockSlab.h" +#include "BlockStairs.h" #include "../BlockInfo.h" #include "../Chunk.h" +#include "Defines.h" +#include "Entities/Player.h" #include "Mixins.h" #include "ChunkInterface.h" +#include "World.h" @@ -132,7 +137,37 @@ class cBlockButtonHandler final : return false; } BLOCKTYPE SupportBlockType; - a_Chunk.UnboundedRelGetBlockType(SupportRelPos, SupportBlockType); + NIBBLETYPE SupportBlockMeta; + a_Chunk.UnboundedRelGetBlock(SupportRelPos, SupportBlockType, SupportBlockMeta); + eBlockFace Face = BlockMetaDataToBlockFace(a_Meta); + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(SupportBlockType)) + { + return (Face == BLOCK_FACE_YP) && (SupportBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); + } + + // stairs (top and sides) + if (cBlockStairsHandler::IsAnyStairType(SupportBlockType)) + { + switch (Face) + { + case eBlockFace::BLOCK_FACE_YP: + return (SupportBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_XP: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_XP); + case eBlockFace::BLOCK_FACE_XM: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_XM); + case eBlockFace::BLOCK_FACE_ZP: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_ZP); + case eBlockFace::BLOCK_FACE_ZM: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_ZM); + default: + { + return false; + } + } + } return cBlockInfo::FullyOccupiesVoxel(SupportBlockType); } diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h index e58b386c34..18aa2a8b90 100644 --- a/src/Blocks/BlockComparator.h +++ b/src/Blocks/BlockComparator.h @@ -167,14 +167,19 @@ class cBlockComparatorHandler final : { return true; } - else if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) { - // Check if the slab is turned up side down - if ((BelowBlockMeta & 0x08) == 0x08) - { - return true; - } + return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(BelowBlock)) + { + return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; + } + return false; } diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h index bf6f911a11..60db4ddee7 100644 --- a/src/Blocks/BlockLever.h +++ b/src/Blocks/BlockLever.h @@ -2,6 +2,9 @@ #include "BlockHandler.h" #include "../Chunk.h" +#include "Blocks/BlockStairs.h" +#include "ChunkDef.h" +#include "Defines.h" #include "Mixins.h" #include "BlockSlab.h" @@ -117,7 +120,28 @@ class cBlockLeverHandler final : (((NeighborMeta & 0x08) == 0) && (NeighborFace == BLOCK_FACE_BOTTOM)) ); } - + else if (cBlockStairsHandler::IsAnyStairType(NeighborBlockType)) + { + switch (NeighborFace) + { + case eBlockFace::BLOCK_FACE_YM: + return !(NeighborMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_YP: + return (NeighborMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_XP: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_XP); + case eBlockFace::BLOCK_FACE_XM: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_XM); + case eBlockFace::BLOCK_FACE_ZP: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_ZP); + case eBlockFace::BLOCK_FACE_ZM: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_ZM); + default: + { + return false; + } + } + } return false; } diff --git a/src/Blocks/BlockPressurePlate.h b/src/Blocks/BlockPressurePlate.h index d2f05b2e7f..6d852bfc05 100644 --- a/src/Blocks/BlockPressurePlate.h +++ b/src/Blocks/BlockPressurePlate.h @@ -2,6 +2,9 @@ #pragma once #include "BlockHandler.h" +#include "BlockSlab.h" +#include "../Chunk.h" +#include "BlockStairs.h" @@ -24,9 +27,22 @@ class cBlockPressurePlateHandler final : return false; } - // TODO: check if the block is upside-down slab or upside-down stairs + BLOCKTYPE Block; + NIBBLETYPE BlockMeta; + a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), Block, BlockMeta); + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(Block)) + { + return BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; + } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(Block)) + { + return BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; + } - const auto Block = a_Chunk.GetBlock(a_Position.addedY(-1)); switch (Block) { case E_BLOCK_ACACIA_FENCE: diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index 6c43673345..4e2e6211fc 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -1,6 +1,14 @@ - #pragma once +#include "BlockHandler.h" +#include "BlockSlab.h" +#include "BlockStairs.h" +#include "BlockType.h" +#include "Blocks/Mixins.h" +#include "../BlockInfo.h" +#include "../Chunk.h" +#include "ChunkDef.h" + @@ -154,9 +162,26 @@ class cBlockRailHandler final : private: + static bool CanBeSupportedBy(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) + { + if (cBlockSlabHandler::IsAnySlabType(a_BlockType)) + { + return (a_BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); + } + else if (cBlockStairsHandler::IsAnyStairType(a_BlockType)) + { + return (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + } + return cBlockInfo::FullyOccupiesVoxel(a_BlockType); + } + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta) const override { - if ((a_Position.y <= 0) || !cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_Position.addedY(-1)))) + BLOCKTYPE BelowBlock; + NIBBLETYPE BelowBlockMeta; + a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta); + + if ((a_Position.y <= 0) || !CanBeSupportedBy(BelowBlock, BelowBlockMeta)) { return false; } @@ -187,6 +212,7 @@ class cBlockRailHandler final : return cBlockInfo::FullyOccupiesVoxel(BlockType); } } + return true; } diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h index 4b9650e90b..893691d7bc 100644 --- a/src/Blocks/BlockRedstoneRepeater.h +++ b/src/Blocks/BlockRedstoneRepeater.h @@ -2,9 +2,11 @@ #pragma once #include "BlockHandler.h" +#include "BlockType.h" #include "Mixins.h" #include "ChunkInterface.h" #include "BlockSlab.h" +#include "BlockStairs.h" #include "../Chunk.h" @@ -120,14 +122,19 @@ class cBlockRedstoneRepeaterHandler final : { return true; } - else if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) { - // Check if the slab is turned up side down - if ((BelowBlockMeta & 0x08) == 0x08) - { - return true; - } + return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(BelowBlock)) + { + return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; + } + return false; } diff --git a/src/Blocks/BlockRedstoneWire.h b/src/Blocks/BlockRedstoneWire.h index 3976afa906..de8e59a402 100644 --- a/src/Blocks/BlockRedstoneWire.h +++ b/src/Blocks/BlockRedstoneWire.h @@ -3,7 +3,8 @@ #include "BlockHandler.h" #include "BlockSlab.h" - +#include "BlockStairs.h" +#include "../Chunk.h" @@ -34,14 +35,19 @@ class cBlockRedstoneWireHandler final : { return true; } - else if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + { + return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; + } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(BelowBlock)) { - // Check if the slab is turned up side down - if ((BelowBlockMeta & 0x08) == 0x08) - { - return true; - } + return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; } + return false; } diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h index 55a9e877ef..76614bb620 100644 --- a/src/Blocks/BlockStairs.h +++ b/src/Blocks/BlockStairs.h @@ -16,6 +16,32 @@ class cBlockStairsHandler final : using Super::Super; + static bool IsAnyStairType(BLOCKTYPE a_Block) + { + switch (a_Block) + { + case E_BLOCK_SANDSTONE_STAIRS: + case E_BLOCK_BIRCH_WOOD_STAIRS: + case E_BLOCK_QUARTZ_STAIRS: + case E_BLOCK_JUNGLE_WOOD_STAIRS: + case E_BLOCK_RED_SANDSTONE_STAIRS: + case E_BLOCK_COBBLESTONE_STAIRS: + case E_BLOCK_STONE_BRICK_STAIRS: + case E_BLOCK_OAK_WOOD_STAIRS: + case E_BLOCK_ACACIA_WOOD_STAIRS: + case E_BLOCK_PURPUR_STAIRS: + case E_BLOCK_DARK_OAK_WOOD_STAIRS: + case E_BLOCK_BRICK_STAIRS: + case E_BLOCK_NETHER_BRICK_STAIRS: + case E_BLOCK_SPRUCE_WOOD_STAIRS: + return true; + default: + { + return false; + } + } + } + private: virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override @@ -25,9 +51,6 @@ class cBlockStairsHandler final : } - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h index 0b96ad2464..ad69cf5eb6 100644 --- a/src/Blocks/BlockTorch.h +++ b/src/Blocks/BlockTorch.h @@ -1,8 +1,12 @@ #pragma once #include "BlockHandler.h" +#include "BlockSlab.h" +#include "BlockStairs.h" #include "../Chunk.h" +#include "BlockType.h" #include "ChunkInterface.h" +#include "Defines.h" #include "Mixins.h" @@ -22,6 +26,34 @@ class cBlockTorchBaseHandler : /** Returns true if the torch can be placed on the specified block's face. */ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace) { + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(a_BlockType)) + { + return (a_BlockFace == BLOCK_FACE_YP) && (a_BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); + } + + // stairs (top and sides) + if (cBlockStairsHandler::IsAnyStairType(a_BlockType)) + { + switch (a_BlockFace) + { + case eBlockFace::BLOCK_FACE_YP: + return (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_XP: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_XP); + case eBlockFace::BLOCK_FACE_XM: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_XM); + case eBlockFace::BLOCK_FACE_ZP: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_ZP); + case eBlockFace::BLOCK_FACE_ZM: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_ZM); + default: + { + return false; + } + } + } + switch (a_BlockType) { case E_BLOCK_END_PORTAL_FRAME: @@ -44,28 +76,6 @@ class cBlockTorchBaseHandler : // Torches can only be placed on top of these blocks return (a_BlockFace == BLOCK_FACE_YP); } - case E_BLOCK_STONE_SLAB: - case E_BLOCK_WOODEN_SLAB: - { - // Toches can be placed only on the top of top-half-slabs - return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08)); - } - case E_BLOCK_OAK_WOOD_STAIRS: - case E_BLOCK_COBBLESTONE_STAIRS: - case E_BLOCK_BRICK_STAIRS: - case E_BLOCK_STONE_BRICK_STAIRS: - case E_BLOCK_NETHER_BRICK_STAIRS: - case E_BLOCK_SANDSTONE_STAIRS: - case E_BLOCK_SPRUCE_WOOD_STAIRS: - case E_BLOCK_BIRCH_WOOD_STAIRS: - case E_BLOCK_JUNGLE_WOOD_STAIRS: - case E_BLOCK_QUARTZ_STAIRS: - case E_BLOCK_ACACIA_WOOD_STAIRS: - case E_BLOCK_DARK_OAK_WOOD_STAIRS: - case E_BLOCK_RED_SANDSTONE_STAIRS: - { - return (a_BlockFace == BLOCK_FACE_TOP) && (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); - } default: { if (cBlockInfo::FullyOccupiesVoxel(a_BlockType)) From 847884b6a803650903b871054adcde19921af8b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Havl=C3=AD=C4=8Dek?= <80639037+havel06@users.noreply.github.com> Date: Wed, 25 Jan 2023 21:50:08 +0100 Subject: [PATCH 12/13] TNT minecarts exploding when riding over activator rails (#5469) * TNT Minecarts exploding via activator rails * Fuse animation * Add TNT minecart explosion source to APIDesc --- Server/Plugins/APIDump/APIDesc.lua | 4 +++ src/Bindings/PluginLua.cpp | 4 +++ src/Defines.h | 1 + src/Entities/Minecart.cpp | 48 ++++++++++++++++++++++++++++-- src/Entities/Minecart.h | 9 ++++-- src/World.cpp | 1 + 6 files changed, 62 insertions(+), 5 deletions(-) diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index f920a8f5bf..a5f9679153 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -17949,6 +17949,10 @@ end { Notes = "A TNT explosion. The SourceData param is the {{cTNTEntity|TNT entity}} object.", }, + esTNTMinecart = + { + Notes = "A TNT minecart explosion. The SourceData param is the {{cMinecartWithTNT|Minecart with TNT entity}} object.", + }, esWitherBirth = { Notes = "An explosion at a wither's birth. The SourceData param is the {{cMonster|wither entity}} object.", diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index 69a8626c1c..caa02acf91 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -4,6 +4,8 @@ // Implements the cPluginLua class representing a plugin written in Lua #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules +#include "Defines.h" +#include "Entities/Minecart.h" #ifdef __APPLE__ #define LUA_USE_MACOSX @@ -431,6 +433,7 @@ bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_Can case esOther: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res); break; case esPlugin: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res); break; case esPrimedTNT: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; + case esTNTMinecart: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esWitherBirth: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esWitherSkull: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esMax: @@ -471,6 +474,7 @@ bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool & case esOther: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esPlugin: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esPrimedTNT: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; + case esTNTMinecart: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esWitherBirth: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esWitherSkull: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esMax: diff --git a/src/Defines.h b/src/Defines.h index bbe5d3d3df..ab0a639c49 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -314,6 +314,7 @@ enum eExplosionSource esOther, esPlugin, esPrimedTNT, + esTNTMinecart, esWitherBirth, esWitherSkull, esMax, diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 50be91e4e3..d8dbc10c19 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -6,6 +6,8 @@ // Indiana Jones! #include "Globals.h" +#include "ChunkDef.h" +#include "Defines.h" #include "Minecart.h" #include "../BlockInfo.h" #include "../ClientHandle.h" @@ -223,7 +225,7 @@ void cMinecart::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) switch (InsideType) { case E_BLOCK_RAIL: HandleRailPhysics(InsideMeta, a_Dt); break; - case E_BLOCK_ACTIVATOR_RAIL: break; + case E_BLOCK_ACTIVATOR_RAIL: HandleActivatorRailPhysics(InsideMeta, a_Dt); break; case E_BLOCK_POWERED_RAIL: HandlePoweredRailPhysics(InsideMeta); break; case E_BLOCK_DETECTOR_RAIL: { @@ -678,6 +680,7 @@ void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::mi void cMinecart::HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) { HandleRailPhysics(a_RailMeta & 0x07, a_Dt); + // TODO - shake minecart, throw entities out } @@ -1516,7 +1519,22 @@ cMinecartWithTNT::cMinecartWithTNT(Vector3d a_Pos): { } -// TODO: Make it activate when passing over activator rail + + + + +void cMinecartWithTNT::HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) +{ + Super::HandleActivatorRailPhysics(a_RailMeta, a_Dt); + + if ((a_RailMeta & 0x08) && !m_isTNTFused) + { + m_isTNTFused = true; + m_TNTFuseTicksLeft = 80; + m_World->BroadcastSoundEffect("entity.tnt.primed", GetPosition(), 1.0f, 1.0f); + m_World->BroadcastEntityAnimation(*this, EntityAnimation::MinecartTNTIgnites); + } +} @@ -1531,6 +1549,32 @@ void cMinecartWithTNT::GetDrops(cItems & a_Drops, cEntity * a_Killer) +void cMinecartWithTNT::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +{ + Super::Tick(a_Dt, a_Chunk); + if (!IsTicking()) + { + return; + } + + if (m_isTNTFused) + { + if (m_TNTFuseTicksLeft > 0) + { + --m_TNTFuseTicksLeft; + } + else + { + Destroy(); + m_World->DoExplosionAt(4.0, GetPosX(), GetPosY() + GetHeight() / 2, GetPosZ(), true, esTNTMinecart, this); + } + } +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cMinecartWithHopper: diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h index 0d62d98f1d..0e63363307 100644 --- a/src/Entities/Minecart.h +++ b/src/Entities/Minecart.h @@ -72,8 +72,8 @@ class cMinecart : */ void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt); - /** Handles activator rails - placeholder for future implementation */ - void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt); + /** Handles activator rails */ + virtual void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt); /** Snaps a mincecart to a rail's axis, resetting its speed For curved rails, it changes the cart's direction as well as snapping it to axis */ @@ -89,7 +89,6 @@ class cMinecart : /** Tests if this mincecart's bounding box is intersecting another entity's bounding box (collision) and pushes mincecart away if necessary */ bool TestEntityCollision(NIBBLETYPE a_RailMeta); - } ; @@ -222,10 +221,14 @@ class cMinecartWithTNT final : CLASS_PROTODEF(cMinecartWithTNT) cMinecartWithTNT(Vector3d a_Pos); + void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; private: + int m_TNTFuseTicksLeft; + bool m_isTNTFused = false; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) override; } ; diff --git a/src/World.cpp b/src/World.cpp index 1af7650e69..133458a8c2 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1395,6 +1395,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo case eExplosionSource::esGhastFireball: case eExplosionSource::esMonster: case eExplosionSource::esPrimedTNT: + case eExplosionSource::esTNTMinecart: case eExplosionSource::esWitherBirth: case eExplosionSource::esWitherSkull: { From cb2201dabac8883b726b2dc83511d596cbb50f9c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 8 Mar 2023 09:23:42 +0100 Subject: [PATCH 13/13] Added small embedded devices to README A nonsense change pretty much only to trigger a rebuild due to missing binaries on the build server. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 34f3320df3..18000a2042 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Cuberite is a Minecraft-compatible multiplayer game server that is written in C++ and designed to be efficient with memory and CPU, as well as having a flexible Lua Plugin API. Cuberite is compatible with the Java Edition Minecraft client. -Cuberite runs on Windows, *nix and Android operating systems. This includes Android phones and tablets as well as Raspberry Pis. +Cuberite runs on Windows, *nix and Android operating systems. This includes Android phones and tablets as well as Raspberry Pis; support for small embedded devices is experimental. Currently we support Release 1.8 - 1.12.2 Minecraft protocol versions.