From 8028a8bbc6b625da265791dc6a0628e215f2b643 Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 10 Feb 2014 11:22:15 -0500 Subject: [PATCH 001/106] Typo Fix in console.lua --- MCServer/Plugins/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core index 7f97e93ef..5fe3662a8 160000 --- a/MCServer/Plugins/Core +++ b/MCServer/Plugins/Core @@ -1 +1 @@ -Subproject commit 7f97e93ef25616673e8342b7919d9b5914e1327e +Subproject commit 5fe3662a8719f79cb2ca0a16150c716a3c5eb19c From e8e76a6058988cb0cff222579049fb6aa3cdb9c1 Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 10 Feb 2014 20:00:07 -0500 Subject: [PATCH 002/106] Fixed bug #385. UnloadUnusedChunks now has the same interface as SaveAllChunks. Meaning, QueueUnloadUnusedChunks and the supporting cTaskUnloadUnusedChunks has been added. Use QueueUnloadUnusedChunks from now on to prevent deadlocking. --- lib/polarssl | 2 +- src/World.cpp | 10 ++++++++++ src/World.h | 16 +++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/polarssl b/lib/polarssl index 2cb1a0c40..2ceda5798 160000 --- a/lib/polarssl +++ b/lib/polarssl @@ -1 +1 @@ -Subproject commit 2cb1a0c4009ecf368ecc74eb428394e10f9e6d00 +Subproject commit 2ceda579893ceb23c5eb0d56df47dc235644e0f4 diff --git a/src/World.cpp b/src/World.cpp index 662a9a4b8..9120f8d7d 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2213,6 +2213,10 @@ void cWorld::UnloadUnusedChunks(void) } +void cWorld::QueueUnloadUnusedChunks(void) +{ + QueueTask(new cWorld::cTaskUnloadUnusedChunks); +} @@ -2966,7 +2970,13 @@ void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World) } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cWorld::cTaskUnloadUnusedChunks +void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World) +{ + a_World.UnloadUnusedChunks(); +} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/World.h b/src/World.h index 0174be03b..e4036d8df 100644 --- a/src/World.h +++ b/src/World.h @@ -99,6 +99,15 @@ public: } ; + class cTaskUnloadUnusedChunks : + public cTask + { + protected: + // cTask overrides: + virtual void Run(cWorld & a_World) override; + }; + + static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates { return "cWorld"; @@ -243,7 +252,12 @@ public: bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const; bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const; - void UnloadUnusedChunks(void); // tolua_export + + /*Unloads all chunks immediately. Dangerous interface, may deadlock, use QueueUnloadUnusedChunks() instead*/ + void UnloadUnusedChunks(void); + + /*Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/ + void QueueUnloadUnusedChunks(void); // tolua_export void CollectPickupsByPlayer(cPlayer * a_Player); From d7f32ed682b19cded6c54f14e4e46792695399a7 Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 08:01:25 -0500 Subject: [PATCH 003/106] Fixed formatting of previous commit. --- src/World.cpp | 5 +++++ src/World.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/World.cpp b/src/World.cpp index 9120f8d7d..ad2a58e01 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2213,6 +2213,9 @@ void cWorld::UnloadUnusedChunks(void) } + + + void cWorld::QueueUnloadUnusedChunks(void) { QueueTask(new cWorld::cTaskUnloadUnusedChunks); @@ -2220,6 +2223,8 @@ void cWorld::QueueUnloadUnusedChunks(void) + + void cWorld::CollectPickupsByPlayer(cPlayer * a_Player) { m_ChunkMap->CollectPickupsByPlayer(a_Player); diff --git a/src/World.h b/src/World.h index e4036d8df..5161c7fd6 100644 --- a/src/World.h +++ b/src/World.h @@ -253,10 +253,10 @@ public: bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const; - /*Unloads all chunks immediately. Dangerous interface, may deadlock, use QueueUnloadUnusedChunks() instead*/ + /** Unloads all chunks immediately. Dangerous interface, may deadlock, use QueueUnloadUnusedChunks() instead*/ void UnloadUnusedChunks(void); - /*Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/ + /** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/ void QueueUnloadUnusedChunks(void); // tolua_export void CollectPickupsByPlayer(cPlayer * a_Player); From 803314b9407c41106b06f59f16a83bf2484d3793 Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 10:19:18 -0500 Subject: [PATCH 004/106] Updated APIDesc.lua to replace 'UnloadUnusedChunks' with 'QueueUnloadUnusedChunks'. --- MCServer/Plugins/APIDump/APIDesc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index c0056ac4a..3b34ec6b9 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2145,7 +2145,7 @@ end SpawnExperienceOrb = { Params = "X, Y, Z, Reward", Return = "EntityID", Notes = "Spawns an {{cExpOrb|experience orb}} at the specified coords, with the given reward" }, SpawnPrimedTNT = { Params = "X, Y, Z, FuseTimeSecs, InitialVelocityCoeff", Return = "", Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse time. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value." }, TryGetHeight = { Params = "BlockX, BlockZ", Return = "IsValid, Height", Notes = "Returns true and height of the highest non-air block if the chunk is loaded, or false otherwise." }, - UnloadUnusedChunks = { Params = "", Return = "", Notes = "Unloads chunks that are no longer needed, and are saved. NOTE: This API is deprecated and will be removed soon." }, + QueueUnloadUnusedChunks = { Params = "", Return = "", Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved." }, UpdateSign = { Params = "X, Y, Z, Line1, Line2, Line3, Line4, [{{cPlayer|Player}}]", Return = "", Notes = "Sets the sign text at the specified coords. The sign-updating hooks are called for the change. The Player parameter is used to indicate the player from whom the change has come, it may be nil. Same as SetSignLiens()" }, UseBlockEntity = { Params = "{{cPlayer|Player}}, BlockX, BlockY, BlockZ", Return = "", Notes = "Makes the specified Player use the block entity at the specified coords (open chest UI, etc.) If the cords are in an unloaded chunk or there's no block entity, ignores the call." }, WakeUpSimulators = { Params = "BlockX, BlockY, BlockZ", Return = "", Notes = "Wakes up the simulators for the specified block." }, From 619c3438ef2e70b4e116ab8ecd1edde8fb9b4896 Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 10:35:25 -0500 Subject: [PATCH 005/106] Changed console.lua in core plugin. --- MCServer/Plugins/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core index 5fe3662a8..51aa4290d 160000 --- a/MCServer/Plugins/Core +++ b/MCServer/Plugins/Core @@ -1 +1 @@ -Subproject commit 5fe3662a8719f79cb2ca0a16150c716a3c5eb19c +Subproject commit 51aa4290d7cef2aff68a35c66339535d9068f79b From 03dbfce10e3bc6f6e5d093fd6591f0a650636848 Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 14:11:20 -0500 Subject: [PATCH 006/106] Alpha-Sorted List. --- MCServer/Plugins/APIDump/APIDesc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 3b34ec6b9..c9ef02a96 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -1851,6 +1851,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage); GetWebAdmin = { Params = "", Return = "{{cWebAdmin|cWebAdmin}}", Notes = "Returns the cWebAdmin object." }, GetWorld = { Params = "WorldName", Return = "{{cWorld|cWorld}}", Notes = "Returns the cWorld object of the given world. It returns nil if there is no world with the given name." }, QueueExecuteConsoleCommand = { Params = "Message", Return = "", Notes = "Queues a console command for execution through the cServer class. The command will be executed in the tick thread. The command's output will be sent to console." }, + QueueUnloadUnusedChunks = { Params = "", Return = "", Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved." }, SaveAllChunks = { Params = "", Return = "", Notes = "Saves all the chunks in all the worlds. Note that the saving is queued on each world's tick thread and this functions returns before the chunks are actually saved." }, SetPrimaryServerVersion = { Params = "Protocol Version", Return = "", Notes = "Sets the servers PrimaryServerVersion to the given protocol number." } }, @@ -2145,7 +2146,6 @@ end SpawnExperienceOrb = { Params = "X, Y, Z, Reward", Return = "EntityID", Notes = "Spawns an {{cExpOrb|experience orb}} at the specified coords, with the given reward" }, SpawnPrimedTNT = { Params = "X, Y, Z, FuseTimeSecs, InitialVelocityCoeff", Return = "", Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse time. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value." }, TryGetHeight = { Params = "BlockX, BlockZ", Return = "IsValid, Height", Notes = "Returns true and height of the highest non-air block if the chunk is loaded, or false otherwise." }, - QueueUnloadUnusedChunks = { Params = "", Return = "", Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved." }, UpdateSign = { Params = "X, Y, Z, Line1, Line2, Line3, Line4, [{{cPlayer|Player}}]", Return = "", Notes = "Sets the sign text at the specified coords. The sign-updating hooks are called for the change. The Player parameter is used to indicate the player from whom the change has come, it may be nil. Same as SetSignLiens()" }, UseBlockEntity = { Params = "{{cPlayer|Player}}, BlockX, BlockY, BlockZ", Return = "", Notes = "Makes the specified Player use the block entity at the specified coords (open chest UI, etc.) If the cords are in an unloaded chunk or there's no block entity, ignores the call." }, WakeUpSimulators = { Params = "BlockX, BlockY, BlockZ", Return = "", Notes = "Wakes up the simulators for the specified block." }, From e53b331b4a17234c89f0ac54e724a5f48de4c4be Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 14:38:28 -0500 Subject: [PATCH 007/106] Fixed formatting. Moved UnloadUnusedChunks from public to private. --- src/World.cpp | 7 +++++++ src/World.h | 7 +++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/World.cpp b/src/World.cpp index ad2a58e01..6090443a8 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2966,6 +2966,7 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cWorld::cTaskSaveAllChunks: @@ -2975,6 +2976,9 @@ void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World) } + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cWorld::cTaskUnloadUnusedChunks @@ -2984,6 +2988,9 @@ void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World) } + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cWorld::cChunkGeneratorCallbacks: diff --git a/src/World.h b/src/World.h index 5161c7fd6..f22a8f49c 100644 --- a/src/World.h +++ b/src/World.h @@ -252,10 +252,6 @@ public: bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const; bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const; - - /** Unloads all chunks immediately. Dangerous interface, may deadlock, use QueueUnloadUnusedChunks() instead*/ - void UnloadUnusedChunks(void); - /** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/ void QueueUnloadUnusedChunks(void); // tolua_export @@ -882,6 +878,9 @@ private: /** Ticks all clients that are in this world */ void TickClients(float a_Dt); + /** Unloads all chunks immediately.*/ + void UnloadUnusedChunks(void); + void UpdateSkyDarkness(void); /** Generates a random spawnpoint on solid land by walking chunks and finding their biomes */ From c53406f0d4d83f795e2a445059952b61abb12f34 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 22:04:11 +0000 Subject: [PATCH 008/106] Fixed #612 * Chests send contents updates to client --- src/BlockEntities/ChestEntity.cpp | 15 +++++++++++++++ src/BlockEntities/ChestEntity.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp index dfbe6ae87..9282da7fd 100644 --- a/src/BlockEntities/ChestEntity.cpp +++ b/src/BlockEntities/ChestEntity.cpp @@ -170,3 +170,18 @@ void cChestEntity::OpenNewWindow(void) + +void cChestEntity::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) +{ + super::OnSlotChanged(a_Grid, a_SlotNum); + + cWindow * Window = GetWindow(); + if (Window != NULL) + { + Window->BroadcastWholeWindow(); + } +} + + + + diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h index 4110de1f3..1f5668f78 100644 --- a/src/BlockEntities/ChestEntity.h +++ b/src/BlockEntities/ChestEntity.h @@ -49,6 +49,7 @@ public: virtual void SaveToJson(Json::Value & a_Value) override; virtual void SendTo(cClientHandle & a_Client) override; virtual void UsedBy(cPlayer * a_Player) override; + virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override; /// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate. void OpenNewWindow(void); From 06239c8336a340459a62b45b6d633a55058e4677 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 22:09:56 +0000 Subject: [PATCH 009/106] Fixed #627 - Attack() is now called from cAggressive instead of cMonster * Monsters can no longer attack through walls * Should fix last remnants of player damage after teleporting (that both STR and bearbin contributed fixes to :P) --- src/Entities/Player.cpp | 4 ++-- src/Mobs/AggressiveMonster.cpp | 11 +++++++++-- src/Mobs/AggressiveMonster.h | 2 +- src/Mobs/Monster.cpp | 14 -------------- src/Mobs/Monster.h | 2 -- 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 286d43cf6..5f2379ba2 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1122,8 +1122,8 @@ void cPlayer::SetIP(const AString & a_IP) void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) { - SetPosition( a_PosX, a_PosY, a_PosZ ); - m_LastGroundHeight = (float)a_PosY; + SetPosition(a_PosX, a_PosY, a_PosZ); + m_LastGroundHeight, m_LastJumpHeight = (float)a_PosY; m_World->BroadcastTeleportEntity(*this, GetClientHandle()); m_ClientHandle->SendPlayerMoveLook(); diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp index f2f0c404c..7da9f4fc2 100644 --- a/src/Mobs/AggressiveMonster.cpp +++ b/src/Mobs/AggressiveMonster.cpp @@ -5,7 +5,7 @@ #include "../World.h" #include "../Entities/Player.h" -#include "../MersenneTwister.h" +#include "../Tracer.h" @@ -73,6 +73,13 @@ void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) { CheckEventSeePlayer(); } + + cTracer LineOfSight(GetWorld()); + if (ReachedFinalDestination() && (m_Target != NULL) && !LineOfSight.Trace(GetPosition(), (m_Target->GetPosition() - GetPosition()), (int)(m_Target->GetPosition() - GetPosition()).Length())) + { + // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) + Attack(a_Dt / 1000); + } } @@ -81,7 +88,7 @@ void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) void cAggressiveMonster::Attack(float a_Dt) { - super::Attack(a_Dt); + m_AttackInterval += a_Dt * m_AttackRate; if ((m_Target != NULL) && (m_AttackInterval > 3.0)) { diff --git a/src/Mobs/AggressiveMonster.h b/src/Mobs/AggressiveMonster.h index 9cee4e7a7..152260f95 100644 --- a/src/Mobs/AggressiveMonster.h +++ b/src/Mobs/AggressiveMonster.h @@ -20,7 +20,7 @@ public: virtual void InStateChasing(float a_Dt) override; virtual void EventSeePlayer(cEntity *) override; - virtual void Attack(float a_Dt) override; + virtual void Attack(float a_Dt); } ; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index ad3a87725..9817901c9 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -311,9 +311,6 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) } } - if (ReachedFinalDestination() && (m_Target != NULL)) - Attack(a_Dt); - SetPitchAndYawFromDestination(); HandleFalling(); @@ -657,17 +654,6 @@ void cMonster::InStateEscaping(float a_Dt) -// Do attack here -// a_Dt is passed so we can set attack rate -void cMonster::Attack(float a_Dt) -{ - m_AttackInterval += a_Dt * m_AttackRate; -} - - - - - void cMonster::GetMonsterConfig(const AString & a_Name) { cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name); diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index 714feddb9..4d2e099c5 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -112,8 +112,6 @@ public: virtual void InStateChasing (float a_Dt); virtual void InStateEscaping(float a_Dt); - virtual void Attack(float a_Dt); - int GetAttackRate() { return (int)m_AttackRate; } void SetAttackRate(float a_AttackRate) { m_AttackRate = a_AttackRate; } void SetAttackRange(int a_AttackRange) { m_AttackRange = a_AttackRange; } From 9d54f2b761370afb04ebb49e0920de460f269efd Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 22:54:01 +0000 Subject: [PATCH 010/106] Fixed #190 + Hoppers now collect pickups above them --- src/BlockEntities/HopperEntity.cpp | 69 +++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index 2255cad64..2d07ce6c7 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -7,10 +7,12 @@ #include "HopperEntity.h" #include "../Chunk.h" #include "../Entities/Player.h" +#include "../Entities/Pickup.h" #include "../Bindings/PluginManager.h" #include "ChestEntity.h" #include "DropSpenserEntity.h" #include "FurnaceEntity.h" +#include "../BoundingBox.h" @@ -190,8 +192,71 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick) /// Moves pickups from above this hopper into it. Returns true if the contents have changed. bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) { - // TODO - return false; + UNUSED(a_CurrentTick); + + class cHopperPickupSearchCallback : + public cEntityCallback + { + public: + cHopperPickupSearchCallback(Vector3i a_Pos, cItemGrid & a_Contents) : + m_Pos(a_Pos), + m_Contents(a_Contents), + m_bFoundPickupsAbove(false) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + ASSERT(a_Entity != NULL); + + if (!a_Entity->IsPickup() || a_Entity->IsDestroyed()) + { + return false; + } + + Vector3f EntityPos = a_Entity->GetPosition(); + Vector3f BlockPos(m_Pos.x + 0.5f, (float)m_Pos.y + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards + float Distance = (EntityPos - BlockPos).Length(); + + if (Distance < 0.5) + { + for (int i = 0; i < ContentsWidth * ContentsHeight; i++) + { + if (m_Contents.IsSlotEmpty(i)) + { + m_bFoundPickupsAbove = true; + m_Contents.SetSlot(i, ((cPickup *)a_Entity)->GetItem()); + a_Entity->Destroy(); // Kill pickup + return false; // Don't break enumeration + } + else if (m_Contents.GetSlot(i).IsEqual(((cPickup *)a_Entity)->GetItem())) + { + m_bFoundPickupsAbove = true; + m_Contents.ChangeSlotCount(i, ((cPickup *)a_Entity)->GetItem().m_ItemCount); + a_Entity->Destroy(); + return false; + } + } + } + + return false; + } + + bool FoundPickupsAbove(void) const + { + return m_bFoundPickupsAbove; + } + + protected: + Vector3i m_Pos; + bool m_bFoundPickupsAbove; + cItemGrid & m_Contents; + }; + + cHopperPickupSearchCallback HopperPickupSearchCallback(Vector3i(GetPosX(), GetPosY(), GetPosZ()), m_Contents); + a_Chunk.ForEachEntity(HopperPickupSearchCallback); + + return HopperPickupSearchCallback.FoundPickupsAbove(); } From a0a44b969ece88d32bcc89fea51b25d819424a06 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 23:13:49 +0000 Subject: [PATCH 011/106] Improved pressure plates + Two (or more) pressure plates can be triggered at the same time * Fixed issues caused by pressure plates not being in the sources list --- src/Simulator/IncrementalRedstoneSimulator.cpp | 2 +- src/Simulator/IncrementalRedstoneSimulator.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 5dba69455..a875c9e4d 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -960,7 +960,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); float Distance = (EntityPos - BlockPos).Length(); - if (Distance < 0.5) + if (Distance <= 0.7) { m_Entity = a_Entity; return true; // Break out, we only need to know for wooden plates that at least one entity is on top diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 3397e143c..a3da13584 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -207,6 +207,10 @@ private: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_ACTIVE_COMPARATOR: + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_STONE_PRESSURE_PLATE: + case E_BLOCK_WOODEN_PRESSURE_PLATE: { return true; } From 2f11e145e55dcde0c8bde19b9c324764b81f4d2e Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 19:58:40 -0500 Subject: [PATCH 012/106] Fixed location of QueueUnloadUnusedChunks entry in APIDesc dump. Now is lexographically listed in cWorld, not cRoot. --- MCServer/Plugins/APIDump/APIDesc.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index c9ef02a96..565b32b1b 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -1851,7 +1851,6 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage); GetWebAdmin = { Params = "", Return = "{{cWebAdmin|cWebAdmin}}", Notes = "Returns the cWebAdmin object." }, GetWorld = { Params = "WorldName", Return = "{{cWorld|cWorld}}", Notes = "Returns the cWorld object of the given world. It returns nil if there is no world with the given name." }, QueueExecuteConsoleCommand = { Params = "Message", Return = "", Notes = "Queues a console command for execution through the cServer class. The command will be executed in the tick thread. The command's output will be sent to console." }, - QueueUnloadUnusedChunks = { Params = "", Return = "", Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved." }, SaveAllChunks = { Params = "", Return = "", Notes = "Saves all the chunks in all the worlds. Note that the saving is queued on each world's tick thread and this functions returns before the chunks are actually saved." }, SetPrimaryServerVersion = { Params = "Protocol Version", Return = "", Notes = "Sets the servers PrimaryServerVersion to the given protocol number." } }, @@ -2117,7 +2116,8 @@ end QueueSaveAllChunks = { Params = "", Return = "", Notes = "Queues all chunks to be saved in the world storage thread" }, QueueSetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta, TickDelay", Return = "", Notes = "Queues the block to be set to the specified blocktype and meta after the specified amount of game ticks. Uses SetBlock() for the actual setting, so simulators are woken up and block entities are handled correctly." }, QueueTask = { Params = "TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the tick thread. This is the primary means of interaction with a cWorld from the WebAdmin page handlers (see {{WebWorldThreads}}). The function signature is
function()
All return values from the function are ignored. Note that this function is actually called *after* the QueueTask() function returns. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." }, - RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." }, + QueueUnloadUnusedChunks = { Params = "", Return = "", Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved." }, + RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." }, ScheduleTask = { Params = "DelayTicks, TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the world's tick thread after a the specified number of ticks. This enables operations to be queued for execution in the future. The function signature is
function({{cWorld|World}})
All return values from the function are ignored. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." }, SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." }, SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." }, From 7ced2f290fc2018d93e324d384d87cfd826312a5 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 21:53:21 +0000 Subject: [PATCH 013/106] Simplified Attack() tracing --- src/Mobs/AggressiveMonster.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp index 7da9f4fc2..0901f85a9 100644 --- a/src/Mobs/AggressiveMonster.cpp +++ b/src/Mobs/AggressiveMonster.cpp @@ -74,8 +74,13 @@ void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) CheckEventSeePlayer(); } + if (m_Target == NULL) + return; + cTracer LineOfSight(GetWorld()); - if (ReachedFinalDestination() && (m_Target != NULL) && !LineOfSight.Trace(GetPosition(), (m_Target->GetPosition() - GetPosition()), (int)(m_Target->GetPosition() - GetPosition()).Length())) + Vector3d AttackDirection(m_Target->GetPosition() - GetPosition()); + + if (ReachedFinalDestination() && !LineOfSight.Trace(GetPosition(), AttackDirection, (int)AttackDirection.Length())) { // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) Attack(a_Dt / 1000); From 91ebb6cef09ff8437beaa0c17ca2a1c094741200 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 21:53:46 +0000 Subject: [PATCH 014/106] Made player jump reset less ambiguous --- src/Entities/Player.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 5f2379ba2..838bbd06c 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1123,7 +1123,8 @@ void cPlayer::SetIP(const AString & a_IP) void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) { SetPosition(a_PosX, a_PosY, a_PosZ); - m_LastGroundHeight, m_LastJumpHeight = (float)a_PosY; + m_LastGroundHeight = (float)a_PosY; + m_LastJumpHeight = (float)a_PosY; m_World->BroadcastTeleportEntity(*this, GetClientHandle()); m_ClientHandle->SendPlayerMoveLook(); From f97ce3015171fcc6f6c5316810d19eb37c89c5f7 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 22:01:22 +0000 Subject: [PATCH 015/106] Changed inheritance a bit * cBlockEntityWithItems now inherits from cBlockEntityWindowOwner --- src/BlockEntities/BlockEntityWithItems.h | 7 +++ src/BlockEntities/ChestEntity.h | 4 +- src/BlockEntities/DropSpenserEntity.h | 4 +- src/BlockEntities/EnderChestEntity.h | 4 +- src/BlockEntities/FurnaceEntity.h | 4 +- src/BlockEntities/HopperEntity.cpp | 55 ++++++++++++++++-------- src/BlockEntities/HopperEntity.h | 4 +- src/ItemGrid.cpp | 7 +++ 8 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/BlockEntities/BlockEntityWithItems.h b/src/BlockEntities/BlockEntityWithItems.h index bf6289a2f..918781a00 100644 --- a/src/BlockEntities/BlockEntityWithItems.h +++ b/src/BlockEntities/BlockEntityWithItems.h @@ -11,6 +11,7 @@ #include "BlockEntity.h" #include "../ItemGrid.h" +#include "../UI/WindowOwner.h" @@ -22,6 +23,7 @@ class cBlockEntityWithItems : // tolua_end // tolua doesn't seem to support multiple inheritance? , public cItemGrid::cListener + , public cBlockEntityWindowOwner // tolua_begin { typedef cBlockEntity super; @@ -77,6 +79,11 @@ protected: ASSERT(a_Grid == &m_Contents); if (m_World != NULL) { + if (GetWindow() != NULL) + { + GetWindow()->BroadcastWholeWindow(); + } + m_World->MarkChunkDirty(GetChunkX(), GetChunkZ()); } } diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h index 1f5668f78..3167d64a0 100644 --- a/src/BlockEntities/ChestEntity.h +++ b/src/BlockEntities/ChestEntity.h @@ -2,7 +2,6 @@ #pragma once #include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" @@ -23,8 +22,7 @@ class cNBTData; // tolua_begin class cChestEntity : - public cBlockEntityWithItems, - public cBlockEntityWindowOwner + public cBlockEntityWithItems { typedef cBlockEntityWithItems super; diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h index f2f1eba36..47d3bd492 100644 --- a/src/BlockEntities/DropSpenserEntity.h +++ b/src/BlockEntities/DropSpenserEntity.h @@ -11,7 +11,6 @@ #pragma once #include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" @@ -31,8 +30,7 @@ class cServer; // tolua_begin class cDropSpenserEntity : - public cBlockEntityWithItems, - public cBlockEntityWindowOwner + public cBlockEntityWithItems { typedef cBlockEntityWithItems super; diff --git a/src/BlockEntities/EnderChestEntity.h b/src/BlockEntities/EnderChestEntity.h index 0ee3cab3b..45beee45f 100644 --- a/src/BlockEntities/EnderChestEntity.h +++ b/src/BlockEntities/EnderChestEntity.h @@ -2,7 +2,6 @@ #pragma once #include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" @@ -23,8 +22,7 @@ class cNBTData; // tolua_begin class cEnderChestEntity : - public cBlockEntityWithItems, - public cBlockEntityWindowOwner + public cBlockEntityWithItems { typedef cBlockEntityWithItems super; diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h index b08187300..5e08ae37a 100644 --- a/src/BlockEntities/FurnaceEntity.h +++ b/src/BlockEntities/FurnaceEntity.h @@ -2,7 +2,6 @@ #pragma once #include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" #include "../FurnaceRecipe.h" @@ -23,8 +22,7 @@ class cServer; // tolua_begin class cFurnaceEntity : - public cBlockEntityWithItems, - public cBlockEntityWindowOwner + public cBlockEntityWithItems { typedef cBlockEntityWithItems super; diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index 2d07ce6c7..b2fe7ee99 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -198,10 +198,10 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) public cEntityCallback { public: - cHopperPickupSearchCallback(Vector3i a_Pos, cItemGrid & a_Contents) : + cHopperPickupSearchCallback(const Vector3i a_Pos, cItemGrid & a_Contents) : m_Pos(a_Pos), - m_Contents(a_Contents), - m_bFoundPickupsAbove(false) + m_bFoundPickupsAbove(false), + m_Contents(a_Contents) { } @@ -220,35 +220,52 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) if (Distance < 0.5) { - for (int i = 0; i < ContentsWidth * ContentsHeight; i++) + if (TrySuckPickupIn((cPickup *)a_Entity)) { - if (m_Contents.IsSlotEmpty(i)) - { - m_bFoundPickupsAbove = true; - m_Contents.SetSlot(i, ((cPickup *)a_Entity)->GetItem()); - a_Entity->Destroy(); // Kill pickup - return false; // Don't break enumeration - } - else if (m_Contents.GetSlot(i).IsEqual(((cPickup *)a_Entity)->GetItem())) - { - m_bFoundPickupsAbove = true; - m_Contents.ChangeSlotCount(i, ((cPickup *)a_Entity)->GetItem().m_ItemCount); - a_Entity->Destroy(); - return false; - } + return false; } } return false; } + bool TrySuckPickupIn(cPickup * a_Pickup) + { + for (int i = 0; i < ContentsWidth * ContentsHeight; i++) + { + if (m_Contents.IsSlotEmpty(i)) + { + m_bFoundPickupsAbove = true; + m_Contents.SetSlot(i, a_Pickup->GetItem()); + a_Pickup->Destroy(); // Kill pickup + return true; + } + else if (m_Contents.GetSlot(i).IsEqual(a_Pickup->GetItem()) && !m_Contents.GetSlot(i).IsFullStack()) + { + m_bFoundPickupsAbove = true; + LOGINFO("Previous counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); + int PreviousCount = m_Contents.GetSlot(i).m_ItemCount; + a_Pickup->GetItem().m_ItemCount -= m_Contents.ChangeSlotCount(i, a_Pickup->GetItem().m_ItemCount) - PreviousCount; // Set count to however many items were added + LOGINFO("After counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); + + if (a_Pickup->GetItem().IsEmpty()) + { + //LOGINFO("Pickup was empty!"); + a_Pickup->Destroy(); // Kill pickup if all items were added + } + return true; + } + } + return false; + } + bool FoundPickupsAbove(void) const { return m_bFoundPickupsAbove; } protected: - Vector3i m_Pos; + const Vector3i m_Pos; bool m_bFoundPickupsAbove; cItemGrid & m_Contents; }; diff --git a/src/BlockEntities/HopperEntity.h b/src/BlockEntities/HopperEntity.h index 2c8b301fe..6ef98f43a 100644 --- a/src/BlockEntities/HopperEntity.h +++ b/src/BlockEntities/HopperEntity.h @@ -10,7 +10,6 @@ #pragma once #include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" @@ -18,8 +17,7 @@ // tolua_begin class cHopperEntity : - public cBlockEntityWithItems, - public cBlockEntityWindowOwner + public cBlockEntityWithItems { typedef cBlockEntityWithItems super; diff --git a/src/ItemGrid.cpp b/src/ItemGrid.cpp index e8b58695f..34a267bab 100644 --- a/src/ItemGrid.cpp +++ b/src/ItemGrid.cpp @@ -369,6 +369,13 @@ int cItemGrid::ChangeSlotCount(int a_SlotNum, int a_AddToCount) } m_Slots[a_SlotNum].m_ItemCount += a_AddToCount; + + cItemHandler * Handler = cItemHandler::GetItemHandler(m_Slots[a_SlotNum].m_ItemType); + if (m_Slots[a_SlotNum].m_ItemCount > Handler->GetMaxStackSize()) + { + m_Slots[a_SlotNum].m_ItemCount = Handler->GetMaxStackSize(); + } + TriggerListeners(a_SlotNum); return m_Slots[a_SlotNum].m_ItemCount; } From e915a0df4cf78f41a200f0a06aabf069aec1bb07 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 22:06:13 +0000 Subject: [PATCH 016/106] Removed some unneeded BroadcastWholeWindow()s --- src/BlockEntities/ChestEntity.cpp | 15 --------------- src/BlockEntities/ChestEntity.h | 1 - src/BlockEntities/DropSpenserEntity.cpp | 7 ------- src/BlockEntities/SignEntity.h | 2 ++ 4 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp index 9282da7fd..dfbe6ae87 100644 --- a/src/BlockEntities/ChestEntity.cpp +++ b/src/BlockEntities/ChestEntity.cpp @@ -170,18 +170,3 @@ void cChestEntity::OpenNewWindow(void) - -void cChestEntity::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) -{ - super::OnSlotChanged(a_Grid, a_SlotNum); - - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->BroadcastWholeWindow(); - } -} - - - - diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h index 3167d64a0..ce16f84d7 100644 --- a/src/BlockEntities/ChestEntity.h +++ b/src/BlockEntities/ChestEntity.h @@ -47,7 +47,6 @@ public: virtual void SaveToJson(Json::Value & a_Value) override; virtual void SendTo(cClientHandle & a_Client) override; virtual void UsedBy(cPlayer * a_Player) override; - virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override; /// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate. void OpenNewWindow(void); diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp index 7c9a40ce6..81df0fc8c 100644 --- a/src/BlockEntities/DropSpenserEntity.cpp +++ b/src/BlockEntities/DropSpenserEntity.cpp @@ -99,13 +99,6 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) } m_World->BroadcastSoundParticleEffect(2000, m_PosX, m_PosY, m_PosZ, SmokeDir); m_World->BroadcastSoundEffect("random.click", m_PosX * 8, m_PosY * 8, m_PosZ * 8, 1.0f, 1.0f); - - // Update the UI window, if open: - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->BroadcastWholeWindow(); - } } diff --git a/src/BlockEntities/SignEntity.h b/src/BlockEntities/SignEntity.h index d998ff1e8..2b965747c 100644 --- a/src/BlockEntities/SignEntity.h +++ b/src/BlockEntities/SignEntity.h @@ -56,6 +56,8 @@ public: virtual void UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle & a_Client) override; + + static const char * GetClassStatic(void) { return "cSignrEntity"; } private: From 6ed4f476ce1365c5878c2726de331c892d00c256 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 22:06:59 +0000 Subject: [PATCH 017/106] Added more missing GetClassStatic()s --- src/BlockEntities/JukeboxEntity.h | 2 ++ src/BlockEntities/NoteEntity.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h index 996de965b..734d7bb66 100644 --- a/src/BlockEntities/JukeboxEntity.h +++ b/src/BlockEntities/JukeboxEntity.h @@ -43,6 +43,8 @@ public: void EjectRecord(void); // tolua_end + + static const char * GetClassStatic(void) { return "cJukeboxEntity"; } virtual void UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle &) override { }; diff --git a/src/BlockEntities/NoteEntity.h b/src/BlockEntities/NoteEntity.h index cf78aeac6..b698899c0 100644 --- a/src/BlockEntities/NoteEntity.h +++ b/src/BlockEntities/NoteEntity.h @@ -54,6 +54,8 @@ public: virtual void UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle &) override { }; + static const char * GetClassStatic(void) { return "cNoteEntity"; } + private: char m_Pitch; } ; // tolua_export From 972919589bfe77e21fad99a52e5ed401127c37a0 Mon Sep 17 00:00:00 2001 From: narroo Date: Thu, 13 Feb 2014 07:51:17 -0600 Subject: [PATCH 018/106] Fixed formatting issue in APIDesc.lua --- MCServer/Plugins/APIDump/APIDesc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 565b32b1b..19553ea80 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2117,7 +2117,7 @@ end QueueSetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta, TickDelay", Return = "", Notes = "Queues the block to be set to the specified blocktype and meta after the specified amount of game ticks. Uses SetBlock() for the actual setting, so simulators are woken up and block entities are handled correctly." }, QueueTask = { Params = "TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the tick thread. This is the primary means of interaction with a cWorld from the WebAdmin page handlers (see {{WebWorldThreads}}). The function signature is
function()
All return values from the function are ignored. Note that this function is actually called *after* the QueueTask() function returns. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." }, QueueUnloadUnusedChunks = { Params = "", Return = "", Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved." }, - RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." }, + RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." }, ScheduleTask = { Params = "DelayTicks, TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the world's tick thread after a the specified number of ticks. This enables operations to be queued for execution in the future. The function signature is
function({{cWorld|World}})
All return values from the function are ignored. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." }, SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." }, SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." }, From 05590fb91d7f4bd2178847cc56ae31699f09ddd2 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 13 Feb 2014 11:47:20 +0100 Subject: [PATCH 019/106] MCADefrag: Initial implementation. Partially implements #639. This only defragments the chunks, without recompressing them. --- Tools/MCADefrag/.gitignore | 1 + Tools/MCADefrag/CMakeLists.txt | 144 ++++++++++++++++ Tools/MCADefrag/Globals.cpp | 10 ++ Tools/MCADefrag/Globals.h | 229 +++++++++++++++++++++++++ Tools/MCADefrag/MCADefrag.cpp | 303 +++++++++++++++++++++++++++++++++ Tools/MCADefrag/MCADefrag.h | 112 ++++++++++++ 6 files changed, 799 insertions(+) create mode 100644 Tools/MCADefrag/.gitignore create mode 100644 Tools/MCADefrag/CMakeLists.txt create mode 100644 Tools/MCADefrag/Globals.cpp create mode 100644 Tools/MCADefrag/Globals.h create mode 100644 Tools/MCADefrag/MCADefrag.cpp create mode 100644 Tools/MCADefrag/MCADefrag.h diff --git a/Tools/MCADefrag/.gitignore b/Tools/MCADefrag/.gitignore new file mode 100644 index 000000000..44a3e1f48 --- /dev/null +++ b/Tools/MCADefrag/.gitignore @@ -0,0 +1 @@ +*.mca diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt new file mode 100644 index 000000000..7296b8ddc --- /dev/null +++ b/Tools/MCADefrag/CMakeLists.txt @@ -0,0 +1,144 @@ + +cmake_minimum_required (VERSION 2.6) + +project (MCADefrag) + + + +macro(add_flags_cxx FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}") +endmacro() + + + + +# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC): +if (NOT MSVC) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG") +endif() + + + +if(MSVC) + # Make build use multiple threads under MSVC: + add_flags_cxx("/MP") + + # Make release builds use link-time code generation: + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") + set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG") +elseif(APPLE) + #on os x clang adds pthread for us but we need to add it for gcc + if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + add_flags_cxx("-pthread") + endif() +else() + # Let gcc / clang know that we're compiling a multi-threaded app: + add_flags_cxx("-pthread") +endif() + + + + +# Use static CRT in MSVC builds: +if (MSVC) + string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") +endif() + + + + +# Set include paths to the used libraries: +include_directories("../../lib") +include_directories("../../src") + + + +function(flatten_files arg1) + set(res "") + foreach(f ${${arg1}}) + get_filename_component(f ${f} ABSOLUTE) + list(APPEND res ${f}) + endforeach() + set(${arg1} "${res}" PARENT_SCOPE) +endfunction() + + +# Include the libraries: +file(GLOB ZLIB_SRC "../../lib/zlib/*.c") +file(GLOB ZLIB_HDR "../../lib/zlib/*.h") +flatten_files(ZLIB_SRC) +flatten_files(ZLIB_HDR) +source_group("ZLib" FILES ${ZLIB_SRC} ${ZLIB_HDR}) + + +# Include the shared files: +set(SHARED_SRC + ../../src/StringCompression.cpp + ../../src/StringUtils.cpp + ../../src/Log.cpp + ../../src/MCLogger.cpp +) +set(SHARED_HDR + ../../src/ByteBuffer.h + ../../src/StringUtils.h + ../../src/Log.h + ../../src/MCLogger.h +) +set(SHARED_OSS_SRC + ../../src/OSSupport/CriticalSection.cpp + ../../src/OSSupport/File.cpp + ../../src/OSSupport/IsThread.cpp + ../../src/OSSupport/Timer.cpp +) +set(SHARED_OSS_HDR + ../../src/OSSupport/CriticalSection.h + ../../src/OSSupport/File.h + ../../src/OSSupport/IsThread.h + ../../src/OSSupport/Timer.h +) +flatten_files(SHARED_SRC) +flatten_files(SHARED_HDR) +flatten_files(SHARED_OSS_SRC) +flatten_files(SHARED_OSS_HDR) +source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) +source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR}) + + + +# Include the main source files: +set(SOURCES + MCADefrag.cpp + Globals.cpp +) +set(HEADERS + MCADefrag.h + Globals.h +) + +source_group("" FILES ${SOURCES} ${HEADERS}) + +add_executable(MCADefrag + ${SOURCES} + ${HEADERS} + ${SHARED_SRC} + ${SHARED_HDR} + ${SHARED_OSS_SRC} + ${SHARED_OSS_HDR} + ${ZLIB_SRC} + ${ZLIB_HDR} +) + diff --git a/Tools/MCADefrag/Globals.cpp b/Tools/MCADefrag/Globals.cpp new file mode 100644 index 000000000..13c6ae709 --- /dev/null +++ b/Tools/MCADefrag/Globals.cpp @@ -0,0 +1,10 @@ + +// Globals.cpp + +// This file is used for precompiled header generation in MSVC environments + +#include "Globals.h" + + + + diff --git a/Tools/MCADefrag/Globals.h b/Tools/MCADefrag/Globals.h new file mode 100644 index 000000000..6f4bbdc76 --- /dev/null +++ b/Tools/MCADefrag/Globals.h @@ -0,0 +1,229 @@ + +// Globals.h + +// This file gets included from every module in the project, so that global symbols may be introduced easily +// Also used for precompiled header generation in MSVC environments + + + + + +// Compiler-dependent stuff: +#if defined(_MSC_VER) + // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether + #pragma warning(disable:4481) + + // Disable some warnings that we don't care about: + #pragma warning(disable:4100) + + #define OBSOLETE __declspec(deprecated) + + // No alignment needed in MSVC + #define ALIGN_8 + #define ALIGN_16 + +#elif defined(__GNUC__) + + // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)? + #define abstract + + // TODO: Can GCC mark virtual methods as overriding (forcing them to have a virtual function of the same signature in the base class) + #define override + + #define OBSOLETE __attribute__((deprecated)) + + #define ALIGN_8 __attribute__((aligned(8))) + #define ALIGN_16 __attribute__((aligned(16))) + + // Some portability macros :) + #define stricmp strcasecmp + +#else + + #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler" + + /* + // Copy and uncomment this into another #elif section based on your compiler identification + + // Explicitly mark classes as abstract (no instances can be created) + #define abstract + + // Mark virtual methods as overriding (forcing them to have a virtual function of the same signature in the base class) + #define override + + // Mark functions as obsolete, so that their usage results in a compile-time warning + #define OBSOLETE + + // Mark types / variables for alignment. Do the platforms need it? + #define ALIGN_8 + #define ALIGN_16 + */ + +#endif + + + + + +// Integral types with predefined sizes: +typedef long long Int64; +typedef int Int32; +typedef short Int16; + +typedef unsigned long long UInt64; +typedef unsigned int UInt32; +typedef unsigned short UInt16; + +typedef unsigned char Byte; + + + + + +// A macro to disallow the copy constructor and operator= functions +// This should be used in the private: declarations for any class that shouldn't allow copying itself +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName &); \ + void operator=(const TypeName &) + +// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc +#define UNUSED(X) (void)(X) + + + + +// OS-dependent stuff: +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #include + #include + #include + + // Windows SDK defines min and max macros, messing up with our std::min and std::max usage + #undef min + #undef max + + // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant + #ifdef GetFreeSpace + #undef GetFreeSpace + #endif // GetFreeSpace + + #define SocketError WSAGetLastError() +#else + #include + #include // for mkdir + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + typedef int SOCKET; + enum + { + INVALID_SOCKET = -1, + }; + #define closesocket close + #define SocketError errno +#if !defined(ANDROID_NDK) + #include +#endif +#endif + +#if !defined(ANDROID_NDK) + #define USE_SQUIRREL +#endif + +#if defined(ANDROID_NDK) + #define FILE_IO_PREFIX "/sdcard/mcserver/" +#else + #define FILE_IO_PREFIX "" +#endif + + + + + +// CRT stuff: +#include +#include +#include +#include +#include + + + + + +// STL stuff: +#include +#include +#include +#include +#include +#include +#include + + + + + +// Common headers (without macros): +#include "StringUtils.h" +#include "OSSupport/CriticalSection.h" +#include "OSSupport/IsThread.h" +#include "OSSupport/File.h" + + + + + +// Common definitions: + +/// Evaluates to the number of elements in an array (compile-time!) +#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) + +/// Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)" ) +#define KiB * 1024 +#define MiB * 1024 * 1024 + +/// Faster than (int)floorf((float)x / (float)div) +#define FAST_FLOOR_DIV( x, div ) ( (x) < 0 ? (((int)x / div) - 1) : ((int)x / div) ) + +// Own version of assert() that writes failed assertions to the log for review +#ifdef NDEBUG + #define ASSERT(x) ((void)0) +#else + #define ASSERT assert +#endif + +// Pretty much the same as ASSERT() but stays in Release builds +#define VERIFY( x ) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), exit(1), 0 ) ) + + + + + +/// A generic interface used mainly in ForEach() functions +template class cItemCallback +{ +public: + /// Called for each item in the internal list; return true to stop the loop, or false to continue enumerating + virtual bool Item(Type * a_Type) = 0; +} ; + + + + diff --git a/Tools/MCADefrag/MCADefrag.cpp b/Tools/MCADefrag/MCADefrag.cpp new file mode 100644 index 000000000..2f24469c9 --- /dev/null +++ b/Tools/MCADefrag/MCADefrag.cpp @@ -0,0 +1,303 @@ + +// MCADefrag.cpp + +// Implements the main app entrypoint and the cMCADefrag class representing the entire app + +#include "Globals.h" +#include "MCADefrag.h" +#include "MCLogger.h" + + + + + +int main(int argc, char ** argv) +{ + new cMCLogger(Printf("Defrag_%08x.log", time(NULL))); + cMCADefrag Defrag; + if (!Defrag.Init(argc, argv)) + { + return 1; + } + + Defrag.Run(); + + return 0; +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cMCADefrag: + +cMCADefrag::cMCADefrag(void) : + m_NumThreads(1) +{ +} + + + + + +bool cMCADefrag::Init(int argc, char ** argv) +{ + // Nothing needed yet + return true; +} + + + + + +void cMCADefrag::Run(void) +{ + // Fill the queue with MCA files + m_Queue = cFile::GetFolderContents("."); + + // Start the processing threads: + for (int i = 0; i < m_NumThreads; i++) + { + StartThread(); + } + + // Wait for all the threads to finish: + while (!m_Threads.empty()) + { + m_Threads.front()->Wait(); + delete m_Threads.front(); + m_Threads.pop_front(); + } +} + + + + +void cMCADefrag::StartThread(void) +{ + cThread * Thread = new cThread(*this); + m_Threads.push_back(Thread); + Thread->Start(); +} + + + + + +AString cMCADefrag::GetNextFileName(void) +{ + cCSLock Lock(m_CS); + if (m_Queue.empty()) + { + return AString(); + } + AString res = m_Queue.back(); + m_Queue.pop_back(); + return res; +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cMCADefrag::cThread: + +cMCADefrag::cThread::cThread(cMCADefrag & a_Parent) : + super("MCADefrag thread"), + m_Parent(a_Parent) +{ +} + + + + + +void cMCADefrag::cThread::Execute(void) +{ + for (;;) + { + AString FileName = m_Parent.GetNextFileName(); + if (FileName.empty()) + { + return; + } + ProcessFile(FileName); + } +} + + + + + +void cMCADefrag::cThread::ProcessFile(const AString & a_FileName) +{ + // Filter out non-MCA files: + if ((a_FileName.length() < 4) || (a_FileName.substr(a_FileName.length() - 4, 4) != ".mca")) + { + return; + } + LOGINFO("%s", a_FileName.c_str()); + + // Open input and output files: + AString OutFileName = a_FileName + ".new"; + cFile In, Out; + if (!In.Open(a_FileName, cFile::fmRead)) + { + LOGWARNING("Cannot open file %s for reading, skipping file.", a_FileName.c_str()); + return; + } + if (!Out.Open(OutFileName.c_str(), cFile::fmWrite)) + { + LOGWARNING("Cannot open file %s for writing, skipping file.", OutFileName.c_str()); + return; + } + + // Read the Locations and Timestamps from the input file: + Byte Locations[4096]; + UInt32 Timestamps[1024]; + if (In.Read(Locations, sizeof(Locations)) != sizeof(Locations)) + { + LOGWARNING("Cannot read Locations in file %s, skipping file.", a_FileName.c_str()); + return; + } + if (In.Read(Timestamps, sizeof(Timestamps)) != sizeof(Timestamps)) + { + LOGWARNING("Cannot read Timestamps in file %s, skipping file.", a_FileName.c_str()); + return; + } + + // Write dummy Locations to the Out file (will be overwritten once the correct ones are known) + if (Out.Write(Locations, sizeof(Locations)) != sizeof(Locations)) + { + LOGWARNING("Cannot write Locations to file %s, skipping file.", OutFileName.c_str()); + return; + } + m_CurrentSectorOut = 2; + + // Write a copy of the Timestamps into the Out file: + if (Out.Write(Timestamps, sizeof(Timestamps)) != sizeof(Timestamps)) + { + LOGWARNING("Cannot write Timestamps to file %s, skipping file.", OutFileName.c_str()); + return; + } + + // Process each chunk: + for (size_t i = 0; i < 1024; i++) + { + size_t idx = i * 4; + if ( + (Locations[idx] == 0) && + (Locations[idx + 1] == 0) && + (Locations[idx + 2] == 0) && + (Locations[idx + 3] == 0) + ) + { + // Chunk not present + continue; + } + if (!ReadChunk(In, Locations + idx)) + { + LOGWARNING("Cannot read chunk #%d from file %s. Skipping file.", i, a_FileName.c_str()); + return; + } + if (!WriteChunk(Out, Locations + idx)) + { + LOGWARNING("Cannot write chunk #%d to file %s. Skipping file.", i, OutFileName.c_str()); + return; + } + } + + // Write the new Locations into the MCA header: + Out.Seek(0); + if (Out.Write(Locations, sizeof(Locations)) != sizeof(Locations)) + { + LOGWARNING("Cannot write updated Locations to file %s, skipping file.", OutFileName.c_str()); + return; + } + + // Close the files, delete orig, rename new: + In.Close(); + Out.Close(); + cFile::Delete(a_FileName); + cFile::Rename(OutFileName, a_FileName); +} + + + + + +bool cMCADefrag::cThread::ReadChunk(cFile & a_File, const Byte * a_LocationRaw) +{ + int SectorNum = (a_LocationRaw[0] << 16) | (a_LocationRaw[1] << 8) | a_LocationRaw[2]; + int SizeInSectors = a_LocationRaw[3] * (4 KiB); + if (a_File.Seek(SectorNum * (4 KiB)) < 0) + { + LOGWARNING("Failed to seek to chunk data - file pos %llu (%d KiB, %.02f MiB)!", (Int64)SectorNum * (4 KiB), SectorNum * 4, ((double)SectorNum) / 256); + return false; + } + + // Read the exact size: + Byte Buf[4]; + if (a_File.Read(Buf, 4) != 4) + { + LOGWARNING("Failed to read chunk data length"); + return false; + } + m_CompressedChunkDataSize = (Buf[0] << 24) | (Buf[1] << 16) | (Buf[2] << 8) | Buf[3]; + if (m_CompressedChunkDataSize > SizeInSectors) + { + LOGWARNING("Invalid chunk data - SizeInSectors (%d) smaller that RealSize (%d)", SizeInSectors, m_CompressedChunkDataSize); + return false; + } + + // Read the data: + if (a_File.Read(m_CompressedChunkData, m_CompressedChunkDataSize) != m_CompressedChunkDataSize) + { + LOGWARNING("Failed to read chunk data!"); + return false; + } + + // TODO: Uncompress the data if recompression is active + + return true; +} + + + + + +bool cMCADefrag::cThread::WriteChunk(cFile & a_File, Byte * a_LocationRaw) +{ + // TODO: Recompress the data if recompression is active + + a_LocationRaw[0] = m_CurrentSectorOut >> 16; + a_LocationRaw[1] = (m_CurrentSectorOut >> 8) & 0xff; + a_LocationRaw[2] = m_CurrentSectorOut & 0xff; + a_LocationRaw[3] = (m_CompressedChunkDataSize + (4 KiB) - 1) / (4 KiB); + + // Write the data length: + Byte Buf[4]; + Buf[0] = m_CompressedChunkDataSize >> 24; + Buf[1] = (m_CompressedChunkDataSize >> 16) & 0xff; + Buf[2] = (m_CompressedChunkDataSize >> 8) & 0xff; + Buf[3] = m_CompressedChunkDataSize & 0xff; + if (a_File.Write(Buf, 4) != 4) + { + LOGWARNING("Failed to write chunk length!"); + return false; + } + + // Write the data: + if (a_File.Write(m_CompressedChunkData, m_CompressedChunkDataSize) != m_CompressedChunkDataSize) + { + LOGWARNING("Failed to write chunk data!"); + return false; + } + return true; +} + + + + diff --git a/Tools/MCADefrag/MCADefrag.h b/Tools/MCADefrag/MCADefrag.h new file mode 100644 index 000000000..0801d1b5d --- /dev/null +++ b/Tools/MCADefrag/MCADefrag.h @@ -0,0 +1,112 @@ + +// MCADefrag.h + +// Interfaces to the cMCADefrag class encapsulating the entire app + + + + + +#pragma once + + + + + + +class cMCADefrag +{ +public: + enum + { + MAX_COMPRESSED_CHUNK_DATA_SIZE = (1 MiB), + MAX_RAW_CHUNK_DATA_SIZE = (100 MiB), + } ; + + cMCADefrag(void); + + /** Reads the cmdline params and initializes the app. + Returns true if the app should continue, false if not. */ + bool Init(int argc, char ** argv); + + /** Runs the entire app. */ + void Run(void); + +protected: + /** A single thread processing MCA files from the queue */ + class cThread : + public cIsThread + { + typedef cIsThread super; + + public: + cThread(cMCADefrag & a_Parent); + + protected: + cMCADefrag & m_Parent; + + /** The current compressed chunk data. Valid after a successful ReadChunk(). + This contains only the compression method byte and the compressed data, + but not the length preceding the data in the MCA file. */ + unsigned char m_CompressedChunkData[MAX_COMPRESSED_CHUNK_DATA_SIZE]; + + /** Size of the actual current compressed chunk data. */ + int m_CompressedChunkDataSize; + + /** The current raw chunk data. Valid after a successful ReadChunk(), if recompression is active. */ + unsigned char m_RawChunkData[MAX_RAW_CHUNK_DATA_SIZE]; + + /** Size of the actual current raw chunk data. */ + int m_RawChunkDataSize; + + /** Number of the sector where the next chunk will be written by WriteChunk(). */ + int m_CurrentSectorOut; + + + /** Processes the specified file. */ + void ProcessFile(const AString & a_FileName); + + /** Reads the chunk data into m_CompressedChunkData. + Calls DecompressChunkData() if recompression is active. + a_LocationRaw is the pointer to the first byte of the Location data in the MCA header. + Returns true if successful. */ + bool ReadChunk(cFile & a_File, const Byte * a_LocationRaw); + + /** Writes the chunk data from m_CompressedData or m_RawChunkData (performing recompression) into file. + Calls CompressChunkData() for the actual compression, if recompression is active. + a_LocationRaw is the pointer to the first byte of the Location data to be put into the MCA header, + the chunk's location is stored in that memory area. Updates m_CurrentSectorOut. + Returns true if successful. */ + bool WriteChunk(cFile & a_File, Byte * a_LocationRaw); + + // cIsThread overrides: + virtual void Execute(void) override; + } ; + + typedef std::list cThreads; + + + /** The mutex protecting m_Files agains multithreaded access. */ + cCriticalSection m_CS; + + /** The queue of MCA files to be processed by the threads. Protected by m_CS. */ + AStringVector m_Queue; + + /** List of threads that the server has running. */ + cThreads m_Threads; + + /** The number of threads that should be started. Configurable on the command line. */ + int m_NumThreads; + + + /** Starts a new processing thread and adds it to cThreads. */ + void StartThread(void); + + /** Retrieves one file from the queue (and removes it from the queue). + Returns an empty string when queue empty. */ + AString GetNextFileName(void); +} ; + + + + From cd658e02e8dcb7503d8aa5d75c314dcddb1ca11a Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 13 Feb 2014 12:48:22 +0100 Subject: [PATCH 020/106] MCADefrag: Fixed bugs, now produces valid MCA files. --- Tools/MCADefrag/MCADefrag.cpp | 20 +++++++++++++++++++- Tools/MCADefrag/MCADefrag.h | 5 +++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Tools/MCADefrag/MCADefrag.cpp b/Tools/MCADefrag/MCADefrag.cpp index 2f24469c9..59a67e45d 100644 --- a/Tools/MCADefrag/MCADefrag.cpp +++ b/Tools/MCADefrag/MCADefrag.cpp @@ -11,6 +11,13 @@ +// An array of 4096 zero bytes, used for writing the padding +static const Byte g_Zeroes[4096] = {0}; + + + + + int main(int argc, char ** argv) { new cMCLogger(Printf("Defrag_%08x.log", time(NULL))); @@ -275,7 +282,7 @@ bool cMCADefrag::cThread::WriteChunk(cFile & a_File, Byte * a_LocationRaw) a_LocationRaw[0] = m_CurrentSectorOut >> 16; a_LocationRaw[1] = (m_CurrentSectorOut >> 8) & 0xff; a_LocationRaw[2] = m_CurrentSectorOut & 0xff; - a_LocationRaw[3] = (m_CompressedChunkDataSize + (4 KiB) - 1) / (4 KiB); + a_LocationRaw[3] = (m_CompressedChunkDataSize + (4 KiB) + 3) / (4 KiB); // +3 because the m_CompressedChunkDataSize doesn't include the exact-length // Write the data length: Byte Buf[4]; @@ -295,6 +302,17 @@ bool cMCADefrag::cThread::WriteChunk(cFile & a_File, Byte * a_LocationRaw) LOGWARNING("Failed to write chunk data!"); return false; } + + // Pad onto the next sector: + int NumPadding = a_LocationRaw[3] * 4096 - (m_CompressedChunkDataSize + 4); + ASSERT(NumPadding >= 0); + if ((NumPadding > 0) && (a_File.Write(g_Zeroes, NumPadding) != NumPadding)) + { + LOGWARNING("Failed to write padding"); + return false; + } + + m_CurrentSectorOut += a_LocationRaw[3]; return true; } diff --git a/Tools/MCADefrag/MCADefrag.h b/Tools/MCADefrag/MCADefrag.h index 0801d1b5d..ef527863d 100644 --- a/Tools/MCADefrag/MCADefrag.h +++ b/Tools/MCADefrag/MCADefrag.h @@ -47,10 +47,11 @@ protected: /** The current compressed chunk data. Valid after a successful ReadChunk(). This contains only the compression method byte and the compressed data, - but not the length preceding the data in the MCA file. */ + but not the exact-length preceding the data in the MCA file. */ unsigned char m_CompressedChunkData[MAX_COMPRESSED_CHUNK_DATA_SIZE]; - /** Size of the actual current compressed chunk data. */ + /** Size of the actual current compressed chunk data, excluding the 4 exact-length bytes. + This is the amount of bytes in m_CompressedChunkData[] that are valid. */ int m_CompressedChunkDataSize; /** The current raw chunk data. Valid after a successful ReadChunk(), if recompression is active. */ From 41ab8260f7b50bedbf06ea0effcb6147cb648685 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 13 Feb 2014 16:54:29 +0100 Subject: [PATCH 021/106] MCADefrag: Implemented recompression. This finalizes #639. --- Tools/MCADefrag/MCADefrag.cpp | 110 ++++++++++++++++++++++++++++++++-- Tools/MCADefrag/MCADefrag.h | 31 ++++++++++ 2 files changed, 136 insertions(+), 5 deletions(-) diff --git a/Tools/MCADefrag/MCADefrag.cpp b/Tools/MCADefrag/MCADefrag.cpp index 59a67e45d..a2de7f957 100644 --- a/Tools/MCADefrag/MCADefrag.cpp +++ b/Tools/MCADefrag/MCADefrag.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "MCADefrag.h" #include "MCLogger.h" +#include "zlib/zlib.h" @@ -40,7 +41,8 @@ int main(int argc, char ** argv) // cMCADefrag: cMCADefrag::cMCADefrag(void) : - m_NumThreads(1) + m_NumThreads(4), + m_ShouldRecompress(true) { } @@ -113,7 +115,8 @@ AString cMCADefrag::GetNextFileName(void) cMCADefrag::cThread::cThread(cMCADefrag & a_Parent) : super("MCADefrag thread"), - m_Parent(a_Parent) + m_Parent(a_Parent), + m_IsChunkUncompressed(false) { } @@ -204,6 +207,7 @@ void cMCADefrag::cThread::ProcessFile(const AString & a_FileName) // Chunk not present continue; } + m_IsChunkUncompressed = false; if (!ReadChunk(In, Locations + idx)) { LOGWARNING("Cannot read chunk #%d from file %s. Skipping file.", i, a_FileName.c_str()); @@ -266,7 +270,15 @@ bool cMCADefrag::cThread::ReadChunk(cFile & a_File, const Byte * a_LocationRaw) return false; } - // TODO: Uncompress the data if recompression is active + // Uncompress the data if recompression is active + if (m_Parent.m_ShouldRecompress) + { + m_IsChunkUncompressed = UncompressChunk(); + if (!m_IsChunkUncompressed) + { + LOGINFO("Chunk failed to uncompress, will be copied verbatim instead."); + } + } return true; } @@ -277,12 +289,21 @@ bool cMCADefrag::cThread::ReadChunk(cFile & a_File, const Byte * a_LocationRaw) bool cMCADefrag::cThread::WriteChunk(cFile & a_File, Byte * a_LocationRaw) { - // TODO: Recompress the data if recompression is active + // Recompress the data if recompression is active: + if (m_Parent.m_ShouldRecompress) + { + if (!CompressChunk()) + { + LOGINFO("Chunk failed to recompress, will be coped verbatim instead."); + } + } + // Update the Location: a_LocationRaw[0] = m_CurrentSectorOut >> 16; a_LocationRaw[1] = (m_CurrentSectorOut >> 8) & 0xff; a_LocationRaw[2] = m_CurrentSectorOut & 0xff; a_LocationRaw[3] = (m_CompressedChunkDataSize + (4 KiB) + 3) / (4 KiB); // +3 because the m_CompressedChunkDataSize doesn't include the exact-length + m_CurrentSectorOut += a_LocationRaw[3]; // Write the data length: Byte Buf[4]; @@ -312,7 +333,86 @@ bool cMCADefrag::cThread::WriteChunk(cFile & a_File, Byte * a_LocationRaw) return false; } - m_CurrentSectorOut += a_LocationRaw[3]; + return true; +} + + + + + +bool cMCADefrag::cThread::UncompressChunk(void) +{ + switch (m_CompressedChunkData[0]) + { + case COMPRESSION_GZIP: return UncompressChunkGzip(); + case COMPRESSION_ZLIB: return UncompressChunkZlib(); + } + LOGINFO("Chunk is compressed with in an unknown algorithm"); + return false; +} + + + + + +bool cMCADefrag::cThread::UncompressChunkGzip(void) +{ + // TODO + // This format is not used in practice + return false; +} + + + + + +bool cMCADefrag::cThread::UncompressChunkZlib(void) +{ + // Uncompress the data: + z_stream strm; + strm.zalloc = (alloc_func)NULL; + strm.zfree = (free_func)NULL; + strm.opaque = NULL; + inflateInit(&strm); + strm.next_out = m_RawChunkData; + strm.avail_out = sizeof(m_RawChunkData); + strm.next_in = m_CompressedChunkData + 1; // The first byte is the compression method, skip it + strm.avail_in = m_CompressedChunkDataSize; + int res = inflate(&strm, Z_FINISH); + inflateEnd(&strm); + if (res != Z_STREAM_END) + { + LOGWARNING("Failed to uncompress chunk data: %s", strm.msg); + return false; + } + m_RawChunkDataSize = strm.total_out; + + return true; +} + + + + + +bool cMCADefrag::cThread::CompressChunk(void) +{ + // Check that the compressed data can fit: + uLongf CompressedSize = compressBound(m_RawChunkDataSize); + if (CompressedSize > sizeof(m_CompressedChunkData)) + { + LOGINFO("Too much data for the internal compression buffer!"); + return false; + } + + // Compress the data using the highest compression factor: + int errorcode = compress2(m_CompressedChunkData + 1, &CompressedSize, m_RawChunkData, m_RawChunkDataSize, Z_BEST_COMPRESSION); + if (errorcode != Z_OK) + { + LOGINFO("Recompression failed: %d", errorcode); + return false; + } + m_CompressedChunkData[0] = COMPRESSION_ZLIB; + m_CompressedChunkDataSize = CompressedSize + 1; return true; } diff --git a/Tools/MCADefrag/MCADefrag.h b/Tools/MCADefrag/MCADefrag.h index ef527863d..d7fa1fc6e 100644 --- a/Tools/MCADefrag/MCADefrag.h +++ b/Tools/MCADefrag/MCADefrag.h @@ -43,6 +43,14 @@ protected: cThread(cMCADefrag & a_Parent); protected: + /** The compression methods, as specified by the MCA compression method byte. */ + enum + { + COMPRESSION_GZIP = 1, + COMPRESSION_ZLIB = 2, + } ; + + cMCADefrag & m_Parent; /** The current compressed chunk data. Valid after a successful ReadChunk(). @@ -63,6 +71,10 @@ protected: /** Number of the sector where the next chunk will be written by WriteChunk(). */ int m_CurrentSectorOut; + /** Set to true when the chunk has been successfully uncompressed. Only used if recompression is active. + WriteChunk() tests this flag to decide whether to call Compress(). */ + bool m_IsChunkUncompressed; + /** Processes the specified file. */ void ProcessFile(const AString & a_FileName); @@ -80,6 +92,22 @@ protected: Returns true if successful. */ bool WriteChunk(cFile & a_File, Byte * a_LocationRaw); + /** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData. + Returns true if successful, false on failure. */ + bool UncompressChunk(void); + + /** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData, using Gzip. + Returns true if successful, false on failure. */ + bool UncompressChunkGzip(void); + + /** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData, using Zlib. + Returns true if successful, false on failure. */ + bool UncompressChunkZlib(void); + + /** Compresses the chunk data from m_RawChunkData into m_CompressedChunkData. + Returns true if successful, false on failure. */ + bool CompressChunk(void); + // cIsThread overrides: virtual void Execute(void) override; } ; @@ -99,6 +127,9 @@ protected: /** The number of threads that should be started. Configurable on the command line. */ int m_NumThreads; + /** If set to true, the chunk data is recompressed while saving each MCA file. */ + bool m_ShouldRecompress; + /** Starts a new processing thread and adds it to cThreads. */ void StartThread(void); From 6103589e8c13aca159f34eff5d0bc7bb40e3e76a Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 13 Feb 2014 17:05:31 +0100 Subject: [PATCH 022/106] Updated Core. --- MCServer/Plugins/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core index 0e5358871..5c8557d4f 160000 --- a/MCServer/Plugins/Core +++ b/MCServer/Plugins/Core @@ -1 +1 @@ -Subproject commit 0e53588713215f0a9557ef55295e8aa22f265cba +Subproject commit 5c8557d4fdfa580c100510cde07a1a778ea2e244 From c0e7d6fec9c8349321849b933183ef3f49ff87d2 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 13 Feb 2014 19:57:23 +0000 Subject: [PATCH 023/106] Fancy stuff with constant references --- src/BlockEntities/HopperEntity.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index b2fe7ee99..b4ee36607 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -198,7 +198,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) public cEntityCallback { public: - cHopperPickupSearchCallback(const Vector3i a_Pos, cItemGrid & a_Contents) : + cHopperPickupSearchCallback(const Vector3i & a_Pos, cItemGrid & a_Contents) : m_Pos(a_Pos), m_bFoundPickupsAbove(false), m_Contents(a_Contents) @@ -265,7 +265,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) } protected: - const Vector3i m_Pos; + Vector3i m_Pos; bool m_bFoundPickupsAbove; cItemGrid & m_Contents; }; From f4f0099947a017085574bff681d76aa1d4d53058 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 13 Feb 2014 20:20:37 +0000 Subject: [PATCH 024/106] Added proper debug messages --- src/BlockEntities/HopperEntity.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index b4ee36607..386dc2d32 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -238,19 +238,24 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) m_bFoundPickupsAbove = true; m_Contents.SetSlot(i, a_Pickup->GetItem()); a_Pickup->Destroy(); // Kill pickup + + LOGD("Hopper sucking pickup into an empty slot"); + return true; } else if (m_Contents.GetSlot(i).IsEqual(a_Pickup->GetItem()) && !m_Contents.GetSlot(i).IsFullStack()) { m_bFoundPickupsAbove = true; - LOGINFO("Previous counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); + + LOGD("Hopper sucking pickup; previous counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); + int PreviousCount = m_Contents.GetSlot(i).m_ItemCount; a_Pickup->GetItem().m_ItemCount -= m_Contents.ChangeSlotCount(i, a_Pickup->GetItem().m_ItemCount) - PreviousCount; // Set count to however many items were added - LOGINFO("After counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); + + LOGD("Hopper sucking pickup; after counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); if (a_Pickup->GetItem().IsEmpty()) { - //LOGINFO("Pickup was empty!"); a_Pickup->Destroy(); // Kill pickup if all items were added } return true; From ceb16ea2f714cc1b9f52750446e3842e2b6a5820 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sat, 15 Feb 2014 11:38:20 +0100 Subject: [PATCH 025/106] Exported cWorld::BroadcastParticleEffect. --- src/World.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/World.h b/src/World.h index fa83fe73e..9049971be 100644 --- a/src/World.h +++ b/src/World.h @@ -183,7 +183,7 @@ public: void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL); void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL); - void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); + void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); void BroadcastScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); From 34207a606a129c888eb77d9765214a351144f0f5 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sat, 15 Feb 2014 11:45:20 +0100 Subject: [PATCH 026/106] Documented BroadcastParticleEffect --- MCServer/Plugins/APIDump/APIDesc.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 01554d99c..54e1d097d 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2031,6 +2031,7 @@ end BroadcastChatInfo = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Yellow [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For informational messages, such as command usage." }, BroadcastChatSuccess = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For success messages." }, BroadcastChatWarning = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For concerning events, such as plugin reload etc." }, + BroadcastParticleEffect = { Params = "ParticleName, X, Y, Z, OffSetX, OffSetY, OffSetZ, ParticleData, ParticleAmmount, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Spawns the specified particles to all players in the world exept the optional ExeptClient. A list of available particles by thinkofdeath can be found {{https://gist.github.com/thinkofdeath/5110835|Here}}" }, BroadcastSoundEffect = { Params = "SoundName, X, Y, Z, Volume, Pitch, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Sends the specified sound effect to all players in this world, except the optional ExceptClient" }, BroadcastSoundParticleEffect = { Params = "EffectID, X, Y, Z, EffectData, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Sends the specified effect to all players in this world, except the optional ExceptClient" }, CastThunderbolt = { Params = "X, Y, Z", Return = "", Notes = "Creates a thunderbolt at the specified coords" }, From c6a2e8c6889aca8aa422ac704b79bf7fc43856ec Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 12:58:17 +0000 Subject: [PATCH 027/106] Removed debug messages again --- src/BlockEntities/HopperEntity.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index 386dc2d32..31b23ac99 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -239,20 +239,14 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) m_Contents.SetSlot(i, a_Pickup->GetItem()); a_Pickup->Destroy(); // Kill pickup - LOGD("Hopper sucking pickup into an empty slot"); - return true; } else if (m_Contents.GetSlot(i).IsEqual(a_Pickup->GetItem()) && !m_Contents.GetSlot(i).IsFullStack()) { m_bFoundPickupsAbove = true; - LOGD("Hopper sucking pickup; previous counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); - int PreviousCount = m_Contents.GetSlot(i).m_ItemCount; a_Pickup->GetItem().m_ItemCount -= m_Contents.ChangeSlotCount(i, a_Pickup->GetItem().m_ItemCount) - PreviousCount; // Set count to however many items were added - - LOGD("Hopper sucking pickup; after counts, pickup: %i, hopper: %i", (int)a_Pickup->GetItem().m_ItemCount, (int)m_Contents.GetSlot(i).m_ItemCount); if (a_Pickup->GetItem().IsEmpty()) { From b0fd5511eab236b69fb0805789917e91f8bb6b6e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 13:55:58 +0000 Subject: [PATCH 028/106] Fixed typographical error --- src/BlockEntities/SignEntity.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/BlockEntities/SignEntity.h b/src/BlockEntities/SignEntity.h index 2b965747c..80c7bbfdf 100644 --- a/src/BlockEntities/SignEntity.h +++ b/src/BlockEntities/SignEntity.h @@ -1,4 +1,3 @@ - // SignEntity.h // Declares the cSignEntity class representing a single sign in the world @@ -57,7 +56,7 @@ public: virtual void UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle & a_Client) override; - static const char * GetClassStatic(void) { return "cSignrEntity"; } + static const char * GetClassStatic(void) { return "cSignEntity"; } private: From 87e79de4b7d435366862c3b70ccdad559bb2e286 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 11 Feb 2014 15:01:24 +0100 Subject: [PATCH 029/106] Add Fence Gate to Redstone Simulator --- .../IncrementalRedstoneSimulator.cpp | 29 +++++++++++++++++++ src/Simulator/IncrementalRedstoneSimulator.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index a875c9e4d..a6e2cb2e9 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -8,6 +8,7 @@ #include "../Entities/TNTEntity.h" #include "../Blocks/BlockTorch.h" #include "../Blocks/BlockDoor.h" +#include "../Blocks/BlockFenceGate.h" #include "../Piston.h" @@ -221,6 +222,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int { case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(a_X, dataitr->y, a_Z); break; case E_BLOCK_LEVER: HandleRedstoneLever(a_X, dataitr->y, a_Z); break; + case E_BLOCK_FENCE_GATE: HandleFenceGate(a_X, dataitr->y, a_Z); break; case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break; case E_BLOCK_TRAPDOOR: HandleTrapdoor(a_X, dataitr->y, a_Z); break; case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(a_X, dataitr->y, a_Z); break; @@ -402,6 +404,33 @@ void cIncrementalRedstoneSimulator::HandleRedstoneLever(int a_BlockX, int a_Bloc +void cIncrementalRedstoneSimulator::HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + cChunkInterface ChunkInterface(m_World.GetChunkMap()); + NIBBLETYPE MetaData = ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); + + if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) + { + if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true)) + { + m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaData | 0x4); + 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, MetaData & 0xFFFFFFFB); + SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false); + } + } +} + + + + + void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType) { if (IsButtonOn(m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ))) diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index a3da13584..bcf89bb82 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -84,6 +84,8 @@ private: void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ); /** Handles levers */ void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ); + /** Handles Fence Gates */ + void HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ); /** Handles buttons */ void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType); /** Handles daylight sensors */ From 70a0dcb1ebf8c79dce3a2c3bad553b9ee4606540 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 11 Feb 2014 15:08:17 +0100 Subject: [PATCH 030/106] Add more Sounds to Redstone Simulator --- .../IncrementalRedstoneSimulator.cpp | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index a6e2cb2e9..985fdee27 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -318,6 +318,22 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_Bloc { // There was a match, torch goes off m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_OFF, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ)); + + float Pitch = (((1.0F-0.0F)*((float)rand()/RAND_MAX)) - ((1.0F-0.0F)*((float)rand()/RAND_MAX))) * 0.8F; + m_World.BroadcastSoundEffect("random.fizz", + ((int) (a_BlockX + 0.5F) * 8.0), + ((int) (a_BlockY + 0.5F) * 8.0), + ((int) (a_BlockZ + 0.5F) * 8.0), + 0.5F, + 2.6F + Pitch); + + for (int l = 0; l < 5; ++l) { + float d0 = a_BlockX + (double(rand())/RAND_MAX) * 0.6F + 0.2F; + float d1 = a_BlockY + (double(rand())/RAND_MAX) * 0.6F + 0.2F; + float d2 = a_BlockZ + (double(rand())/RAND_MAX) * 0.6F + 0.2F; + m_World.BroadcastParticleEffect("smoke", d0, d1, d2, 0.0F, 0.0F, 0.0F, 0.01F, 1); + } + return; } @@ -414,6 +430,7 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_BlockX, int a_BlockY, if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true)) { m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaData | 0x4); + m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0); SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true); } } @@ -422,6 +439,7 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_BlockX, int a_BlockY, if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false)) { m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaData & 0xFFFFFFFB); + m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0); SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false); } } @@ -766,7 +784,7 @@ void cIncrementalRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_ { if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) { - m_World.BroadcastSoundEffect("random.fuse", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); + m_World.BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); m_World.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); } @@ -784,6 +802,7 @@ void cIncrementalRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a { cChunkInterface ChunkInterface(m_World.GetChunkMap()); cBlockDoorHandler::ChangeDoor(ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); + m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0); SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true); } } @@ -793,6 +812,7 @@ void cIncrementalRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a { cChunkInterface ChunkInterface(m_World.GetChunkMap()); cBlockDoorHandler::ChangeDoor(ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); + m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0); SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false); } } @@ -865,6 +885,7 @@ 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); SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true); } } @@ -873,6 +894,7 @@ void cIncrementalRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, i 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); SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false); } } From 147b9ed69456bd38d7f9167ad0b3aa249e5ede45 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 15 Feb 2014 16:27:40 +0100 Subject: [PATCH 031/106] Debuggers: Added a WebAdmin StressTest page. This page reloads content from the WebAdmin as fast as possible. --- MCServer/Plugins/Debuggers/Debuggers.lua | 87 ++++++++++++++++++++---- 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index 8345e2169..51b3a3a87 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -19,18 +19,18 @@ function Initialize(Plugin) cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick2); --]] - cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock); - cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem); - cPluginManager:AddHook(cPluginManager.HOOK_TAKE_DAMAGE, OnTakeDamage); - cPluginManager:AddHook(cPluginManager.HOOK_TICK, OnTick); - cPluginManager:AddHook(cPluginManager.HOOK_CHAT, OnChat); - cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY, OnPlayerRightClickingEntity); - cPluginManager:AddHook(cPluginManager.HOOK_WORLD_TICK, OnWorldTick); - cPluginManager:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated); - cPluginManager:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded); - cPluginManager:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage); + local PM = cPluginManager; + PM:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock); + PM:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem); + PM:AddHook(cPluginManager.HOOK_TAKE_DAMAGE, OnTakeDamage); + PM:AddHook(cPluginManager.HOOK_TICK, OnTick); + PM:AddHook(cPluginManager.HOOK_CHAT, OnChat); + PM:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY, OnPlayerRightClickingEntity); + PM:AddHook(cPluginManager.HOOK_WORLD_TICK, OnWorldTick); + PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated); + PM:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded); + PM:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage); - PM = cRoot:Get():GetPluginManager(); PM:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities"); PM:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities"); PM:BindCommand("/wool", "debuggers", HandleWoolCmd, "- Sets all your armor to blue wool"); @@ -55,7 +55,8 @@ function Initialize(Plugin) PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()"); PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords"); - Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers); + Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers) + Plugin:AddWebTab("StressTest", HandleRequest_StressTest) -- Enable the following line for BlockArea / Generator interface testing: -- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED); @@ -1038,6 +1039,68 @@ end +local g_Counter = 0 +local g_JavaScript = +[[ + +]] + +function HandleRequest_StressTest(a_Request) + if (a_Request.PostParams["counter"]) then + g_Counter = g_Counter + 1 + return tostring(g_Counter) + end + return g_JavaScript .. "

The counter below should be reloading as fast as possible

0
" +end + + + + + function OnPluginMessage(a_Client, a_Channel, a_Message) LOGINFO("Received a plugin message from client " .. a_Client:GetUsername() .. ": channel '" .. a_Channel .. "', message '" .. a_Message .. "'"); From a5b8d358450aa8208319f37226ef0b34687c0e37 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 15:37:10 +0000 Subject: [PATCH 032/106] Updated Plugin article + Adds reference to new SendMessage() functions --- .../APIDump/Writing-a-MCServer-plugin.html | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html index 1eec4842a..35c880b00 100644 --- a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html +++ b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html @@ -20,13 +20,7 @@

Let us begin. In order to begin development, we must firstly obtain a compiled copy of MCServer, and make sure that the Core plugin is within the Plugins folder, and activated. - Core handles much of the MCServer end-user experience and is a necessary component of - plugin development, as necessary plugin components depend on sone of its functions. -

-

- Next, we must obtain a copy of CoreMessaging.lua. This can be found - here. - This is used to provide messaging support that is compliant with MCServer standards. + Core handles much of the MCServer end-user experience and gameplay will be very bland without it.

Creating the basic template

@@ -41,7 +35,11 @@ function Initialize(Plugin) Plugin:SetName("NewPlugin") Plugin:SetVersion(1) - PLUGIN = Plugin + -- Hooks + + PLUGIN = Plugin -- NOTE: only needed if you want OnDisable() to use GetName() or something like that + + -- Command Bindings LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) return true @@ -58,7 +56,8 @@ end

  • Plugin:SetName sets the name of the plugin.
  • Plugin:SetVersion sets the revision number of the plugin. This must be an integer.
  • LOG logs to console a message, in this case, it prints that the plugin was initialised.
  • -
  • The PLUGIN variable just stores this plugin's object, so GetName() can be called in OnDisable (as no Plugin parameter is passed there, contrary to Initialize).
  • +
  • The PLUGIN variable just stores this plugin's object, so GetName() can be called in OnDisable (as no Plugin parameter is passed there, contrary to Initialize). + This global variable is only needed if you want to know the plugin details (name, etc.) when shutting down.
  • function OnDisable is called when the plugin is disabled, commonly when the server is shutting down. Perform cleanup and logging here.
  • Be sure to return true for this function, else MCS thinks you plugin had failed to initialise and prints a stacktrace with an error message. @@ -159,21 +158,23 @@ cPluginManager.BindCommand("/commandname", "permissionnode", FunctionToCall, " ~ a message. Again, see the API documentation for fuller details. But, you ask, how do we send a message to the client?

    - Remember that copy of CoreMessaging.lua that we downloaded earlier? Make sure that file is in your plugin folder, along with the main.lua file you are typing - your code in. Since MCS brings all the files together on JIT compile, we don't need to worry about requiring any files or such. Simply follow the below examples: + There are dedicated functions used for sending a player formatted messages. By format, I refer to coloured prefixes/coloured text (depending on configuration) + that clearly categorise what type of message a player is being sent. For example, an informational message has a yellow coloured [INFO] prefix, and a warning message + has a rose coloured [WARNING] prefix. A few of the most used functions are listed here, but see the API docs for more details. Look in the cRoot, cWorld, and cPlayer sections + for functions that broadcast to the entire server, the whole world, and a single player, respectively.

     -- Format: §yellow[INFO] §white%text% (yellow [INFO], white text following it)
     -- Use: Informational message, such as instructions for usage of a command
    -SendMessage(Player, "Usage: /explode [player]")
    +Player:SendMessageInfo("Usage: /explode [player]")
     
     -- Format: §green[INFO] §white%text% (green [INFO] etc.)
     -- Use: Success message, like when a command executes successfully
    -SendMessageSuccess(Player, "Notch was blown up!")
    +Player:SendMessageSuccess("Notch was blown up!")
     
     -- Format: §rose[INFO] §white%text% (rose coloured [INFO] etc.)
     -- Use: Failure message, like when a command was entered correctly but failed to run, such as when the destination player wasn't found in a /tp command
    -SendMessageFailure(Player, "Player Salted was not found")
    +Player:SendMessageFailure("Player Salted was not found")
     			

    Those are the basics. If you want to output text to the player for a reason other than the three listed above, and you want to colour the text, simply concatenate From 6eeeb2aa0129ee9664b6cf21a68517bd4b9c7348 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 15:51:49 +0000 Subject: [PATCH 033/106] Sizeable speed improvements to redstone + Moved all simulator data into individual chunks * Cleaned up parameters for functions and some code * Fixed repeaters powering off faster than they power on The main issue before was that, although the redstone simulator stored blocks to be simulated in individual cChunks, other data, such as powered lists, and etcetera, were global regardless of which chunk was being simulated. Therefore, with worlds with lots of redstone, each tick saw the ticking of chunks, which themselves iterated through the entire dataset needlessly, creating LOTS of lag. Should be better now :) --- src/Chunk.h | 14 +- .../IncrementalRedstoneSimulator.cpp | 161 ++++++++++-------- src/Simulator/IncrementalRedstoneSimulator.h | 35 ++-- 3 files changed, 127 insertions(+), 83 deletions(-) diff --git a/src/Chunk.h b/src/Chunk.h index 93eba217e..696690068 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -343,12 +343,17 @@ public: NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const; - // Simulator data: + // Per-chunk simulator data: cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; } cFluidSimulatorData * GetWaterSimulatorData(void) { return m_WaterSimulatorData; } cFluidSimulatorData * GetLavaSimulatorData (void) { return m_LavaSimulatorData; } cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; } - cRedstoneSimulatorChunkData & GetRedstoneSimulatorData(void) { return m_RedstoneSimulatorData; } + + cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return &m_RedstoneSimulatorData; } + cIncrementalRedstoneSimulator::PoweredBlocksList * GetRedstoneSimulatorPoweredBlocksList(void) { return &m_RedstoneSimulatorPoweredBlocksList; } + cIncrementalRedstoneSimulator::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; }; + cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; }; + cIncrementalRedstoneSimulator::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; }; cBlockEntity * GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ); cBlockEntity * GetBlockEntity(const Vector3i & a_BlockPos) { return GetBlockEntity(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); } @@ -419,7 +424,12 @@ private: cFluidSimulatorData * m_WaterSimulatorData; cFluidSimulatorData * m_LavaSimulatorData; cSandSimulatorChunkData m_SandSimulatorData; + cRedstoneSimulatorChunkData m_RedstoneSimulatorData; + cIncrementalRedstoneSimulator::PoweredBlocksList m_RedstoneSimulatorPoweredBlocksList; + cIncrementalRedstoneSimulator::LinkedBlocksList m_RedstoneSimulatorLinkedBlocksList; + cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList m_RedstoneSimulatorSimulatedPlayerToggleableList; + cIncrementalRedstoneSimulator::RepeatersDelayList m_RedstoneSimulatorRepeatersDelayList; // pick up a random block of this chunk diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 985fdee27..e6398a9eb 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -8,7 +8,6 @@ #include "../Entities/TNTEntity.h" #include "../Blocks/BlockTorch.h" #include "../Blocks/BlockDoor.h" -#include "../Blocks/BlockFenceGate.h" #include "../Piston.h" @@ -53,7 +52,8 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid // Checking only when a block is changed, as opposed to every tick, also improves performance - for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) + PoweredBlocksList * PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); + for (PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end(); ++itr) { if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -63,7 +63,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (!IsPotentialSource(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - m_PoweredBlocks.erase(itr); + &(*PoweredBlocks).erase(itr); break; } else if ( @@ -76,7 +76,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B ) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - m_PoweredBlocks.erase(itr); + &(*PoweredBlocks).erase(itr); break; } else if (Block == E_BLOCK_DAYLIGHT_SENSOR) @@ -94,21 +94,22 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (a_Chunk->GetTimeAlteredLight(SkyLight) <= 8) // Could use SkyLight - m_World.GetSkyDarkness(); { LOGD("cIncrementalRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level"); - m_PoweredBlocks.erase(itr); + &(*PoweredBlocks).erase(itr); break; } } } } - for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) + LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); + for (LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end(); ++itr) { if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { if (!IsPotentialSource(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - m_LinkedPoweredBlocks.erase(itr); + &(*LinkedPoweredBlocks).erase(itr); break; } else if ( @@ -119,7 +120,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B ) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - m_LinkedPoweredBlocks.erase(itr); + &(*LinkedPoweredBlocks).erase(itr); break; } } @@ -128,13 +129,14 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (!IsViableMiddleBlock(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - m_LinkedPoweredBlocks.erase(itr); + &(*LinkedPoweredBlocks).erase(itr); break; } } } - for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr) + SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); + for (SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks->begin(); itr != SimulatedPlayerToggleableBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -144,12 +146,13 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (!IsAllowedBlock(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - m_SimulatedPlayerToggleableBlocks.erase(itr); + &(*SimulatedPlayerToggleableBlocks).erase(itr); break; } } - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr) + RepeatersDelayList * RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); + for (RepeatersDelayList::iterator itr = RepeatersDelayList->begin(); itr != RepeatersDelayList->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -158,13 +161,13 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { - m_RepeatersDelayList.erase(itr); + &(*RepeatersDelayList).erase(itr); break; } } - cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData(); - for (cRedstoneSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr) + cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); + for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr) { if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block { @@ -185,7 +188,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B return; } - ChunkData.push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); + RedstoneSimulatorChunkData->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); } @@ -199,20 +202,26 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int // The easiest way to make this more efficient is probably just to reduce code within the handlers that put too much strain on server, like getting or setting blocks // A marking dirty system might be a TODO for later on, perhaps - cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData(); - if (ChunkData.empty()) + m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); + if (m_RedstoneSimulatorChunkData->empty()) { return; } + m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); + m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); + m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); + m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); + m_Chunk = a_Chunk; + int BaseX = a_Chunk->GetPosX() * cChunkDef::Width; int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width; - for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(); dataitr != ChunkData.end();) + for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();) { if (dataitr->DataTwo) { - dataitr = ChunkData.erase(dataitr); + dataitr = m_RedstoneSimulatorChunkData->erase(dataitr); continue; } @@ -293,6 +302,31 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int +void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) +{ + if ( + ((a_BlockX % cChunkDef::Width) >= cChunkDef::Width - 2) || + ((a_BlockX % cChunkDef::Width) <= cChunkDef::Width + 2) || + ((a_BlockZ % cChunkDef::Width) >= cChunkDef::Width - 2) || + ((a_BlockZ % cChunkDef::Width) <= cChunkDef::Width + 2) + ) // Are we on a chunk boundary? ± 2 because of LinkedPowered blocks + { + // On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk) + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ)); + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ)); + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1)); + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1)); + return; + } + + // Not on boundary, just alert this chunk for speed + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); +} + + + + void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState) { @@ -318,22 +352,6 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_Bloc { // There was a match, torch goes off m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_OFF, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ)); - - float Pitch = (((1.0F-0.0F)*((float)rand()/RAND_MAX)) - ((1.0F-0.0F)*((float)rand()/RAND_MAX))) * 0.8F; - m_World.BroadcastSoundEffect("random.fizz", - ((int) (a_BlockX + 0.5F) * 8.0), - ((int) (a_BlockY + 0.5F) * 8.0), - ((int) (a_BlockZ + 0.5F) * 8.0), - 0.5F, - 2.6F + Pitch); - - for (int l = 0; l < 5; ++l) { - float d0 = a_BlockX + (double(rand())/RAND_MAX) * 0.6F + 0.2F; - float d1 = a_BlockY + (double(rand())/RAND_MAX) * 0.6F + 0.2F; - float d2 = a_BlockZ + (double(rand())/RAND_MAX) * 0.6F + 0.2F; - m_World.BroadcastParticleEffect("smoke", d0, d1, d2, 0.0F, 0.0F, 0.0F, 0.01F, 1); - } - return; } @@ -424,7 +442,7 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_BlockX, int a_BlockY, { cChunkInterface ChunkInterface(m_World.GetChunkMap()); NIBBLETYPE MetaData = ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); - + if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) { if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true)) @@ -432,7 +450,7 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_BlockX, int a_BlockY, m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaData | 0x4); m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0); SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true); - } + } } else { @@ -554,7 +572,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block } } - if (TimesMetaSmaller == TimesFoundAWire) + if ((TimesMetaSmaller == TimesFoundAWire) && (MyMeta != 0)) { // All surrounding metas were smaller - self must have been a wire that was // transferring power to other wires around. @@ -563,7 +581,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, 0); // SetMeta & WakeUpSims doesn't seem to work here, so SetBlock return; // No need to process block power sets because self not powered } - else + else if (MyMeta != MetaToSet) { m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaToSet); } @@ -587,12 +605,15 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block { case REDSTONE_NONE: { - SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); + SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); + SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); + SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); + SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); + SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE); - SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YP, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE); break; @@ -638,14 +659,14 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_B if (IsSelfPowered && !IsOn) // Queue a power change if I am receiving power but not on { - QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, true); + QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, true); } else if (!IsSelfPowered && IsOn) // Queue a power change if I am not receiving power but on { - QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, false); + QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, false); } - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr) + for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -699,7 +720,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_B { m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta); } - m_RepeatersDelayList.erase(itr); // We can remove off repeaters which don't need further updating + m_RepeatersDelayList->erase(itr); // We can remove off repeaters which don't need further updating return; } } @@ -1060,7 +1081,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list + for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list { if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -1076,7 +1097,7 @@ bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_BlockX, int a bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) // Check linked powered list + for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list { if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -1094,7 +1115,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY { // Repeaters cannot be powered by any face except their back; verify that this is true for a source - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) + for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } @@ -1124,7 +1145,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY } } - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) + for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } @@ -1165,7 +1186,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, int OldX = a_BlockX, OldY = a_BlockY, OldZ = a_BlockZ; eBlockFace Face = cPiston::MetaDataToDirection(a_Meta); - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) + for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } @@ -1181,7 +1202,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, a_BlockZ = OldZ; } - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) + for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } @@ -1204,7 +1225,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ) { - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) + for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } @@ -1214,7 +1235,7 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, in } } - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) + for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } @@ -1232,7 +1253,7 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, in bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered) { - for (SimulatedPlayerToggleableList::const_iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr) + for (SimulatedPlayerToggleableList::const_iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr) { if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -1375,7 +1396,9 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, return; } - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list + PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorPoweredBlocksList(); + + for (PoweredBlocksList::const_iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list { if ( itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) && @@ -1390,7 +1413,7 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, sPoweredBlocks RC; RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ); - m_PoweredBlocks.push_back(RC); + Powered->push_back(RC); } @@ -1415,7 +1438,9 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( return; } - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) // Check linked powered list + LinkedBlocksList * Linked = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorLinkedBlocksList(); + + for (LinkedBlocksList::const_iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list { if ( itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) && @@ -1432,7 +1457,7 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.a_MiddlePos = Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ); RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ); - m_LinkedPoweredBlocks.push_back(RC); + Linked->push_back(RC); } @@ -1441,7 +1466,7 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered) { - for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr) + for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -1465,16 +1490,16 @@ void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_Bl sSimulatedPlayerToggleableList RC; RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.WasLastStatePowered = WasLastStatePowered; - m_SimulatedPlayerToggleableBlocks.push_back(RC); + m_SimulatedPlayerToggleableBlocks->push_back(RC); } -void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn) +void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn) { - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr) + for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) { if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -1484,7 +1509,7 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a } // Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit - itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + (ShouldPowerOn ? 1 : 0)) * 2; // See below for description + itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description itr->a_ElapsedTicks = 0; itr->ShouldPowerOn = ShouldPowerOn; return; @@ -1492,18 +1517,16 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a } // Self not in list, add self to list - sRepeatersDelayList RC; + sRepeatersDelayList RC; RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.) // * 2 because apparently, MCS ticks are way faster than vanilla ticks, so repeater aren't noticeably delayed - // We don't +1 when powering off because everything seems to already delay a tick when powering off, why? No idea :P - RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + (ShouldPowerOn ? 1 : 0)) * 2; - + RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; RC.a_ElapsedTicks = 0; RC.ShouldPowerOn = ShouldPowerOn; - m_RepeatersDelayList.push_back(RC); + m_RepeatersDelayList->push_back(RC); return; } diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index bcf89bb82..aea668996 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -3,7 +3,7 @@ #include "RedstoneSimulator.h" -/// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used +/// Per-chunk data for the simulator, specified individual chunks to simulate typedef cCoordWithBlockAndBoolVector cRedstoneSimulatorChunkData; @@ -21,7 +21,8 @@ public: virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; - virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return IsRedstone(a_BlockType); } + virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); } + virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override; enum eRedstoneDirection { @@ -57,22 +58,28 @@ private: struct sRepeatersDelayList { Vector3i a_BlockPos; - short a_DelayTicks; - short a_ElapsedTicks; + unsigned char a_DelayTicks; + unsigned char a_ElapsedTicks; bool ShouldPowerOn; }; - + +public: + typedef std::vector PoweredBlocksList; typedef std::vector LinkedBlocksList; typedef std::vector SimulatedPlayerToggleableList; typedef std::vector RepeatersDelayList; - PoweredBlocksList m_PoweredBlocks; - LinkedBlocksList m_LinkedPoweredBlocks; - SimulatedPlayerToggleableList m_SimulatedPlayerToggleableBlocks; - RepeatersDelayList m_RepeatersDelayList; +private: + + cRedstoneSimulatorChunkData * m_RedstoneSimulatorChunkData; + PoweredBlocksList * m_PoweredBlocks; + LinkedBlocksList * m_LinkedPoweredBlocks; + SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks; + RepeatersDelayList * m_RepeatersDelayList; virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override; + cChunk * m_Chunk; // We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly // In addition to being non-performant, it would stop the player from actually breaking said device @@ -84,8 +91,6 @@ private: void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ); /** Handles levers */ void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ); - /** Handles Fence Gates */ - void HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ); /** Handles buttons */ void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType); /** Handles daylight sensors */ @@ -118,6 +123,8 @@ private: void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType); /** Handles trapdoors */ void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ); + /** Handles fence gates */ + void HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ); /** Handles noteblocks */ void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ); /* ===================== */ @@ -134,7 +141,7 @@ private: /** Marks all blocks immediately surrounding a coordinate as powered */ void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock); /** Queues a repeater to be powered or unpowered */ - void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn); + void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn); /** Returns if a coordinate is powered or linked powered */ bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { return AreCoordsDirectlyPowered(a_BlockX, a_BlockY, a_BlockZ) || AreCoordsLinkedPowered(a_BlockX, a_BlockY, a_BlockZ); } @@ -267,3 +274,7 @@ private: } } }; + + + + From 8fbb936b6326b46fb3f4b85d654288a6b2ccc240 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 15:53:02 +0000 Subject: [PATCH 034/106] Fixed TNT fizzing everywhere --- src/Items/ItemLighter.h | 2 +- src/Mobs/Creeper.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h index 6681a08d4..cc7daeb08 100644 --- a/src/Items/ItemLighter.h +++ b/src/Items/ItemLighter.h @@ -33,7 +33,7 @@ public: case E_BLOCK_TNT: { // Activate the TNT: - a_World->BroadcastSoundEffect("random.fuse", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); + a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0); break; diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp index 2e1ece865..ff0abfdca 100644 --- a/src/Mobs/Creeper.cpp +++ b/src/Mobs/Creeper.cpp @@ -79,7 +79,7 @@ void cCreeper::Attack(float a_Dt) if (!m_bIsBlowing) { - m_World->BroadcastSoundEffect("random.fuse", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); + m_World->BroadcastSoundEffect("game.tnt.primed", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); m_bIsBlowing = true; m_World->BroadcastEntityMetadata(*this); } From 0040a88b9b40817c04e54259fcb61e31dc4f4213 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sat, 15 Feb 2014 19:51:05 +0100 Subject: [PATCH 035/106] If a player is called "Notch" he drops an apple. http://minecraft.gamepedia.com/Notch --- src/Entities/Player.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 286d43cf6..cf5a8edfe 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -839,6 +839,12 @@ void cPlayer::KilledBy(cEntity * a_Killer) cItems Pickups; m_Inventory.CopyToItems(Pickups); m_Inventory.Clear(); + + if (GetName() == "Notch") + { + Pickups.Add(cItem(E_ITEM_RED_APPLE)); + } + m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10); SaveToDisk(); // Save it, yeah the world is a tough place ! From c494d0f6f2645baa4fd356ef2250dbc3202f883a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 19:56:45 +0000 Subject: [PATCH 036/106] A fix and an improvement * Fixed a special case with the wrong ChunkX/Z values being used to calculate a relative position * Simplified data structure adding and removing operations (no more pointers!) - Removed one character of whitespace :D --- .../IncrementalRedstoneSimulator.cpp | 63 ++++++++++++------- src/Simulator/IncrementalRedstoneSimulator.h | 3 +- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index e6398a9eb..4e165bd36 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -31,7 +31,7 @@ cIncrementalRedstoneSimulator::~cIncrementalRedstoneSimulator() -void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) +void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk, cChunk * a_OtherChunk) { if ((a_Chunk == NULL) || !a_Chunk->IsValid()) { @@ -42,12 +42,27 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B return; } - int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; - int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; - + // We may be called with coordinates in a chunk that is not the first chunk parameter + // In that case, the actual chunk (which the coordinates are in), will be passed as the second parameter + // Use that Chunk pointer to get a relative position + + int RelX = 0; + int RelZ = 0; BLOCKTYPE Block; NIBBLETYPE Meta; - a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + + if (a_OtherChunk != NULL) + { + RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width; + RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width; + a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + } + else + { + RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; + RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; + a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + } // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid // Checking only when a block is changed, as opposed to every tick, also improves performance @@ -63,7 +78,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (!IsPotentialSource(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - &(*PoweredBlocks).erase(itr); + PoweredBlocks->erase(itr); break; } else if ( @@ -76,7 +91,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B ) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - &(*PoweredBlocks).erase(itr); + PoweredBlocks->erase(itr); break; } else if (Block == E_BLOCK_DAYLIGHT_SENSOR) @@ -94,7 +109,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (a_Chunk->GetTimeAlteredLight(SkyLight) <= 8) // Could use SkyLight - m_World.GetSkyDarkness(); { LOGD("cIncrementalRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level"); - &(*PoweredBlocks).erase(itr); + PoweredBlocks->erase(itr); break; } } @@ -102,15 +117,16 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B } LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); - for (LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end(); ++itr) + // We loop through all values (insteading of breaking out at the first) to make sure everything is gone, as there can be multiple SourceBlock entries for one AddBlock coordinate + for (LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end();) { if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { if (!IsPotentialSource(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - &(*LinkedPoweredBlocks).erase(itr); - break; + itr = LinkedPoweredBlocks->erase(itr); + continue; } else if ( // Things that can send power through a block but which depends on meta @@ -120,8 +136,8 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B ) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - &(*LinkedPoweredBlocks).erase(itr); - break; + itr = LinkedPoweredBlocks->erase(itr); + continue; } } else if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) @@ -129,13 +145,14 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (!IsViableMiddleBlock(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - &(*LinkedPoweredBlocks).erase(itr); - break; + itr = LinkedPoweredBlocks->erase(itr); + continue; } } + ++itr; } - SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); + SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); for (SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks->begin(); itr != SimulatedPlayerToggleableBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) @@ -146,7 +163,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if (!IsAllowedBlock(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - &(*SimulatedPlayerToggleableBlocks).erase(itr); + SimulatedPlayerToggleableBlocks->erase(itr); break; } } @@ -161,7 +178,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { - &(*RepeatersDelayList).erase(itr); + RepeatersDelayList->erase(itr); break; } } @@ -313,10 +330,12 @@ void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_Blo { // On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk) AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ)); - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ)); - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1)); - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1)); + // Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position + // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordiantes are in + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1), a_Chunk); return; } diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index aea668996..e6bc28621 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -78,7 +78,8 @@ private: SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks; RepeatersDelayList * m_RepeatersDelayList; - virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override; + virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); } + void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk, cChunk * a_OtherChunk = NULL); cChunk * m_Chunk; // We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly From d273cc414241e11d56d336535501955d413cec89 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 20:22:51 +0000 Subject: [PATCH 037/106] Added a 'default:' for SimChunk()'s switch --- src/Simulator/IncrementalRedstoneSimulator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 4e165bd36..4f592d253 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -311,6 +311,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int HandlePressurePlate(a_X, dataitr->y, a_Z, dataitr->Data); break; } + default: LOGD("Unhandled block (!) or unimplemented redstone block: %s", ItemToString(dataitr->Data).c_str()); break; } ++dataitr; } From 0f1f7583aeea65335b2ee051585a857b1142a927 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 15 Feb 2014 23:16:44 +0100 Subject: [PATCH 038/106] Implemented cCompositeChat. This allows plugins to send composite chat messages, containing URLs, commands to run and cmdline suggestions. Fixes #678. --- src/Bindings/AllToLua.pkg | 1 + src/ClientHandle.cpp | 12 +- src/ClientHandle.h | 4 +- src/CompositeChat.cpp | 206 ++++++++++++++++++++++++++++ src/CompositeChat.h | 172 +++++++++++++++++++++++ src/Defines.h | 9 +- src/Entities/Player.h | 1 + src/Protocol/Protocol.h | 2 + src/Protocol/Protocol125.cpp | 38 +++++ src/Protocol/Protocol125.h | 1 + src/Protocol/Protocol17x.cpp | 153 +++++++++++++++++++++ src/Protocol/Protocol17x.h | 38 +++-- src/Protocol/ProtocolRecognizer.cpp | 10 ++ src/Protocol/ProtocolRecognizer.h | 1 + src/Root.cpp | 14 +- src/Root.h | 6 +- src/World.cpp | 20 ++- src/World.h | 4 +- 18 files changed, 671 insertions(+), 21 deletions(-) create mode 100644 src/CompositeChat.cpp create mode 100644 src/CompositeChat.h diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg index f65aed9bb..6c295102f 100644 --- a/src/Bindings/AllToLua.pkg +++ b/src/Bindings/AllToLua.pkg @@ -70,6 +70,7 @@ $cfile "../Generating/ChunkDesc.h" $cfile "../CraftingRecipes.h" $cfile "../UI/Window.h" $cfile "../Mobs/Monster.h" +$cfile "../CompositeChat.h" diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 1b3ebc3d4..f8a707324 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -31,6 +31,7 @@ #include "MersenneTwister.h" #include "Protocol/ProtocolRecognizer.h" +#include "CompositeChat.h" @@ -1729,7 +1730,7 @@ void cClientHandle::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlock -void cClientHandle::SendChat(const AString & a_Message, ChatPrefixCodes a_ChatPrefix, const AString & a_AdditionalData) +void cClientHandle::SendChat(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData) { bool ShouldAppendChatPrefixes = true; @@ -1840,6 +1841,15 @@ void cClientHandle::SendChat(const AString & a_Message, ChatPrefixCodes a_ChatPr +void cClientHandle::SendChat(const cCompositeChat & a_Message) +{ + m_Protocol->SendChat(a_Message); +} + + + + + void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { ASSERT(m_Player != NULL); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index d9a86d983..034fe07c2 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -34,6 +34,7 @@ class cWindow; class cFallingBlock; class cItemHandler; class cWorld; +class cCompositeChat; @@ -89,7 +90,8 @@ public: void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage); void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes); - void SendChat (const AString & a_Message, ChatPrefixCodes a_ChatPrefix, const AString & a_AdditionalData = ""); + void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); + void SendChat (const cCompositeChat & a_Message); void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer); void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player); void SendDestroyEntity (const cEntity & a_Entity); diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp new file mode 100644 index 000000000..16ae58f56 --- /dev/null +++ b/src/CompositeChat.cpp @@ -0,0 +1,206 @@ + +// CompositeChat.cpp + +// Implements the cCompositeChat class used to wrap a chat message with multiple parts (text, url, cmd) + +#include "Globals.h" +#include "CompositeChat.h" + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat: + +cCompositeChat::cCompositeChat(void) : + m_MessageType(mtCustom) +{ +} + + + + + +cCompositeChat::cCompositeChat(const AString & a_ParseText) : + m_MessageType(mtCustom) +{ + ParseText(a_ParseText); +} + + + + + +cCompositeChat::~cCompositeChat() +{ + Clear(); +} + + + + + +void cCompositeChat::Clear(void) +{ + for (cParts::iterator itr = m_Parts.begin(), end = m_Parts.end(); itr != end; ++itr) + { + delete *itr; + } // for itr - m_Parts[] + m_Parts.clear(); +} + + + + + +void cCompositeChat::AddTextPart(const AString & a_Message, const AString & a_Style) +{ + m_Parts.push_back(new cTextPart(a_Message, a_Style)); +} + + + + + +void cCompositeChat::AddClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style) +{ + m_Parts.push_back(new cClientTranslatedPart(a_TranslationID, a_Parameters, a_Style)); +} + + + + + +void cCompositeChat::AddUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style) +{ + m_Parts.push_back(new cUrlPart(a_Text, a_Url, a_Style)); +} + + + + + +void cCompositeChat::AddRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style) +{ + m_Parts.push_back(new cRunCommandPart(a_Text, a_Command, a_Style)); +} + + + + + +void cCompositeChat::AddSuggestCommandPart(const AString & a_Text, const AString & a_SuggestedCommand, const AString & a_Style) +{ + m_Parts.push_back(new cSuggestCommandPart(a_Text, a_SuggestedCommand, a_Style)); +} + + + + + +void cCompositeChat::ParseText(const AString & a_ParseText) +{ + // TODO +} + + + + + +void cCompositeChat::SetMessageType(eMessageType a_MessageType) +{ + m_MessageType = a_MessageType; +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat::cBasePart: + +cCompositeChat::cBasePart::cBasePart(cCompositeChat::ePartType a_PartType, const AString & a_Text, const AString & a_Style) : + m_PartType(a_PartType), + m_Text(a_Text), + m_Style(a_Style) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat::cTextPart: + +cCompositeChat::cTextPart::cTextPart(const AString & a_Text, const AString &a_Style) : + super(ptText, a_Text, a_Style) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat::cClientTranslatedPart: + +cCompositeChat::cClientTranslatedPart::cClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style) : + super(ptClientTranslated, a_TranslationID, a_Style), + m_Parameters(a_Parameters) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat::cUrlPart: + +cCompositeChat::cUrlPart::cUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style) : + super(ptUrl, a_Text, a_Style), + m_Url(a_Url) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat::cCommandPart: + +cCompositeChat::cCommandPart::cCommandPart(ePartType a_PartType, const AString & a_Text, const AString & a_Command, const AString & a_Style) : + super(a_PartType, a_Text, a_Style), + m_Command(a_Command) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat::cRunCommandPart: + +cCompositeChat::cRunCommandPart::cRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style) : + super(ptRunCommand, a_Text, a_Command, a_Style) +{ +} + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCompositeChat::cSuggestCommandPart: + +cCompositeChat::cSuggestCommandPart::cSuggestCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style) : + super(ptSuggestCommand, a_Text, a_Command, a_Style) +{ +} + + + + diff --git a/src/CompositeChat.h b/src/CompositeChat.h new file mode 100644 index 000000000..e220f6345 --- /dev/null +++ b/src/CompositeChat.h @@ -0,0 +1,172 @@ + +// CompositeChat.h + +// Declares the cCompositeChat class used to wrap a chat message with multiple parts (text, url, cmd) + +#include "Defines.h" + + + + + +// tolua_begin +/** Container for a single chat message composed of multiple functional parts. +Each part corresponds roughly to the behavior supported by the client messaging: + - plain text, optionaly colorized / styled + - clickable URLs + - clickable commands (run) + - 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 +If the protocol version doesn't support all the features, it degrades gracefully. +*/ +class cCompositeChat +{ +public: + // tolua_end + + enum ePartType + { + ptText, + ptClientTranslated, + ptUrl, + ptRunCommand, + ptSuggestCommand, + } ; + + class cBasePart + { + public: + ePartType m_PartType; + AString m_Text; + AString m_Style; + + cBasePart(ePartType a_PartType, const AString & a_Text, const AString & a_Style = ""); + } ; + + class cTextPart : + public cBasePart + { + typedef cBasePart super; + public: + cTextPart(const AString & a_Text, const AString & a_Style = ""); + } ; + + class cClientTranslatedPart : + public cBasePart + { + typedef cBasePart super; + public: + AStringVector m_Parameters; + + cClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style = ""); + } ; + + class cUrlPart : + public cBasePart + { + typedef cBasePart super; + public: + AString m_Url; + + cUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style = ""); + } ; + + class cCommandPart : + public cBasePart + { + typedef cBasePart super; + public: + AString m_Command; + + cCommandPart(ePartType a_PartType, const AString & a_Text, const AString & a_Command, const AString & a_Style = ""); + } ; + + class cRunCommandPart : + public cCommandPart + { + typedef cCommandPart super; + public: + cRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style = ""); + } ; + + class cSuggestCommandPart : + public cCommandPart + { + typedef cCommandPart super; + public: + cSuggestCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style = ""); + } ; + + typedef std::vector cParts; + + // tolua_begin + + /** Creates a new empty chat message */ + cCompositeChat(void); + + /** Creates a new chat message and parses the text into parts. + Recognizes "http:" and "https:" links and @color-codes. + Uses ParseText() for the actual parsing. */ + cCompositeChat(const AString & a_ParseText); + + ~cCompositeChat(); + + /** Removes all parts from the object. */ + void Clear(void); + + /** 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. */ + void AddClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style = ""); + + // tolua_begin + + /** 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"); + + /** 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"); + + /** 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"); + + /** Parses text into various parts, adds those. + Recognizes "http:" and "https:" URLs and @color-codes. */ + void ParseText(const AString & a_ParseText); + + /** 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; } + + // tolua_end + + const cParts & GetParts(void) const { return m_Parts; } + +protected: + /** All the parts that */ + cParts m_Parts; + + /** The message type, as indicated by prefixes. */ + eMessageType m_MessageType; +} ; // tolua_export + + + + diff --git a/src/Defines.h b/src/Defines.h index 290f862ef..f33d1ae56 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -441,7 +441,10 @@ inline float GetSpecialSignf( float a_Val ) -enum ChatPrefixCodes + +// tolua_begin + +enum eMessageType { // http://forum.mc-server.org/showthread.php?tid=1212 // MessageType... @@ -458,7 +461,9 @@ enum ChatPrefixCodes mtLeave, // A player has left the server }; -// tolua_begin + + + /** Normalizes an angle in degrees to the [-180, +180) range: */ inline double NormalizeAngleDegrees(const double a_Degrees) diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 7db9544cb..53e4b56db 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -203,6 +203,7 @@ public: void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); } void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } void SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); } + void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); } const AString & GetName(void) const { return m_PlayerName; } void SetName(const AString & a_Name) { m_PlayerName = a_Name; } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 791082537..f5b9fd403 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -28,6 +28,7 @@ class cWorld; class cMonster; class cChunkDataSerializer; class cFallingBlock; +class cCompositeChat; @@ -58,6 +59,7 @@ public: virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0; virtual void SendChat (const AString & a_Message) = 0; + virtual void SendChat (const cCompositeChat & a_Message) = 0; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0; virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) = 0; virtual void SendDestroyEntity (const cEntity & a_Entity) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 73d21161c..7020699d1 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -32,6 +32,8 @@ Documentation: #include "../Mobs/IncludeAllMonsters.h" +#include "../CompositeChat.h" + @@ -233,6 +235,42 @@ void cProtocol125::SendChat(const AString & a_Message) +void cProtocol125::SendChat(const cCompositeChat & a_Message) +{ + // This version doesn't support composite messages, just extract each part's text and use it: + AString Msg; + const cCompositeChat::cParts & Parts = a_Message.GetParts(); + for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) + { + switch ((*itr)->m_PartType) + { + case cCompositeChat::ptText: + case cCompositeChat::ptClientTranslated: + case cCompositeChat::ptRunCommand: + case cCompositeChat::ptSuggestCommand: + { + Msg.append((*itr)->m_Text); + break; + } + case cCompositeChat::ptUrl: + { + Msg.append(((cCompositeChat::cUrlPart *)(*itr))->m_Url); + break; + } + } // switch (PartType) + } // for itr - Parts[] + + // Send the message: + cCSLock Lock(m_CSPacket); + WriteByte (PACKET_CHAT); + WriteString(Msg); + Flush(); +} + + + + + void cProtocol125::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { cCSLock Lock(m_CSPacket); diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index cd15ab518..1a3209333 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -33,6 +33,7 @@ public: virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 7eaf106cf..5aa18300c 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -8,6 +8,7 @@ Implements the 1.7.x protocol classes: */ #include "Globals.h" +#include "json/json.h" #include "Protocol17x.h" #include "ChunkDataSerializer.h" #include "../ClientHandle.h" @@ -25,6 +26,7 @@ Implements the 1.7.x protocol classes: #include "../Mobs/IncludeAllMonsters.h" #include "../UI/Window.h" #include "../BlockEntities/CommandBlockEntity.h" +#include "../CompositeChat.h" @@ -200,6 +202,78 @@ void cProtocol172::SendChat(const AString & a_Message) +void cProtocol172::SendChat(const cCompositeChat & a_Message) +{ + // Compose the complete Json string to send: + Json::Value msg; + msg["text"] = ""; // The client crashes without this + const cCompositeChat::cParts & Parts = a_Message.GetParts(); + for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) + { + Json::Value Part; + switch ((*itr)->m_PartType) + { + case cCompositeChat::ptText: + { + Part["text"] = (*itr)->m_Text; + AddChatPartStyle(Part, (*itr)->m_Style); + break; + } + + case cCompositeChat::ptClientTranslated: + { + const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr; + Part["translate"] = p.m_Text; + Json::Value With; + for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr) + { + With.append(*itrW); + } + if (!p.m_Parameters.empty()) + { + Part["with"] = With; + } + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptUrl: + { + const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Url; + Url["action"] = "open_url"; + Url["value"] = p.m_Url; + Part["clickEvent"] = Url; + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptSuggestCommand: + case cCompositeChat::ptRunCommand: + { + const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Cmd; + Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command"; + Cmd["value"] = p.m_Command; + Part["clickEvent"] = Cmd; + AddChatPartStyle(Part, p.m_Style); + break; + } + } + msg["extra"].append(Part); + } // for itr - Parts[] + + // Send the message to the client: + cPacketizer Pkt(*this, 0x02); + Pkt.WriteString(msg.toStyledString()); +} + + + + + void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { // Serialize first, before creating the Packetizer (the packetizer locks a CS) @@ -1979,6 +2053,85 @@ void cProtocol172::StartEncryption(const Byte * a_Key) +void cProtocol172::AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) +{ + size_t len = a_PartStyle.length(); + for (size_t i = 0; i < len; i++) + { + 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 '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[] +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cProtocol172::cPacketizer: diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 6a75e41c8..d19be0f05 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -36,6 +36,16 @@ Declares the 1.7.x protocol classes: +// fwd: +namespace Json +{ + class Value; +} + + + + + class cProtocol172 : public cProtocol { @@ -45,16 +55,17 @@ public: cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); - /// Called when client sends some data: + /** Called when client sends some data: */ virtual void DataReceived(const char * a_Data, int a_Size) override; - /// Sending stuff to clients (alphabetically sorted): + /** Sending stuff to clients (alphabetically sorted): */ virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; @@ -117,7 +128,7 @@ public: protected: - /// Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed + /** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */ class cPacketizer { public: @@ -206,16 +217,16 @@ protected: AString m_AuthServerID; - /// State of the protocol. 1 = status, 2 = login, 3 = game + /** State of the protocol. 1 = status, 2 = login, 3 = game */ UInt32 m_State; - /// Buffer for the received data + /** Buffer for the received data */ cByteBuffer m_ReceivedData; - /// Buffer for composing the outgoing packets, through cPacketizer + /** Buffer for composing the outgoing packets, through cPacketizer */ cByteBuffer m_OutPacketBuffer; - /// Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) + /** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */ cByteBuffer m_OutPacketLenBuffer; bool m_IsEncrypted; @@ -227,7 +238,7 @@ protected: cFile m_CommLogFile; - /// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets + /** Adds the received (unencrypted) data to m_ReceivedData, parses complete packets */ void AddReceivedData(const char * a_Data, int a_Size); /** Reads and handles the packet. The packet length and type have already been read. @@ -268,21 +279,24 @@ protected: void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer); - /// Writes an entire packet into the output stream. a_Packet is expected to start with the packet type; data length is prepended here. + /** Writes an entire packet into the output stream. a_Packet is expected to start with the packet type; data length is prepended here. */ void WritePacket(cByteBuffer & a_Packet); - /// Sends the data to the client, encrypting them if needed. + /** Sends the data to the client, encrypting them if needed. */ virtual void SendData(const char * a_Data, int a_Size) override; void SendCompass(const cWorld & a_World); - /// Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data + /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */ bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item); - /// Parses item metadata as read by ReadItem(), into the item enchantments. + /** Parses item metadata as read by ReadItem(), into the item enchantments. */ void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); void StartEncryption(const Byte * a_Key); + + /** Adds the chat part's style (represented by the part's stylestring) into the Json object. */ + void AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle); } ; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 32409c2aa..6e51ee9cd 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -159,6 +159,16 @@ void cProtocolRecognizer::SendChat(const AString & a_Message) +void cProtocolRecognizer::SendChat(const cCompositeChat & a_Message) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendChat(a_Message); +} + + + + + void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { ASSERT(m_Protocol != NULL); diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index f58c66d10..800163be6 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -68,6 +68,7 @@ public: virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; diff --git a/src/Root.cpp b/src/Root.cpp index 749fbd288..415a26dd3 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -543,7 +543,7 @@ void cRoot::ReloadGroups(void) -void cRoot::LoopWorldsAndBroadcastChat(const AString & a_Message, ChatPrefixCodes a_ChatPrefix) +void cRoot::LoopWorldsAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix) { for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr) { @@ -555,6 +555,18 @@ void cRoot::LoopWorldsAndBroadcastChat(const AString & a_Message, ChatPrefixCode +void cRoot::BroadcastChat(const cCompositeChat & a_Message) +{ + for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr) + { + itr->second->BroadcastChat(a_Message); + } // for itr - m_WorldsByName[] +} + + + + + bool cRoot::ForEachPlayer(cPlayerListCallback & a_Callback) { for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2) diff --git a/src/Root.h b/src/Root.h index 13e208b8d..a1a3ca6a2 100644 --- a/src/Root.h +++ b/src/Root.h @@ -20,7 +20,8 @@ class cPluginManager; class cServer; class cWorld; class cPlayer; -class cCommandOutputCallback ; +class cCommandOutputCallback; +class cCompositeChat; typedef cItemCallback cPlayerListCallback; typedef cItemCallback cWorldListCallback; @@ -108,7 +109,7 @@ public: /// Finds a player from a partial or complete player name and calls the callback - case-insensitive bool FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << - void LoopWorldsAndBroadcastChat(const AString & a_Message, ChatPrefixCodes a_ChatPrefix); + void LoopWorldsAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix); void BroadcastChatJoin (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtJoin); } void BroadcastChatLeave (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtLeave); } void BroadcastChatDeath (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtDeath); } @@ -122,6 +123,7 @@ public: void BroadcastChatSuccess(const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtSuccess); } void BroadcastChatWarning(const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtWarning); } void BroadcastChatFatal (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtFailure); } + void BroadcastChat (const cCompositeChat & a_Message); /// Returns the textual description of the protocol version: 49 -> "1.4.4". Provided specifically for Lua API static AString GetProtocolVersionTextFromInt(int a_ProtocolVersionNum); diff --git a/src/World.cpp b/src/World.cpp index cb07caa5d..d1a13794c 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1747,7 +1747,7 @@ void cWorld::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cons -void cWorld::LoopPlayersAndBroadcastChat(const AString & a_Message, ChatPrefixCodes a_ChatPrefix, const cClientHandle * a_Exclude) +void cWorld::LoopPlayersAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix, const cClientHandle * a_Exclude) { cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) @@ -1765,6 +1765,24 @@ void cWorld::LoopPlayersAndBroadcastChat(const AString & a_Message, ChatPrefixCo +void cWorld::BroadcastChat(const cCompositeChat & a_Message, const cClientHandle * a_Exclude) +{ + cCSLock Lock(m_CSPlayers); + for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + cClientHandle * ch = (*itr)->GetClientHandle(); + if ((ch == a_Exclude) || (ch == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + { + continue; + } + ch->SendChat(a_Message); + } +} + + + + + void cWorld::BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude) { m_ChunkMap->BroadcastChunkData(a_ChunkX, a_ChunkZ, a_Serializer, a_Exclude); diff --git a/src/World.h b/src/World.h index ca1b7dcc5..2fbc51038 100644 --- a/src/World.h +++ b/src/World.h @@ -46,6 +46,7 @@ class cDispenserEntity; class cFurnaceEntity; class cNoteEntity; class cMobCensus; +class cCompositeChat; typedef std::list< cPlayer * > cPlayerList; @@ -167,7 +168,7 @@ public: void BroadcastBlockBreakAnimation(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = NULL); void BroadcastBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude - void LoopPlayersAndBroadcastChat(const AString & a_Message, ChatPrefixCodes a_ChatPrefix, const cClientHandle * a_Exclude = NULL); + void LoopPlayersAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix, const cClientHandle * a_Exclude = NULL); void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtDeath, a_Exclude); } // tolua_begin @@ -177,6 +178,7 @@ public: void BroadcastChatSuccess(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtSuccess, a_Exclude); } void BroadcastChatWarning(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtWarning, a_Exclude); } void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtFailure, a_Exclude); } + void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = NULL); // tolua_end void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL); From 3582c4bc60beb1f8a093c435131d9d93e337a659 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 15 Feb 2014 23:17:42 +0100 Subject: [PATCH 039/106] Debuggers: Added code to test cCompositeChat functionality. Ref.: #678 --- MCServer/Plugins/Debuggers/Debuggers.lua | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index 51b3a3a87..60e84c947 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -54,6 +54,7 @@ function Initialize(Plugin) PM:BindCommand("/ff", "debuggers", HandleFurnaceFuel, "- Shows how long the currently held item would burn in a furnace"); PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()"); PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords"); + PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings") Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers) Plugin:AddWebTab("StressTest", HandleRequest_StressTest) @@ -1195,3 +1196,25 @@ end + +function HandleCompo(a_Split, a_Player) + -- Send one composite message to self: + local msg = cCompositeChat() + msg:AddTextPart("Hello! ", "b@e") -- bold yellow + msg:AddUrlPart("MCServer", "http://mc-server.org") + msg:AddTextPart(" rules! ") + msg:AddRunCommandPart("Set morning", "/time set 0") + a_Player:SendMessage(msg) + + -- Broadcast another one to the world: + local msg2 = cCompositeChat() + msg2:AddSuggestCommandPart(a_Player:GetName(), "/tell " .. a_Player:GetName() .. " ") + msg2:AddTextPart(" knows how to use cCompositeChat!"); + a_Player:GetWorld():BroadcastChat(msg2) + + return true +end + + + + From 52cd9dfe9f7cfc7c229049d98993f13b6b8ddd5d Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 15 Feb 2014 23:26:19 +0100 Subject: [PATCH 040/106] Removed the unnecessary LoopPlayersAndBroadcastChat() functions. --- src/Root.cpp | 4 ++-- src/Root.h | 20 +++++++++----------- src/World.cpp | 2 +- src/World.h | 16 +++++++--------- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/Root.cpp b/src/Root.cpp index 415a26dd3..206255916 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -543,11 +543,11 @@ void cRoot::ReloadGroups(void) -void cRoot::LoopWorldsAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix) +void cRoot::BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix) { for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr) { - itr->second->LoopPlayersAndBroadcastChat(a_Message, a_ChatPrefix); + itr->second->BroadcastChat(a_Message, NULL, a_ChatPrefix); } // for itr - m_WorldsByName[] } diff --git a/src/Root.h b/src/Root.h index a1a3ca6a2..4bbd7586f 100644 --- a/src/Root.h +++ b/src/Root.h @@ -109,20 +109,18 @@ public: /// Finds a player from a partial or complete player name and calls the callback - case-insensitive bool FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << - void LoopWorldsAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix); - void BroadcastChatJoin (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtJoin); } - void BroadcastChatLeave (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtLeave); } - void BroadcastChatDeath (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtDeath); } - // tolua_begin /// Sends a chat message to all connected clients (in all worlds) - void BroadcastChat (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtCustom); } - void BroadcastChatInfo (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtInformation); } - void BroadcastChatFailure(const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtFailure); } - void BroadcastChatSuccess(const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtSuccess); } - void BroadcastChatWarning(const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtWarning); } - void BroadcastChatFatal (const AString & a_Message) { LoopWorldsAndBroadcastChat(a_Message, mtFailure); } + void BroadcastChat (const AString & a_Message, eMessageType a_ChatPrefix = mtCustom); + void BroadcastChatInfo (const AString & a_Message) { BroadcastChat(a_Message, mtInformation); } + void BroadcastChatFailure(const AString & a_Message) { BroadcastChat(a_Message, mtFailure); } + void BroadcastChatSuccess(const AString & a_Message) { BroadcastChat(a_Message, mtSuccess); } + void BroadcastChatWarning(const AString & a_Message) { BroadcastChat(a_Message, mtWarning); } + void BroadcastChatFatal (const AString & a_Message) { BroadcastChat(a_Message, mtFailure); } + void BroadcastChatJoin (const AString & a_Message) { BroadcastChat(a_Message, mtJoin); } + void BroadcastChatLeave (const AString & a_Message) { BroadcastChat(a_Message, mtLeave); } + void BroadcastChatDeath (const AString & a_Message) { BroadcastChat(a_Message, mtDeath); } void BroadcastChat (const cCompositeChat & a_Message); /// Returns the textual description of the protocol version: 49 -> "1.4.4". Provided specifically for Lua API diff --git a/src/World.cpp b/src/World.cpp index d1a13794c..d67ad36d1 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1747,7 +1747,7 @@ void cWorld::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cons -void cWorld::LoopPlayersAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix, const cClientHandle * a_Exclude) +void cWorld::BroadcastChat(const AString & a_Message, const cClientHandle * a_Exclude, eMessageType a_ChatPrefix) { cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) diff --git a/src/World.h b/src/World.h index 2fbc51038..97358b88a 100644 --- a/src/World.h +++ b/src/World.h @@ -168,16 +168,14 @@ public: void BroadcastBlockBreakAnimation(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = NULL); void BroadcastBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude - void LoopPlayersAndBroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix, const cClientHandle * a_Exclude = NULL); - void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtDeath, a_Exclude); } - // tolua_begin - void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtCustom, a_Exclude); } - void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtInformation, a_Exclude); } - void BroadcastChatFailure(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtFailure, a_Exclude); } - void BroadcastChatSuccess(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtSuccess, a_Exclude); } - void BroadcastChatWarning(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtWarning, a_Exclude); } - void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { LoopPlayersAndBroadcastChat(a_Message, mtFailure, a_Exclude); } + void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = NULL, eMessageType a_ChatPrefix = mtCustom); + void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { BroadcastChat(a_Message, a_Exclude, mtInformation); } + void BroadcastChatFailure(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { BroadcastChat(a_Message, a_Exclude, mtFailure); } + void BroadcastChatSuccess(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { BroadcastChat(a_Message, a_Exclude, mtSuccess); } + void BroadcastChatWarning(const AString & a_Message, const cClientHandle * a_Exclude = NULL) { BroadcastChat(a_Message, a_Exclude, mtWarning); } + void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { BroadcastChat(a_Message, a_Exclude, mtFailure); } + void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = NULL) { BroadcastChat(a_Message, a_Exclude, mtDeath); } void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = NULL); // tolua_end From faa64563440ac8d331f09152214f66b575eb7b0f Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 15 Feb 2014 15:17:58 -0800 Subject: [PATCH 041/106] Added a seperate module for Setting flags --- CMakeLists.txt | 182 +------------------------------- SetFlags.cmake | 208 +++++++++++++++++++++++++++++++++++++ lib/tolua++/CMakeLists.txt | 2 +- 3 files changed, 214 insertions(+), 178 deletions(-) create mode 100644 SetFlags.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 57b200a2a..a42d8c599 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,105 +3,10 @@ cmake_minimum_required (VERSION 2.6) # Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html ) enable_language(CXX C) -macro (add_flags_lnk FLAGS) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}") - set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}") -endmacro() - -macro(add_flags_cxx FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}") -endmacro() - -# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC): -if (NOT MSVC) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG") -endif() - -if(MSVC) - # Make build use multiple threads under MSVC: - add_flags_cxx("/MP") - - # Make release builds use link-time code generation: - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG") -elseif(APPLE) - #on os x clang adds pthread for us but we need to add it for gcc - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11") - else() - add_flags_cxx("-pthread") - endif() - -else() - # Let gcc / clang know that we're compiling a multi-threaded app: - add_flags_cxx("-pthread") - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11") - endif() - - # We use a signed char (fixes #640 on RasPi) - add_flags_cxx("-fsigned-char") -endif() - - -# Allow for a forced 32-bit build under 64-bit OS: -if (FORCE_32) - add_flags_cxx("-m32") - add_flags_lnk("-m32") -endif() - - -# Have the compiler generate code specifically targeted at the current machine on Linux -if(LINUX AND NOT CROSSCOMPILE) - add_flags_cxx("-march=native") -endif() - - -# Use static CRT in MSVC builds: -if (MSVC) - string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -endif() - - -# Set lower warnings-level for the libraries: -if (MSVC) - # Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2) - string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -else() - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w") -endif() - +include(SetFlags.cmake) +set_flags() +set_lib_flags() +enable_profile() # Under Windows, we need Lua as DLL; on *nix we need it linked statically: if (WIN32) @@ -109,18 +14,6 @@ if (WIN32) endif() -# On Unix we use two dynamic loading libraries dl and ltdl. -# Preference is for dl on unknown systems as it is specified in POSIX -# the dynamic loader is used by lua and sqllite. -if (UNIX) - if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") - set(DYNAMIC_LOADER ltdl) - else() - set(DYNAMIC_LOADER dl) - endif() -endif() - - # The Expat library is linked in statically, make the source files aware of that: add_definitions(-DXML_STATIC) @@ -129,64 +22,10 @@ if(${SELF_TEST}) add_definitions(-DSELF_TEST) endif() -# Declare the flags used for profiling builds: -if (MSVC) - set (CXX_PROFILING "") - set (LNK_PROFILING "/PROFILE") -else() - set (CXX_PROFILING "-pg") - set (LNK_PROFILING "-pg") -endif() -# Declare the profiling configurations: -SET(CMAKE_CXX_FLAGS_DEBUGPROFILE - "${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}" - CACHE STRING "Flags used by the C++ compiler during profile builds." - FORCE ) -SET(CMAKE_C_FLAGS_DEBUGPROFILE - "${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}" - CACHE STRING "Flags used by the C compiler during profile builds." - FORCE ) -SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE - "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" - CACHE STRING "Flags used for linking binaries during profile builds." - FORCE ) -SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE - "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" - CACHE STRING "Flags used by the shared libraries linker during profile builds." - FORCE ) -MARK_AS_ADVANCED( - CMAKE_CXX_FLAGS_DEBUGPROFILE - CMAKE_C_FLAGS_DEBUGPROFILE - CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE - CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE ) - -SET(CMAKE_CXX_FLAGS_RELEASEPROFILE - "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}" - CACHE STRING "Flags used by the C++ compiler during profile builds." - FORCE ) -SET(CMAKE_C_FLAGS_RELEASEPROFILE - "${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}" - CACHE STRING "Flags used by the C compiler during profile builds." - FORCE ) -SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE - "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" - CACHE STRING "Flags used for linking binaries during profile builds." - FORCE ) -SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE - "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" - CACHE STRING "Flags used by the shared libraries linker during profile builds." - FORCE ) -MARK_AS_ADVANCED( - CMAKE_CXX_FLAGS_RELEASEPROFILE - CMAKE_C_FLAGS_RELEASEPROFILE - CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE - CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE ) -# The configuration types need to be set after their respective c/cxx/linker flags and before the project directive -set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE) project (MCServer) # Include all the libraries: @@ -205,18 +44,7 @@ add_subdirectory(lib/md5/) # (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those) add_subdirectory(lib/polarssl/ EXCLUDE_FROM_ALL) - -# Remove disabling the maximum warning level: -# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings -# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers; -# the important warnings are turned on using #pragma in Globals.h -if (NOT MSVC) - string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - add_flags_cxx("-Wall") -endif() +set_exe_flags() if(${BUILD_TOOLS}) add_subdirectory(Tools/GeneratorPerformanceTest/) diff --git a/SetFlags.cmake b/SetFlags.cmake new file mode 100644 index 000000000..a2f13384a --- /dev/null +++ b/SetFlags.cmake @@ -0,0 +1,208 @@ + + +macro (add_flags_lnk FLAGS) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}") + set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}") + set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}") +endmacro() + +macro(add_flags_cxx FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}") +endmacro() + + +macro(set_flags) + if(NOT DEFINED ${FLAGS_SET}) + set(FLAGS_SET 1) + + # Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC): + if (NOT MSVC) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG") + endif() + + if(MSVC) + # Make build use multiple threads under MSVC: + add_flags_cxx("/MP") + + # Make release builds use link-time code generation: + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") + set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG") + elseif(APPLE) + #on os x clang adds pthread for us but we need to add it for gcc + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11") + else() + add_flags_cxx("-pthread") + endif() + + else() + # Let gcc / clang know that we're compiling a multi-threaded app: + add_flags_cxx("-pthread") + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11") + endif() + + # We use a signed char (fixes #640 on RasPi) + add_flags_cxx("-fsigned-char") + endif() + + + # Allow for a forced 32-bit build under 64-bit OS: + if (FORCE_32) + add_flags_cxx("-m32") + add_flags_lnk("-m32") + endif() + + + # Have the compiler generate code specifically targeted at the current machine on Linux + if(LINUX AND NOT CROSSCOMPILE) + add_flags_cxx("-march=native") + endif() + + + # Use static CRT in MSVC builds: + if (MSVC) + string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + endif() + + endif() +endmacro() + +macro(set_lib_flags) + if(NOT DEFINED ${LIB_FLAGS_SET}) + set(LIB_FLAGS_SET 1) + # Set lower warnings-level for the libraries: + if (MSVC) + # Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2) + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + else() + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w") + endif() + + # On Unix we use two dynamic loading libraries dl and ltdl. + # Preference is for dl on unknown systems as it is specified in POSIX + # the dynamic loader is used by lua and sqllite. + if (UNIX) + if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + set(DYNAMIC_LOADER ltdl) + else() + set(DYNAMIC_LOADER dl) + endif() + endif() + + + endif() +endmacro() + +macro(enable_profile) + if(NOT DEFINED ${PROFILE_ENABLED}) + set(PROFILE_ENABLED 1) + + # Declare the flags used for profiling builds: + if (MSVC) + set (CXX_PROFILING "") + set (LNK_PROFILING "/PROFILE") + else() + set (CXX_PROFILING "-pg") + set (LNK_PROFILING "-pg") + endif() + + + # Declare the profiling configurations: + SET(CMAKE_CXX_FLAGS_DEBUGPROFILE + "${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}" + CACHE STRING "Flags used by the C++ compiler during profile builds." + FORCE ) + SET(CMAKE_C_FLAGS_DEBUGPROFILE + "${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}" + CACHE STRING "Flags used by the C compiler during profile builds." + FORCE ) + SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE + "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" + CACHE STRING "Flags used for linking binaries during profile builds." + FORCE ) + SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE + "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" + CACHE STRING "Flags used by the shared libraries linker during profile builds." + FORCE ) + MARK_AS_ADVANCED( + CMAKE_CXX_FLAGS_DEBUGPROFILE + CMAKE_C_FLAGS_DEBUGPROFILE + CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE + CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE ) + + SET(CMAKE_CXX_FLAGS_RELEASEPROFILE + "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}" + CACHE STRING "Flags used by the C++ compiler during profile builds." + FORCE ) + SET(CMAKE_C_FLAGS_RELEASEPROFILE + "${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}" + CACHE STRING "Flags used by the C compiler during profile builds." + FORCE ) + SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE + "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" + CACHE STRING "Flags used for linking binaries during profile builds." + FORCE ) + SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE + "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" + CACHE STRING "Flags used by the shared libraries linker during profile builds." + FORCE ) + MARK_AS_ADVANCED( + CMAKE_CXX_FLAGS_RELEASEPROFILE + CMAKE_C_FLAGS_RELEASEPROFILE + CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE + CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE ) + # The configuration types need to be set after their respective c/cxx/linker flags and before the project directive + set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE) + endif() +endmacro() + +macro(set_exe_flags) + if(NOT DEFINED ${EXE_FLAGS_SET}) + set(EXE_FLAGS_SET 1) + + # Remove disabling the maximum warning level: + # clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings + # We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers; + # the important warnings are turned on using #pragma in Globals.h + if (NOT MSVC) + string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + add_flags_cxx("-Wall") + endif() + + + endif() +endmacro() diff --git a/lib/tolua++/CMakeLists.txt b/lib/tolua++/CMakeLists.txt index 239232c38..5ec8ee822 100644 --- a/lib/tolua++/CMakeLists.txt +++ b/lib/tolua++/CMakeLists.txt @@ -19,7 +19,7 @@ add_library(tolualib ${LIB_SOURCE}) #m is the standard math librarys if(UNIX) -target_link_libraries(tolua m) +target_link_libraries(tolua m ${DYNAMIC_LOADER}) endif() target_link_libraries(tolua lua tolualib) From 9ba0b6ecf220346017c831293ffb69d535382480 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 15 Feb 2014 15:24:34 -0800 Subject: [PATCH 042/106] rewrote MCADefrag CMakelist to use Setflags --- Tools/MCADefrag/CMakeLists.txt | 72 ++++++++-------------------------- 1 file changed, 16 insertions(+), 56 deletions(-) diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt index 7296b8ddc..f3256f275 100644 --- a/Tools/MCADefrag/CMakeLists.txt +++ b/Tools/MCADefrag/CMakeLists.txt @@ -3,60 +3,13 @@ cmake_minimum_required (VERSION 2.6) project (MCADefrag) +# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html ) +enable_language(CXX C) - -macro(add_flags_cxx FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}") -endmacro() - - - - -# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC): -if (NOT MSVC) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG") -endif() - - - -if(MSVC) - # Make build use multiple threads under MSVC: - add_flags_cxx("/MP") - - # Make release builds use link-time code generation: - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG") -elseif(APPLE) - #on os x clang adds pthread for us but we need to add it for gcc - if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - add_flags_cxx("-pthread") - endif() -else() - # Let gcc / clang know that we're compiling a multi-threaded app: - add_flags_cxx("-pthread") -endif() - - - - -# Use static CRT in MSVC builds: -if (MSVC) - string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -endif() +include(../../SetFlags.cmake) +set_flags() +set_lib_flags() +enable_profile() @@ -78,12 +31,16 @@ endfunction() # Include the libraries: +if(NOT DEFINED ${ZLIB}) file(GLOB ZLIB_SRC "../../lib/zlib/*.c") file(GLOB ZLIB_HDR "../../lib/zlib/*.h") flatten_files(ZLIB_SRC) flatten_files(ZLIB_HDR) source_group("ZLib" FILES ${ZLIB_SRC} ${ZLIB_HDR}) +set(ZLIB 1) +endif() +set_exe_flags() # Include the shared files: set(SHARED_SRC @@ -98,6 +55,10 @@ set(SHARED_HDR ../../src/Log.h ../../src/MCLogger.h ) +flatten_files(SHARED_SRC) +flatten_files(SHARED_HDR) +source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) + set(SHARED_OSS_SRC ../../src/OSSupport/CriticalSection.cpp ../../src/OSSupport/File.cpp @@ -110,11 +71,10 @@ set(SHARED_OSS_HDR ../../src/OSSupport/IsThread.h ../../src/OSSupport/Timer.h ) -flatten_files(SHARED_SRC) -flatten_files(SHARED_HDR) + flatten_files(SHARED_OSS_SRC) flatten_files(SHARED_OSS_HDR) -source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) + source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR}) From 42e9b21fb25426cd6f4e42c7cede4294e00e9e6b Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 15 Feb 2014 15:27:10 -0800 Subject: [PATCH 043/106] CHange MCADefrag CMakelist to use zlib CMakeList --- Tools/MCADefrag/CMakeLists.txt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt index f3256f275..174da4fab 100644 --- a/Tools/MCADefrag/CMakeLists.txt +++ b/Tools/MCADefrag/CMakeLists.txt @@ -19,7 +19,6 @@ include_directories("../../lib") include_directories("../../src") - function(flatten_files arg1) set(res "") foreach(f ${${arg1}}) @@ -32,12 +31,8 @@ endfunction() # Include the libraries: if(NOT DEFINED ${ZLIB}) -file(GLOB ZLIB_SRC "../../lib/zlib/*.c") -file(GLOB ZLIB_HDR "../../lib/zlib/*.h") -flatten_files(ZLIB_SRC) -flatten_files(ZLIB_HDR) -source_group("ZLib" FILES ${ZLIB_SRC} ${ZLIB_HDR}) -set(ZLIB 1) + add_subdirectory(../../lib/zlib lib/zlib) + set(ZLIB 1) endif() set_exe_flags() @@ -98,7 +93,7 @@ add_executable(MCADefrag ${SHARED_HDR} ${SHARED_OSS_SRC} ${SHARED_OSS_HDR} - ${ZLIB_SRC} - ${ZLIB_HDR} ) +target_link_libraries(MCADefrag zlib) + From d15d6acc5837b0f2aa6814b2d9c9a2e440a952e6 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 11 Feb 2014 15:34:18 +0100 Subject: [PATCH 044/106] Disable Hunger Death --- src/Entities/Player.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index d568e068d..6e3db5194 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1764,6 +1764,12 @@ void cPlayer::HandleFood(void) { // Ref.: http://www.minecraftwiki.net/wiki/Hunger + if (IsGameModeCreative()) + { + // Hunger is disabled for Creative + return; + } + // Remember the food level before processing, for later comparison int LastFoodLevel = m_FoodLevel; @@ -1781,7 +1787,7 @@ void cPlayer::HandleFood(void) Heal(1); m_FoodExhaustionLevel += 3; } - else if (m_FoodLevel <= 0) + else if (m_FoodLevel <= 0 && m_Health > 1) { // Damage from starving TakeDamage(dtStarving, NULL, 1, 1, 0); From 507a8a4b844f1c0a36bfc7063804ddca1012948d Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 14 Feb 2014 21:33:16 +0100 Subject: [PATCH 045/106] Set max. Players in the Tablist to 60 --- src/Protocol/Protocol17x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 5aa18300c..1dfa5ec90 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -550,7 +550,7 @@ void cProtocol172::SendLogin(const cPlayer & a_Player, const cWorld & a_World) Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (cRoot::Get()->GetServer()->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 Pkt.WriteChar((char)a_World.GetDimension()); Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) - Pkt.WriteByte(cRoot::Get()->GetServer()->GetMaxPlayers()); + Pkt.WriteByte(std::min(cRoot::Get()->GetServer()->GetMaxPlayers(), 60)); Pkt.WriteString("default"); // Level type - wtf? } From f3bd288f020a8f004179513c0e260ac0f2855767 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 14 Feb 2014 22:49:23 +0100 Subject: [PATCH 046/106] Add Exp Bottle Effects --- src/Entities/ExpOrb.cpp | 10 +++++++++- src/Entities/Player.cpp | 9 +++++++++ src/Entities/Player.h | 2 ++ src/Entities/ProjectileEntity.cpp | 3 +++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp index 04ee85823..8b0838d27 100644 --- a/src/Entities/ExpOrb.cpp +++ b/src/Entities/ExpOrb.cpp @@ -4,6 +4,8 @@ #include "Player.h" #include "../ClientHandle.h" +#include + cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward) : cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98), @@ -51,6 +53,12 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk) { LOGD("Player %s picked up an ExpOrb. His reward is %i", a_ClosestPlayer->GetName().c_str(), m_Reward); a_ClosestPlayer->DeltaExperience(m_Reward); + + srand (static_cast (time(0))); + float r1 = static_cast (rand()) / static_cast (RAND_MAX); // Random Float Value (Java: random.nextFloat()) + float r2 = static_cast (rand()) / static_cast (RAND_MAX); // Random Float Value (Java: random.nextFloat()) + a_ClosestPlayer->PlaySoundEffect("random.orb", 0.1F, 0.5F * ((r1 - r2) * 0.7F + 1.8F)); + Destroy(true); } a_Distance.Normalize(); @@ -61,4 +69,4 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk) BroadcastMovementUpdate(); } HandlePhysics(a_Dt, a_Chunk); -} \ No newline at end of file +} diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 6e3db5194..be26e4f6e 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1059,6 +1059,15 @@ void cPlayer::CloseWindowIfID(char a_WindowID, bool a_CanRefuse) +void cPlayer::PlaySoundEffect(const AString & a_SoundName, float a_Volume, float a_Pitch) +{ + m_ClientHandle->SendSoundEffect(a_SoundName, (int) (GetPosX() * 8.0), (int) (GetPosY() * 8.0), (int) (GetPosZ() * 8.0), a_Volume, a_Pitch); +} + + + + + void cPlayer::SetLastBlockActionTime() { if (m_World != NULL) diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 53e4b56db..838f0301d 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -208,6 +208,8 @@ public: const AString & GetName(void) const { return m_PlayerName; } void SetName(const AString & a_Name) { m_PlayerName = a_Name; } + void PlaySoundEffect(const AString & a_SoundName, float a_Volume, float a_Pitch); + // tolua_end typedef std::list< cGroup* > GroupList; diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index a3fa9d557..718a04baf 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -12,6 +12,8 @@ #include "../ChunkMap.h" #include "../Chunk.h" +#include + @@ -680,6 +682,7 @@ super(pkExpBottle, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25) void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) { // Spawn an experience orb with a reward between 3 and 11. + m_World->BroadcastSoundParticleEffect(2002, (int) round(GetPosX()), (int) round(GetPosY()), (int) round(GetPosZ()), 0); m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), 3 + m_World->GetTickRandomNumber(8)); Destroy(); From 707916b404e8ba16b8f39b43cb9e91af9d4b37b4 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 15 Feb 2014 19:52:15 +0100 Subject: [PATCH 047/106] Replace random Float Generation and broadcast the Exp Pickup Sound --- src/Entities/ExpOrb.cpp | 9 +++------ src/Entities/ProjectileEntity.cpp | 4 +--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp index 8b0838d27..41b60cc3b 100644 --- a/src/Entities/ExpOrb.cpp +++ b/src/Entities/ExpOrb.cpp @@ -4,8 +4,6 @@ #include "Player.h" #include "../ClientHandle.h" -#include - cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward) : cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98), @@ -54,10 +52,9 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk) LOGD("Player %s picked up an ExpOrb. His reward is %i", a_ClosestPlayer->GetName().c_str(), m_Reward); a_ClosestPlayer->DeltaExperience(m_Reward); - srand (static_cast (time(0))); - float r1 = static_cast (rand()) / static_cast (RAND_MAX); // Random Float Value (Java: random.nextFloat()) - float r2 = static_cast (rand()) / static_cast (RAND_MAX); // Random Float Value (Java: random.nextFloat()) - a_ClosestPlayer->PlaySoundEffect("random.orb", 0.1F, 0.5F * ((r1 - r2) * 0.7F + 1.8F)); + float r1 = (float) (0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64); // Random Float Value + float r2 = (float) (0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64); // Random Float Value + m_World->BroadcastSoundEffect("random.orb", (int) (GetPosX() * 8.0F), (int) (GetPosY() * 8.0F), (int) (GetPosZ() * 8.0F), 0.1F, 0.5F * ((r1 - r2) * 0.7F + 1.8F)); Destroy(true); } diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index 718a04baf..ef82c6e94 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -12,8 +12,6 @@ #include "../ChunkMap.h" #include "../Chunk.h" -#include - @@ -682,7 +680,7 @@ super(pkExpBottle, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25) void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) { // Spawn an experience orb with a reward between 3 and 11. - m_World->BroadcastSoundParticleEffect(2002, (int) round(GetPosX()), (int) round(GetPosY()), (int) round(GetPosZ()), 0); + m_World->BroadcastSoundParticleEffect(2002, POSX_TOINT, POSY_TOINT, POSZ_TOINT, 0); m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), 3 + m_World->GetTickRandomNumber(8)); Destroy(); From 55a6306e2bfa1b8ddf87ee2287fe1217904ac547 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 00:45:14 +0000 Subject: [PATCH 048/106] Fixed a glaring bug with chunk cross-simulating * A chunk's redstone blocks list is no longer touched if AddBlock was being called with another chunk's coordinates * Fixed chunk boundary checks --- .../IncrementalRedstoneSimulator.cpp | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 4f592d253..60dabaf84 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -183,6 +183,12 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, } } + if (a_OtherChunk != NULL) + { + // DO NOT touch our chunk's data structure if we are being called with coordinates from another chunk - this one caused me massive grief :P + return; + } + cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr) { @@ -323,20 +329,22 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) { if ( - ((a_BlockX % cChunkDef::Width) >= cChunkDef::Width - 2) || - ((a_BlockX % cChunkDef::Width) <= cChunkDef::Width + 2) || - ((a_BlockZ % cChunkDef::Width) >= cChunkDef::Width - 2) || - ((a_BlockZ % cChunkDef::Width) <= cChunkDef::Width + 2) + ((a_BlockX % cChunkDef::Width) <= 1) || + ((a_BlockX % cChunkDef::Width) >= 14) || + ((a_BlockZ % cChunkDef::Width) <= 1) || + ((a_BlockZ % cChunkDef::Width) >= 14) ) // Are we on a chunk boundary? ± 2 because of LinkedPowered blocks { // On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk) AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); + // Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position - // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordiantes are in - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1), a_Chunk); + // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordiantes are in and ± 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 2, a_BlockZ), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 2, a_BlockZ), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 2), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 2), a_Chunk); + return; } From 8c34b2d9748311840a93f64494f56a5b1e81015f Mon Sep 17 00:00:00 2001 From: narroo Date: Sat, 15 Feb 2014 19:56:36 -0500 Subject: [PATCH 049/106] Addressed Issue #402. cIniFile can now process UTF-8 files that have a Byte Order Marker, BOM. --- lib/inifile/iniFile.cpp | 154 +++++++++++++++++++++++----------------- lib/inifile/iniFile.h | 2 + 2 files changed, 90 insertions(+), 66 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index afa1c110d..7b0df3d68 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -83,91 +83,97 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) } } - while (getline(f, line)) + if (getline(f, line)) { - // To be compatible with Win32, check for existence of '\r'. - // Win32 files have the '\r' and Unix files don't at the end of a line. - // Note that the '\r' will be written to INI files from - // Unix so that the created INI file can be read under Win32 - // without change. - size_t lineLength = line.length(); - if (lineLength == 0) - { - continue; - } - if (line[lineLength - 1] == '\r') - { - line = line.substr(0, lineLength - 1); - } + // Removes UTF-8 Byte Order Markers (BOM) if, present. + RemoveBom(line); - if (line.length() == 0) + do { - continue; - } + // To be compatible with Win32, check for existence of '\r'. + // Win32 files have the '\r' and Unix files don't at the end of a line. + // Note that the '\r' will be written to INI files from + // Unix so that the created INI file can be read under Win32 + // without change. + size_t lineLength = line.length(); + if (lineLength == 0) + { + continue; + } + if (line[lineLength - 1] == '\r') + { + line = line.substr(0, lineLength - 1); + } - // Check that the user hasn't opened a binary file by checking the first - // character of each line! - if (!isprint(line[0])) - { - printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]); - f.close(); - return false; - } - if ((pLeft = line.find_first_of(";#[=")) == AString::npos) - { - continue; - } + if (line.length() == 0) + { + continue; + } - switch (line[pLeft]) - { + // Check that the user hasn't opened a binary file by checking the first + // character of each line! + if (!isprint(line[0])) + { + printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]); + f.close(); + return false; + } + if ((pLeft = line.find_first_of(";#[=")) == AString::npos) + { + continue; + } + + switch (line[pLeft]) + { case '[': { - if ( - ((pRight = line.find_last_of("]")) != AString::npos) && - (pRight > pLeft) - ) - { - keyname = line.substr(pLeft + 1, pRight - pLeft - 1); - AddKeyName(keyname); - } - break; + if ( + ((pRight = line.find_last_of("]")) != AString::npos) && + (pRight > pLeft) + ) + { + keyname = line.substr(pLeft + 1, pRight - pLeft - 1); + AddKeyName(keyname); + } + break; } case '=': { - valuename = line.substr(0, pLeft); - value = line.substr(pLeft + 1); - AddValue(keyname, valuename, value); - break; + valuename = line.substr(0, pLeft); + value = line.substr(pLeft + 1); + AddValue(keyname, valuename, value); + break; } case ';': case '#': { - if (names.size() == 0) - { - AddHeaderComment(line.substr(pLeft + 1)); - } - else - { - AddKeyComment(keyname, line.substr(pLeft + 1)); - } - break; + if (names.size() == 0) + { + AddHeaderComment(line.substr(pLeft + 1)); + } + else + { + AddKeyComment(keyname, line.substr(pLeft + 1)); + } + break; } - } // switch (line[pLeft]) - } // while (getline()) + } // switch (line[pLeft]) + } while (getline(f, line)); // do - f.close(); - if (names.size() == 0) - { - return false; + f.close(); + if (names.size() == 0) + { + return false; + } + + if (IsFromExampleRedirect) + { + WriteFile(FILE_IO_PREFIX + a_FileName); + } + return true; } - - if (IsFromExampleRedirect) - { - WriteFile(FILE_IO_PREFIX + a_FileName); - } - return true; } @@ -824,3 +830,19 @@ AString cIniFile::CheckCase(const AString & s) const + +void cIniFile::RemoveBom(AString & a_line) const +{ + // The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF ( In Unicode Latin I:  ) + static char BOM[] = { 0xEF, 0xBB, 0xBF }; + + // The BOM sequence, if present, is always the first three characters of the input. + if (a_line.compare(0, 3, BOM) == 0) + { + a_line.erase(0, 3); + } +} + + + + diff --git a/lib/inifile/iniFile.h b/lib/inifile/iniFile.h index 40af618dc..0bf1d917e 100644 --- a/lib/inifile/iniFile.h +++ b/lib/inifile/iniFile.h @@ -51,6 +51,8 @@ private: /// If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is AString CheckCase(const AString & s) const; + /// Removes the UTF-8 BOMs (Byte order makers), if present. + void RemoveBom(AString & a_line) const; public: enum errors { From 0f7d90b7d18a1ccc59b2e47184bf8de1a21ec5a6 Mon Sep 17 00:00:00 2001 From: Muhammad Wang Date: Sun, 16 Feb 2014 12:15:24 +0800 Subject: [PATCH 050/106] Fixed a minor error --- COMPILING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/COMPILING.md b/COMPILING.md index d3c896bdd..94220f9c6 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -69,7 +69,7 @@ Assuming you are in the MCServer folder created in the initial setup step, you n ``` mkdir Release cd Release -cmake . -DCMAKE_BUILD_TYPE=RELEASE .. && make +cmake .. -DCMAKE_BUILD_TYPE=RELEASE && make ``` The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`. @@ -81,7 +81,7 @@ Assuming you are in the MCServer folder created in the Getting the sources step, ``` mkdir Debug cd Debug -cmake . -DCMAKE_BUILD_TYPE=DEBUG && make` +cmake .. -DCMAKE_BUILD_TYPE=DEBUG && make ``` The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`. From 2acf218700a6ae6d5cb441d1e4138b98519f6dfe Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 03:37:31 -0800 Subject: [PATCH 051/106] Allow building MCADefrag at the same time as MCServer --- CMakeLists.txt | 13 ++- SetFlags.cmake | 193 +++++++++++++++------------------ Tools/MCADefrag/CMakeLists.txt | 6 +- lib/zlib/CMakeLists.txt | 14 ++- 4 files changed, 106 insertions(+), 120 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a42d8c599..8c8daf915 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,15 @@ cmake_minimum_required (VERSION 2.6) # Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html ) enable_language(CXX C) +#THis has to be done before any flags have been set up. +if(${BUILD_TOOLS}) + add_subdirectory(Tools/MCADefrag/) +endif() + +if(${BUILD_UNSTABLE_TOOLS}) + add_subdirectory(Tools/GeneratorPerformanceTest/) +endif() + include(SetFlags.cmake) set_flags() set_lib_flags() @@ -46,9 +55,5 @@ add_subdirectory(lib/polarssl/ EXCLUDE_FROM_ALL) set_exe_flags() -if(${BUILD_TOOLS}) -add_subdirectory(Tools/GeneratorPerformanceTest/) -endif() - add_subdirectory (src) diff --git a/SetFlags.cmake b/SetFlags.cmake index a2f13384a..162560c90 100644 --- a/SetFlags.cmake +++ b/SetFlags.cmake @@ -23,9 +23,6 @@ endmacro() macro(set_flags) - if(NOT DEFINED ${FLAGS_SET}) - set(FLAGS_SET 1) - # Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC): if (NOT MSVC) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") @@ -88,121 +85,105 @@ macro(set_flags) string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") endif() - - endif() endmacro() macro(set_lib_flags) - if(NOT DEFINED ${LIB_FLAGS_SET}) - set(LIB_FLAGS_SET 1) - # Set lower warnings-level for the libraries: - if (MSVC) - # Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2) - string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + # Set lower warnings-level for the libraries: + if (MSVC) + # Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2) + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + else() + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w") + endif() + + # On Unix we use two dynamic loading libraries dl and ltdl. + # Preference is for dl on unknown systems as it is specified in POSIX + # the dynamic loader is used by lua and sqllite. + if (UNIX) + if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + set(DYNAMIC_LOADER ltdl) else() - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w") + set(DYNAMIC_LOADER dl) endif() - - # On Unix we use two dynamic loading libraries dl and ltdl. - # Preference is for dl on unknown systems as it is specified in POSIX - # the dynamic loader is used by lua and sqllite. - if (UNIX) - if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") - set(DYNAMIC_LOADER ltdl) - else() - set(DYNAMIC_LOADER dl) - endif() - endif() - - endif() endmacro() macro(enable_profile) - if(NOT DEFINED ${PROFILE_ENABLED}) - set(PROFILE_ENABLED 1) - - # Declare the flags used for profiling builds: - if (MSVC) - set (CXX_PROFILING "") - set (LNK_PROFILING "/PROFILE") - else() - set (CXX_PROFILING "-pg") - set (LNK_PROFILING "-pg") - endif() - - - # Declare the profiling configurations: - SET(CMAKE_CXX_FLAGS_DEBUGPROFILE - "${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}" - CACHE STRING "Flags used by the C++ compiler during profile builds." - FORCE ) - SET(CMAKE_C_FLAGS_DEBUGPROFILE - "${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}" - CACHE STRING "Flags used by the C compiler during profile builds." - FORCE ) - SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE - "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" - CACHE STRING "Flags used for linking binaries during profile builds." - FORCE ) - SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE - "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" - CACHE STRING "Flags used by the shared libraries linker during profile builds." - FORCE ) - MARK_AS_ADVANCED( - CMAKE_CXX_FLAGS_DEBUGPROFILE - CMAKE_C_FLAGS_DEBUGPROFILE - CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE - CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE ) - - SET(CMAKE_CXX_FLAGS_RELEASEPROFILE - "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}" - CACHE STRING "Flags used by the C++ compiler during profile builds." - FORCE ) - SET(CMAKE_C_FLAGS_RELEASEPROFILE - "${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}" - CACHE STRING "Flags used by the C compiler during profile builds." - FORCE ) - SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE - "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" - CACHE STRING "Flags used for linking binaries during profile builds." - FORCE ) - SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE - "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" - CACHE STRING "Flags used by the shared libraries linker during profile builds." - FORCE ) - MARK_AS_ADVANCED( - CMAKE_CXX_FLAGS_RELEASEPROFILE - CMAKE_C_FLAGS_RELEASEPROFILE - CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE - CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE ) - # The configuration types need to be set after their respective c/cxx/linker flags and before the project directive - set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE) + # Declare the flags used for profiling builds: + if (MSVC) + set (CXX_PROFILING "") + set (LNK_PROFILING "/PROFILE") + else() + set (CXX_PROFILING "-pg") + set (LNK_PROFILING "-pg") endif() + + + # Declare the profiling configurations: + SET(CMAKE_CXX_FLAGS_DEBUGPROFILE + "${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}" + CACHE STRING "Flags used by the C++ compiler during profile builds." + FORCE ) + SET(CMAKE_C_FLAGS_DEBUGPROFILE + "${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}" + CACHE STRING "Flags used by the C compiler during profile builds." + FORCE ) + SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE + "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" + CACHE STRING "Flags used for linking binaries during profile builds." + FORCE ) + SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE + "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" + CACHE STRING "Flags used by the shared libraries linker during profile builds." + FORCE ) + MARK_AS_ADVANCED( + CMAKE_CXX_FLAGS_DEBUGPROFILE + CMAKE_C_FLAGS_DEBUGPROFILE + CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE + CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE ) + + SET(CMAKE_CXX_FLAGS_RELEASEPROFILE + "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}" + CACHE STRING "Flags used by the C++ compiler during profile builds." + FORCE ) + SET(CMAKE_C_FLAGS_RELEASEPROFILE + "${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}" + CACHE STRING "Flags used by the C compiler during profile builds." + FORCE ) + SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE + "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" + CACHE STRING "Flags used for linking binaries during profile builds." + FORCE ) + SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE + "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" + CACHE STRING "Flags used by the shared libraries linker during profile builds." + FORCE ) + MARK_AS_ADVANCED( + CMAKE_CXX_FLAGS_RELEASEPROFILE + CMAKE_C_FLAGS_RELEASEPROFILE + CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE + CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE ) + # The configuration types need to be set after their respective c/cxx/linker flags and before the project directive + set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE) endmacro() macro(set_exe_flags) - if(NOT DEFINED ${EXE_FLAGS_SET}) - set(EXE_FLAGS_SET 1) - - # Remove disabling the maximum warning level: - # clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings - # We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers; - # the important warnings are turned on using #pragma in Globals.h - if (NOT MSVC) - string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - add_flags_cxx("-Wall") - endif() - - + # Remove disabling the maximum warning level: + # clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings + # We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers; + # the important warnings are turned on using #pragma in Globals.h + if (NOT MSVC) + string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + add_flags_cxx("-Wall") endif() + endmacro() diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt index 174da4fab..c11c8c772 100644 --- a/Tools/MCADefrag/CMakeLists.txt +++ b/Tools/MCADefrag/CMakeLists.txt @@ -30,10 +30,8 @@ endfunction() # Include the libraries: -if(NOT DEFINED ${ZLIB}) - add_subdirectory(../../lib/zlib lib/zlib) - set(ZLIB 1) -endif() + +add_subdirectory(../../lib/zlib lib/zlib) set_exe_flags() diff --git a/lib/zlib/CMakeLists.txt b/lib/zlib/CMakeLists.txt index b1b74031d..6c52578ee 100644 --- a/lib/zlib/CMakeLists.txt +++ b/lib/zlib/CMakeLists.txt @@ -8,12 +8,14 @@ file(GLOB SOURCE "*.c" ) -add_library(zlib ${SOURCE}) +if(NOT TARGET zlib) + add_library(zlib ${SOURCE}) -if (MSVC) - # Remove SCL warnings, we expect this library to have been tested safe - SET_TARGET_PROPERTIES( - zlib PROPERTIES COMPILE_FLAGS "-D_CRT_SECURE_NO_WARNINGS" - ) + if (MSVC) + # Remove SCL warnings, we expect this library to have been tested safe + SET_TARGET_PROPERTIES( + zlib PROPERTIES COMPILE_FLAGS "-D_CRT_SECURE_NO_WARNINGS" + ) + endif() endif() From 83f0438e21676a0b97850c9c974d3b1a57fc573c Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 04:09:00 -0800 Subject: [PATCH 052/106] COnverted ProtoProxy to use library CMakeLists --- Tools/MCADefrag/CMakeLists.txt | 2 +- Tools/ProtoProxy/CMakeLists.txt | 21 ++++----------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt index c11c8c772..2a021049f 100644 --- a/Tools/MCADefrag/CMakeLists.txt +++ b/Tools/MCADefrag/CMakeLists.txt @@ -31,7 +31,7 @@ endfunction() # Include the libraries: -add_subdirectory(../../lib/zlib lib/zlib) +add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib) set_exe_flags() diff --git a/Tools/ProtoProxy/CMakeLists.txt b/Tools/ProtoProxy/CMakeLists.txt index 9e233a688..30630b04b 100644 --- a/Tools/ProtoProxy/CMakeLists.txt +++ b/Tools/ProtoProxy/CMakeLists.txt @@ -77,19 +77,8 @@ function(flatten_files arg1) set(${arg1} "${res}" PARENT_SCOPE) endfunction() - -# Include the libraries: -file(GLOB POLARSSL_SRC "../../lib/polarssl/library/*.c") -file(GLOB POLARSSL_HDR "../../lib/polarssl/include/polarssl/*.h") -flatten_files(POLARSSL_SRC) -flatten_files(POLARSSL_HDR) -source_group("PolarSSL" FILES ${POLARSSL_SRC} ${POLARSSL_HDR}) - -file(GLOB ZLIB_SRC "../../lib/zlib/*.c") -file(GLOB ZLIB_HDR "../../lib/zlib/*.h") -flatten_files(ZLIB_SRC) -flatten_files(ZLIB_HDR) -source_group("ZLib" FILES ${ZLIB_SRC} ${ZLIB_HDR}) +include(../../lib/polarssl.cmake) +add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib) # Include the shared files: @@ -149,9 +138,7 @@ add_executable(ProtoProxy ${SHARED_HDR} ${SHARED_OSS_SRC} ${SHARED_OSS_HDR} - ${POLARSSL_SRC} - ${POLARSSL_HDR} - ${ZLIB_SRC} - ${ZLIB_HDR} ) +target_link_libraries(ProtoProxy zlib polarssl) + From 994904f6c585accf1fad67f68dde33ca445cc657 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 04:15:12 -0800 Subject: [PATCH 053/106] Now uses setflags for flags --- Tools/ProtoProxy/CMakeLists.txt | 59 +++------------------------------ 1 file changed, 4 insertions(+), 55 deletions(-) diff --git a/Tools/ProtoProxy/CMakeLists.txt b/Tools/ProtoProxy/CMakeLists.txt index 30630b04b..01f1e88ad 100644 --- a/Tools/ProtoProxy/CMakeLists.txt +++ b/Tools/ProtoProxy/CMakeLists.txt @@ -3,62 +3,10 @@ cmake_minimum_required (VERSION 2.6) project (ProtoProxy) +include(../../SetFlags.cmake) - -macro(add_flags_cxx FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}") -endmacro() - - - - -# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC): -if (NOT MSVC) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG") -endif() - - - -if(MSVC) - # Make build use multiple threads under MSVC: - add_flags_cxx("/MP") - - # Make release builds use link-time code generation: - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG") -elseif(APPLE) - #on os x clang adds pthread for us but we need to add it for gcc - if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - add_flags_cxx("-pthread") - endif() -else() - # Let gcc / clang know that we're compiling a multi-threaded app: - add_flags_cxx("-pthread") -endif() - - - - -# Use static CRT in MSVC builds: -if (MSVC) - string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -endif() - - +set_flags() +set_lib_flags() # Set include paths to the used libraries: @@ -80,6 +28,7 @@ endfunction() include(../../lib/polarssl.cmake) add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib) +set_exe_flags() # Include the shared files: set(SHARED_SRC From 48d28a0f94ab168b7cb022107f6a62e3250043bc Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 16 Feb 2014 13:26:07 +0100 Subject: [PATCH 054/106] Add Locale to ClientHandle --- src/ClientHandle.cpp | 1 + src/ClientHandle.h | 7 ++++++- src/Protocol/Protocol132.cpp | 2 +- src/Protocol/Protocol14x.cpp | 2 +- src/Protocol/Protocol17x.cpp | 2 ++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index f8a707324..b46bcfd47 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -95,6 +95,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) : m_ShouldCheckDownloaded(false), m_NumExplosionsThisTick(0), m_UniqueID(0), + m_Locale("en_GB"), m_HasSentPlayerChunk(false) { m_Protocol = new cProtocolRecognizer(this); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 034fe07c2..5faa94004 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -155,6 +155,9 @@ public: void SetViewDistance(int a_ViewDistance); // tolua_export int GetViewDistance(void) const { return m_ViewDistance; } // tolua_export + + void SetLocale(AString & a_Locale) { m_Locale = a_Locale; } // tolua_export + AString GetLocale(void) const { return m_Locale; } // tolua_export int GetUniqueID() const { return m_UniqueID; } // tolua_export @@ -308,7 +311,9 @@ private: /// Set to true when the chunk where the player is is sent to the client. Used for spawning the player bool m_HasSentPlayerChunk; - + + /// Client Settings + AString m_Locale; /// Returns true if the rate block interactions is within a reasonable limit (bot protection) diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index 648e70151..1f9222a69 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -560,7 +560,7 @@ int cProtocol132::ParseLocaleViewDistance(void) HANDLE_PACKET_READ(ReadChar, char, ViewDistance); HANDLE_PACKET_READ(ReadChar, char, ChatFlags); HANDLE_PACKET_READ(ReadChar, char, ClientDifficulty); - // TODO: m_Client->HandleLocale(Locale); + m_Client->SetLocale(Locale); // TODO: m_Client->HandleViewDistance(ViewDistance); // TODO: m_Client->HandleChatFlags(ChatFlags); // Ignoring client difficulty diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp index f82e6de45..232b2718e 100644 --- a/src/Protocol/Protocol14x.cpp +++ b/src/Protocol/Protocol14x.cpp @@ -85,7 +85,7 @@ int cProtocol142::ParseLocaleViewDistance(void) HANDLE_PACKET_READ(ReadChar, char, ChatFlags); HANDLE_PACKET_READ(ReadChar, char, ClientDifficulty); HANDLE_PACKET_READ(ReadChar, char, ShouldShowCape); // <-- new in 1.4.2 - // TODO: m_Client->HandleLocale(Locale); + m_Client->SetLocale(Locale); // TODO: m_Client->HandleViewDistance(ViewDistance); // TODO: m_Client->HandleChatFlags(ChatFlags); // Ignoring client difficulty diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 1dfa5ec90..f7d13774d 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1598,6 +1598,8 @@ void cProtocol172::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ChatColors); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Difficulty); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ShowCape); + + m_Client->SetLocale(Locale); // TODO: handle in m_Client } From f42ad4e9f7e06a95ce1f5a9b3f7ae0246f81e6d5 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 04:30:45 -0800 Subject: [PATCH 055/106] can Now build ProtoProxy alongside MCServer --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c8daf915..18d1fc1c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ enable_language(CXX C) #THis has to be done before any flags have been set up. if(${BUILD_TOOLS}) add_subdirectory(Tools/MCADefrag/) + add_subdirectory(Tools/ProtoProxy/) endif() if(${BUILD_UNSTABLE_TOOLS}) @@ -51,7 +52,7 @@ add_subdirectory(lib/md5/) # We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used # (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those) -add_subdirectory(lib/polarssl/ EXCLUDE_FROM_ALL) +include(lib/polarssl.cmake) set_exe_flags() From e3dd931be21b234eaf17ab816f25854d5a3fdd34 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 04:39:41 -0800 Subject: [PATCH 056/106] Fogot --- lib/polarssl.cmake | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 lib/polarssl.cmake diff --git a/lib/polarssl.cmake b/lib/polarssl.cmake new file mode 100644 index 000000000..d57cc9220 --- /dev/null +++ b/lib/polarssl.cmake @@ -0,0 +1,5 @@ + +if(NOT TARGET polarssl) + message("including polarssl") + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL ) +endif() From d4f2788008d413f2b2031d55759e54b952d0a964 Mon Sep 17 00:00:00 2001 From: narroo Date: Sun, 16 Feb 2014 07:49:09 -0500 Subject: [PATCH 057/106] Changed char[] to unsigned char[] in cIniFile::RemoveBom --- lib/inifile/iniFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index 7b0df3d68..e2a91c4c2 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -834,7 +834,7 @@ AString cIniFile::CheckCase(const AString & s) const void cIniFile::RemoveBom(AString & a_line) const { // The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF ( In Unicode Latin I:  ) - static char BOM[] = { 0xEF, 0xBB, 0xBF }; + static unsigned char BOM[] = { 0xEF, 0xBB, 0xBF }; // The BOM sequence, if present, is always the first three characters of the input. if (a_line.compare(0, 3, BOM) == 0) From 2b0b2b7425c75ddb6d7cc6ea73860698d2b362be Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 04:49:50 -0800 Subject: [PATCH 058/106] Build cmake built tools in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 38dd2f280..c6537cf47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ compiler: - gcc - clang # Build MCServer -script: cmake . -DCMAKE_BUILD_TYPE=RELEASE -DSELF_TEST=1 && make -j 2 && cd MCServer/ && (echo stop | ./MCServer) +script: cmake . -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_TOOLS=1 -DSELF_TEST=1 && make -j 2 && cd MCServer/ && (echo stop | ./MCServer) # Notification Settings notifications: From 03fd3b556a3842da5e359f5c2317d1b62c8e14fd Mon Sep 17 00:00:00 2001 From: narroo Date: Sun, 16 Feb 2014 08:22:10 -0500 Subject: [PATCH 059/106] Changed unsigned char[] back to char[]. --- lib/inifile/iniFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index e2a91c4c2..db48ad25d 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -834,7 +834,7 @@ AString cIniFile::CheckCase(const AString & s) const void cIniFile::RemoveBom(AString & a_line) const { // The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF ( In Unicode Latin I:  ) - static unsigned char BOM[] = { 0xEF, 0xBB, 0xBF }; + static const AString BOM = "" + 0xEF + 0xBB + 0xBF; // The BOM sequence, if present, is always the first three characters of the input. if (a_line.compare(0, 3, BOM) == 0) From 6b64a722b85d2f1ab6ddba7b874fd2ad43443ef2 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 16 Feb 2014 14:34:20 +0100 Subject: [PATCH 060/106] Fixed cmake invocation text The docs say: cmake --- COMPILING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/COMPILING.md b/COMPILING.md index 94220f9c6..139f1a0ee 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -69,7 +69,7 @@ Assuming you are in the MCServer folder created in the initial setup step, you n ``` mkdir Release cd Release -cmake .. -DCMAKE_BUILD_TYPE=RELEASE && make +cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make ``` The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`. @@ -81,7 +81,7 @@ Assuming you are in the MCServer folder created in the Getting the sources step, ``` mkdir Debug cd Debug -cmake .. -DCMAKE_BUILD_TYPE=DEBUG && make +cmake -DCMAKE_BUILD_TYPE=DEBUG .. && make ``` The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`. From 4908b6f500aa31ca550536c7e5a49e660ff72b65 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 13:37:36 +0000 Subject: [PATCH 061/106] Fixed minor formatting issues from #682 - Removed unused PlaySoundEffect * Simplified and parenthesised code --- src/Entities/ExpOrb.cpp | 6 ++---- src/Entities/Player.cpp | 11 +---------- src/Entities/Player.h | 2 -- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp index 41b60cc3b..3398f1c7b 100644 --- a/src/Entities/ExpOrb.cpp +++ b/src/Entities/ExpOrb.cpp @@ -52,11 +52,9 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk) LOGD("Player %s picked up an ExpOrb. His reward is %i", a_ClosestPlayer->GetName().c_str(), m_Reward); a_ClosestPlayer->DeltaExperience(m_Reward); - float r1 = (float) (0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64); // Random Float Value - float r2 = (float) (0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64); // Random Float Value - m_World->BroadcastSoundEffect("random.orb", (int) (GetPosX() * 8.0F), (int) (GetPosY() * 8.0F), (int) (GetPosZ() * 8.0F), 0.1F, 0.5F * ((r1 - r2) * 0.7F + 1.8F)); + m_World->BroadcastSoundEffect("random.orb", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); - Destroy(true); + Destroy(); } a_Distance.Normalize(); a_Distance *= ((float) (5.5 - Distance)); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index be26e4f6e..70ddb3c98 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1059,15 +1059,6 @@ void cPlayer::CloseWindowIfID(char a_WindowID, bool a_CanRefuse) -void cPlayer::PlaySoundEffect(const AString & a_SoundName, float a_Volume, float a_Pitch) -{ - m_ClientHandle->SendSoundEffect(a_SoundName, (int) (GetPosX() * 8.0), (int) (GetPosY() * 8.0), (int) (GetPosZ() * 8.0), a_Volume, a_Pitch); -} - - - - - void cPlayer::SetLastBlockActionTime() { if (m_World != NULL) @@ -1796,7 +1787,7 @@ void cPlayer::HandleFood(void) Heal(1); m_FoodExhaustionLevel += 3; } - else if (m_FoodLevel <= 0 && m_Health > 1) + else if ((m_FoodLevel <= 0) && (m_Health > 1)) { // Damage from starving TakeDamage(dtStarving, NULL, 1, 1, 0); diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 838f0301d..53e4b56db 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -208,8 +208,6 @@ public: const AString & GetName(void) const { return m_PlayerName; } void SetName(const AString & a_Name) { m_PlayerName = a_Name; } - void PlaySoundEffect(const AString & a_SoundName, float a_Volume, float a_Pitch); - // tolua_end typedef std::list< cGroup* > GroupList; From 1a84102b102304945ea1e2c5ecf13075946b3a4a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 13:47:55 +0000 Subject: [PATCH 062/106] Slight cleanup of wolf code --- src/Mobs/Wolf.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index ff324d073..43949d4ce 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -124,12 +124,6 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); } - - // The wolf is sitting so don't move him at all. - if (IsSitting()) - { - m_bMovingToDestination = false; - } cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (a_Closest_Player != NULL) @@ -148,18 +142,15 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) SetIsBegging(true); m_World->BroadcastEntityMetadata(*this); } + // Don't move to the player if the wolf is sitting. if (IsSitting()) { m_bMovingToDestination = false; + return; } - else - { - m_bMovingToDestination = true; - } - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - PlayerPos.y++; - m_FinalDestination = PlayerPos; + + MoveToPosition(a_Closest_Player->GetPosition()); break; } default: @@ -173,7 +164,7 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) } } - if (IsTame()) + if (IsTame() && !IsSitting()) { TickFollowPlayer(); } @@ -196,6 +187,7 @@ void cWolf::TickFollowPlayer() public: Vector3d OwnerPos; } Callback; + if (m_World->DoWithPlayer(m_OwnerName, Callback)) { // The player is present in the world, follow him: @@ -210,15 +202,7 @@ void cWolf::TickFollowPlayer() } else { - m_FinalDestination = Callback.OwnerPos; - if (IsSitting()) - { - m_bMovingToDestination = false; - } - else - { - m_bMovingToDestination = true; - } + MoveToPosition(Callback.OwnerPos); } } } From 761857bd01e7eb42b87504c400d636a0b82a4cf0 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 05:55:37 -0800 Subject: [PATCH 063/106] Fixed comment --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d1fc1c8..05b6d879b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required (VERSION 2.6) # Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html ) enable_language(CXX C) -#THis has to be done before any flags have been set up. +# This has to be done before any flags have been set up. if(${BUILD_TOOLS}) add_subdirectory(Tools/MCADefrag/) add_subdirectory(Tools/ProtoProxy/) From 6eefd54d455d172f7b77819bf9975ed933477c1c Mon Sep 17 00:00:00 2001 From: narroo Date: Sun, 16 Feb 2014 09:25:32 -0500 Subject: [PATCH 064/106] Reworked RemoveBom to use unsigned chars and reverted the logic changes in WriteFile. Should work fine now. --- lib/inifile/iniFile.cpp | 186 +++++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 86 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index db48ad25d..fbbf5c197 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -83,97 +83,102 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) } } - if (getline(f, line)) + bool IsFirstLine = true; + + while (getline(f, line)) { + // To be compatible with Win32, check for existence of '\r'. + // Win32 files have the '\r' and Unix files don't at the end of a line. + // Note that the '\r' will be written to INI files from + // Unix so that the created INI file can be read under Win32 + // without change. + // Removes UTF-8 Byte Order Markers (BOM) if, present. - RemoveBom(line); - - do + if (IsFirstLine) { - // To be compatible with Win32, check for existence of '\r'. - // Win32 files have the '\r' and Unix files don't at the end of a line. - // Note that the '\r' will be written to INI files from - // Unix so that the created INI file can be read under Win32 - // without change. - size_t lineLength = line.length(); - if (lineLength == 0) - { - continue; - } - if (line[lineLength - 1] == '\r') - { - line = line.substr(0, lineLength - 1); - } + RemoveBom(line); + IsFirstLine = false; + } - if (line.length() == 0) - { - continue; - } - - // Check that the user hasn't opened a binary file by checking the first - // character of each line! - if (!isprint(line[0])) - { - printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]); - f.close(); - return false; - } - if ((pLeft = line.find_first_of(";#[=")) == AString::npos) - { - continue; - } - - switch (line[pLeft]) - { - case '[': - { - if ( - ((pRight = line.find_last_of("]")) != AString::npos) && - (pRight > pLeft) - ) - { - keyname = line.substr(pLeft + 1, pRight - pLeft - 1); - AddKeyName(keyname); - } - break; - } - - case '=': - { - valuename = line.substr(0, pLeft); - value = line.substr(pLeft + 1); - AddValue(keyname, valuename, value); - break; - } - - case ';': - case '#': - { - if (names.size() == 0) - { - AddHeaderComment(line.substr(pLeft + 1)); - } - else - { - AddKeyComment(keyname, line.substr(pLeft + 1)); - } - break; - } - } // switch (line[pLeft]) - } while (getline(f, line)); // do - - f.close(); - if (names.size() == 0) + size_t lineLength = line.length(); + if (lineLength == 0) { + continue; + } + if (line[lineLength - 1] == '\r') + { + line = line.substr(0, lineLength - 1); + } + + if (line.length() == 0) + { + continue; + } + + // Check that the user hasn't opened a binary file by checking the first + // character of each line! + if (!isprint(line[0])) + { + printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]); + f.close(); return false; } - - if (IsFromExampleRedirect) + if ((pLeft = line.find_first_of(";#[=")) == AString::npos) { - WriteFile(FILE_IO_PREFIX + a_FileName); + continue; } - return true; + + switch (line[pLeft]) + { + case '[': + { + if ( + ((pRight = line.find_last_of("]")) != AString::npos) && + (pRight > pLeft) + ) + { + keyname = line.substr(pLeft + 1, pRight - pLeft - 1); + AddKeyName(keyname); + } + break; + } + + case '=': + { + valuename = line.substr(0, pLeft); + value = line.substr(pLeft + 1); + AddValue(keyname, valuename, value); + break; + } + + case ';': + case '#': + { + if (names.size() == 0) + { + AddHeaderComment(line.substr(pLeft + 1)); + } + else + { + AddKeyComment(keyname, line.substr(pLeft + 1)); + } + break; + } + } // switch (line[pLeft]) + } // while(getline(f, line)) + + f.close(); + if (names.size() == 0) + { + return false; } + + if (IsFromExampleRedirect) + { + WriteFile(FILE_IO_PREFIX + a_FileName); + } + + return true; } @@ -833,14 +838,23 @@ AString cIniFile::CheckCase(const AString & s) const void cIniFile::RemoveBom(AString & a_line) const { - // The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF ( In Unicode Latin I:  ) - static const AString BOM = "" + 0xEF + 0xBB + 0xBF; + // The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF + static unsigned const char BOM[] = { 0xEF, 0xBB, 0xBF }; - // The BOM sequence, if present, is always the first three characters of the input. - if (a_line.compare(0, 3, BOM) == 0) + // The BOM sequence, if present, is always th e first three characters of the input. + const AString ref = a_line.substr(0, 3); + + // If any of the first three chars do not match, return and do nothing. + for (int i = 0; i < 3; ++i) { - a_line.erase(0, 3); + if (static_cast(ref[i]) != BOM[i]) + { + return; + } } + + // First three characters match; erase them. + a_line.erase(0, 3); } From 6da2d2bb21000bf15f745c171e7a6d9d0e584084 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 16 Feb 2014 07:04:44 -0800 Subject: [PATCH 065/106] Added -Wextra --- SetFlags.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SetFlags.cmake b/SetFlags.cmake index 162560c90..ded57e6d7 100644 --- a/SetFlags.cmake +++ b/SetFlags.cmake @@ -183,7 +183,7 @@ macro(set_exe_flags) string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - add_flags_cxx("-Wall") + add_flags_cxx("-Wall -Wextra") endif() endmacro() From 2350b77bb5fa2de05a619a3646662c9fc00ace28 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 17:08:49 +0000 Subject: [PATCH 066/106] Fixes to previous commit --- src/Mobs/Wolf.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 43949d4ce..2736c3dd1 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -143,14 +143,14 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) m_World->BroadcastEntityMetadata(*this); } + m_FinalDestination = a_Closest_Player->GetPosition(); // So that we will look at a player holding food + // Don't move to the player if the wolf is sitting. - if (IsSitting()) + if (!IsSitting()) { - m_bMovingToDestination = false; - return; + MoveToPosition(a_Closest_Player->GetPosition()); } - MoveToPosition(a_Closest_Player->GetPosition()); break; } default: @@ -168,6 +168,10 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) { TickFollowPlayer(); } + else if (IsSitting()) + { + m_bMovingToDestination = false; + } } @@ -194,11 +198,8 @@ void cWolf::TickFollowPlayer() double Distance = (Callback.OwnerPos - GetPosition()).Length(); if (Distance > 30) { - if (!IsSitting()) - { - Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z); - TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); - } + Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z); + TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); } else { From 60bcf2807a293dcf0a6fcc604a7e36c824a02110 Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Sun, 16 Feb 2014 18:18:07 +0100 Subject: [PATCH 067/106] Now mobs can't escape from fences. --- src/Mobs/Monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 9817901c9..1690d3a31 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -142,11 +142,11 @@ void cMonster::TickPathFinding() BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ); BLOCKTYPE BlockAtYM = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY - 1, gCrossCoords[i].z + PosZ); - if (!g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !IsBlockLava(BlockAtYM)) + if (!g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !IsBlockLava(BlockAtYM) && BlockAtY!=E_BLOCK_FENCE && BlockAtY!=E_BLOCK_FENCE_GATE) { m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ)); } - else if (g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !g_BlockIsSolid[BlockAtYPP] && !IsBlockLava(BlockAtYM)) + else if (g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !g_BlockIsSolid[BlockAtYPP] && !IsBlockLava(BlockAtYM) && BlockAtY!=E_BLOCK_FENCE && BlockAtY!=E_BLOCK_FENCE_GATE) { m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ)); } From e0868c5c062ec81ec268942657517cc8119034c0 Mon Sep 17 00:00:00 2001 From: MuhammadWang Date: Mon, 17 Feb 2014 01:16:00 +0800 Subject: [PATCH 068/106] Added files for eclipse and debug, fix a mistake src/Bindings/BindingsDependecies.txt is a mistake made in 45bc1ff033271bc0c6a9e5931a00c554e065c375 --- .gitignore | 5 ++++- MCServer/.gitignore | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 007b21519..c8ad93a80 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ cloc.xsl *.*~ *~ *.orig +## Eclipse +.cproject +.project # world inside source ChunkWorx.ini @@ -57,7 +60,7 @@ install_mainfest.txt src/MCServer lib/tolua++/tolua src/Bindings/Bindings.* -src/Bindings/BindingsDependecies.txt +src/Bindings/BindingDependecies.txt MCServer.dir/ #win32 cmake stuff diff --git a/MCServer/.gitignore b/MCServer/.gitignore index e3aebbf92..0fd04ef59 100644 --- a/MCServer/.gitignore +++ b/MCServer/.gitignore @@ -4,6 +4,7 @@ *.lib *.ini MCServer +MCServer_debug CommLogs/ logs players From b0dbe512100dd2ce506d78065e415a648faf7f0d Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 16 Feb 2014 23:30:50 +0100 Subject: [PATCH 069/106] Fixed cBoundingBox self-test code-style. Also made the class name unique and the global variable static, to avoid linkage problems with other self-tests --- src/BoundingBox.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/BoundingBox.cpp b/src/BoundingBox.cpp index 47b135688..aab51c539 100644 --- a/src/BoundingBox.cpp +++ b/src/BoundingBox.cpp @@ -12,25 +12,25 @@ #if SELF_TEST -/// A simple self-test that is executed on program start, used to verify bbox functionality -class SelfTest +/** A simple self-test that is executed on program start, used to verify bbox functionality */ +static class SelfTest_BoundingBox { public: - SelfTest(void) + SelfTest_BoundingBox(void) { Vector3d Min(1, 1, 1); Vector3d Max(2, 2, 2); Vector3d LineDefs[] = { - Vector3d(1.5, 4, 1.5), Vector3d(1.5, 3, 1.5), // Should intersect at 2, face 1 (YP) + Vector3d(1.5, 4, 1.5), Vector3d(1.5, 3, 1.5), // Should intersect at 2, face 1 (YP) Vector3d(1.5, 0, 1.5), Vector3d(1.5, 4, 1.5), // Should intersect at 0.25, face 0 (YM) Vector3d(0, 0, 0), Vector3d(2, 2, 2), // Should intersect at 0.5, face 0, 3 or 5 (anyM) Vector3d(0.999, 0, 1.5), Vector3d(0.999, 4, 1.5), // Should not intersect Vector3d(1.999, 0, 1.5), Vector3d(1.999, 4, 1.5), // Should intersect at 0.25, face 0 (YM) Vector3d(2.001, 0, 1.5), Vector3d(2.001, 4, 1.5), // Should not intersect } ; - bool Results[] = {true,true,true,false,true,false}; - double LineCoeffs[] = {2,0.25,0.5,0,0.25,0}; + bool Results[] = {true, true, true, false, true, false}; + double LineCoeffs[] = {2, 0.25, 0.5, 0, 0.25, 0}; for (size_t i = 0; i < ARRAYCOUNT(LineDefs) / 2; i++) { @@ -41,7 +41,7 @@ public: bool res = cBoundingBox::CalcLineIntersection(Min, Max, Line1, Line2, LineCoeff, Face); if (res != Results[i]) { - fprintf(stderr,"LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d\n", + fprintf(stderr, "LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d\n", Line1.x, Line1.y, Line1.z, Line2.x, Line2.y, Line2.z, res ? 1 : 0, LineCoeff, Face @@ -52,7 +52,7 @@ public: { if (LineCoeff != LineCoeffs[i]) { - fprintf(stderr,"LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d\n", + fprintf(stderr, "LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d\n", Line1.x, Line1.y, Line1.z, Line2.x, Line2.y, Line2.z, res ? 1 : 0, LineCoeff, Face @@ -61,9 +61,9 @@ public: } } } // for i - LineDefs[] - fprintf(stderr,"BoundingBox selftest complete."); + fprintf(stderr, "BoundingBox selftest complete.\n"); } -} Test; +} gTest; #endif From 4a24e39ac10de4389bcbda29f51ae09f93e794ca Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 16 Feb 2014 23:31:47 +0100 Subject: [PATCH 070/106] Implemented cCompositeChat::ParseText(), incl. self-test. --- src/CompositeChat.cpp | 207 +++++++++++++++++++++++++++++++++++++++++- src/CompositeChat.h | 5 + 2 files changed, 211 insertions(+), 1 deletion(-) diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp index 16ae58f56..1893585f6 100644 --- a/src/CompositeChat.cpp +++ b/src/CompositeChat.cpp @@ -10,6 +10,96 @@ +#if SELF_TEST + +/** A simple self-test that verifies that the composite chat parser is working properly. */ +class SelfTest_CompositeChat +{ +public: + SelfTest_CompositeChat(void) + { + fprintf(stderr, "cCompositeChat self test...\n"); + TestParser1(); + TestParser2(); + TestParser3(); + TestParser4(); + TestParser5(); + fprintf(stderr, "cCompositeChat self test finished.\n"); + } + + void TestParser1(void) + { + cCompositeChat Msg; + Msg.ParseText("Testing @2color codes and http://links parser"); + const cCompositeChat::cParts & Parts = Msg.GetParts(); + assert(Parts.size() == 4); + assert(Parts[0]->m_PartType == cCompositeChat::ptText); + assert(Parts[1]->m_PartType == cCompositeChat::ptText); + assert(Parts[2]->m_PartType == cCompositeChat::ptUrl); + assert(Parts[3]->m_PartType == cCompositeChat::ptText); + assert(Parts[0]->m_Style == ""); + assert(Parts[1]->m_Style == "@2"); + assert(Parts[2]->m_Style == "@2"); + assert(Parts[3]->m_Style == "@2"); + } + + void TestParser2(void) + { + cCompositeChat Msg; + Msg.ParseText("@3Advanced stuff: @5overriding color codes and http://links.with/@4color-in-them handling"); + const cCompositeChat::cParts & Parts = Msg.GetParts(); + assert(Parts.size() == 4); + assert(Parts[0]->m_PartType == cCompositeChat::ptText); + assert(Parts[1]->m_PartType == cCompositeChat::ptText); + assert(Parts[2]->m_PartType == cCompositeChat::ptUrl); + assert(Parts[3]->m_PartType == cCompositeChat::ptText); + assert(Parts[0]->m_Style == "@3"); + assert(Parts[1]->m_Style == "@5"); + assert(Parts[2]->m_Style == "@5"); + assert(Parts[3]->m_Style == "@5"); + } + + void TestParser3(void) + { + cCompositeChat Msg; + Msg.ParseText("http://links.starting the text"); + const cCompositeChat::cParts & Parts = Msg.GetParts(); + assert(Parts.size() == 2); + assert(Parts[0]->m_PartType == cCompositeChat::ptUrl); + assert(Parts[1]->m_PartType == cCompositeChat::ptText); + assert(Parts[0]->m_Style == ""); + assert(Parts[1]->m_Style == ""); + } + + void TestParser4(void) + { + cCompositeChat Msg; + Msg.ParseText("links finishing the text: http://some.server"); + const cCompositeChat::cParts & Parts = Msg.GetParts(); + assert(Parts.size() == 2); + assert(Parts[0]->m_PartType == cCompositeChat::ptText); + assert(Parts[1]->m_PartType == cCompositeChat::ptUrl); + assert(Parts[0]->m_Style == ""); + assert(Parts[1]->m_Style == ""); + } + + void TestParser5(void) + { + cCompositeChat Msg; + Msg.ParseText("http://only.links"); + const cCompositeChat::cParts & Parts = Msg.GetParts(); + assert(Parts.size() == 1); + assert(Parts[0]->m_PartType == cCompositeChat::ptUrl); + assert(Parts[0]->m_Style == ""); + } + +} gTest; +#endif // SELF_TEST + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cCompositeChat: @@ -101,7 +191,99 @@ void cCompositeChat::AddSuggestCommandPart(const AString & a_Text, const AString void cCompositeChat::ParseText(const AString & a_ParseText) { - // TODO + size_t len = a_ParseText.length(); + size_t first = 0; // First character of the currently parsed block + AString CurrentStyle; + AString CurrentText; + for (size_t i = 0; i < len; i++) + { + switch (a_ParseText[i]) + { + case '@': + { + // Color code + i++; + if (i >= len) + { + // Not enough following text + break; + } + if (a_ParseText[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; + } + 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()) + { + m_Parts.push_back(new cTextPart(CurrentText, CurrentStyle)); + CurrentText.clear(); + } + AddStyle(CurrentStyle, a_ParseText.substr(i - 1, 2)); + } + break; + } + + case ':': + { + const char * LinkPrefixes[] = + { + "http", + "https" + }; + for (size_t Prefix = 0; Prefix < ARRAYCOUNT(LinkPrefixes); Prefix++) + { + size_t PrefixLen = strlen(LinkPrefixes[Prefix]); + if ( + (i >= first + PrefixLen) && // There is enough space in front of the colon for the prefix + (strncmp(a_ParseText.c_str() + i - PrefixLen, LinkPrefixes[Prefix], PrefixLen) == 0) // the prefix matches + ) + { + // Add everything before this as a text part: + if (i > first + PrefixLen) + { + CurrentText.append(a_ParseText.c_str() + first, i - first - PrefixLen); + first = i - PrefixLen; + } + if (!CurrentText.empty()) + { + AddTextPart(CurrentText, CurrentStyle); + CurrentText.clear(); + } + + // Go till the last non-whitespace char in the text: + for (; i < len; i++) + { + if (isspace(a_ParseText[i])) + { + break; + } + } + AddUrlPart(a_ParseText.substr(first, i - first), a_ParseText.substr(first, i - first), CurrentStyle); + first = i; + break; + } + } // for Prefix - LinkPrefix[] + break; + } // case ':' + } // switch (a_ParseText[i]) + } // for i - a_ParseText[] + if (first < len) + { + AddTextPart(a_ParseText.substr(first, len - first), CurrentStyle); + } } @@ -117,6 +299,29 @@ void cCompositeChat::SetMessageType(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); +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cCompositeChat::cBasePart: diff --git a/src/CompositeChat.h b/src/CompositeChat.h index e220f6345..4b3523b08 100644 --- a/src/CompositeChat.h +++ b/src/CompositeChat.h @@ -165,6 +165,11 @@ protected: /** The message type, as indicated by prefixes. */ eMessageType m_MessageType; + + + /** 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 From ea55a22a71a6fd46877bc4b6b56d6205dd20608f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 16 Feb 2014 23:51:32 +0100 Subject: [PATCH 071/106] Links sent via chat messages are clickable. Fixes #658. --- src/ClientHandle.cpp | 22 ++++++++++++++-------- src/CompositeChat.cpp | 15 +++++++++++++++ src/CompositeChat.h | 3 +++ src/Entities/Player.h | 3 ++- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index b46bcfd47..c91a0c01b 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1089,14 +1089,20 @@ void cClientHandle::HandleChat(const AString & a_Message) return; } - // Not a command, broadcast as a simple message: - AString Msg; - Printf(Msg, "%s<%s>%s %s", - m_Player->GetColor().c_str(), - m_Player->GetName().c_str(), - cChatColor::White.c_str(), - Message.c_str() - ); + // Not a command, broadcast as a message: + cCompositeChat Msg; + AString Color = m_Player->GetColor(); + if (Color.length() == 3) + { + Color = AString("@") + Color[2]; + } + else + { + Color.empty(); + } + Msg.AddTextPart(AString("<") + m_Player->GetName() + "> ", Color); + Msg.ParseText(a_Message); + Msg.UnderlineUrls(); m_Player->GetWorld()->BroadcastChat(Msg); } diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp index 1893585f6..3eec35657 100644 --- a/src/CompositeChat.cpp +++ b/src/CompositeChat.cpp @@ -299,6 +299,21 @@ void cCompositeChat::SetMessageType(eMessageType a_MessageType) +void cCompositeChat::UnderlineUrls(void) +{ + for (cParts::iterator itr = m_Parts.begin(), end = m_Parts.end(); itr != end; ++itr) + { + if ((*itr)->m_PartType == ptUrl) + { + (*itr)->m_Style.append("u"); + } + } // for itr - m_Parts[] +} + + + + + void cCompositeChat::AddStyle(AString & a_Style, const AString & a_AddStyle) { if (a_AddStyle.empty()) diff --git a/src/CompositeChat.h b/src/CompositeChat.h index 4b3523b08..8963bb520 100644 --- a/src/CompositeChat.h +++ b/src/CompositeChat.h @@ -155,6 +155,9 @@ public: /** 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_end const cParts & GetParts(void) const { return m_Parts; } diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 53e4b56db..a795bb9eb 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -226,7 +226,8 @@ public: // tolua_begin - /// Returns the full color code to use for this player, based on their primary group or set in m_Color + /** Returns the full color code to use for this player, based on their primary group or set in m_Color. + The returned value includes the cChatColor::Delimiter. */ AString GetColor(void) const; /** tosses the item in the selected hotbar slot */ From a4ff63f223d5a9b20e71286975d7a6d5f0c00f17 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 10:15:18 +0100 Subject: [PATCH 072/106] Fixed a memory leak in CompositeChat. --- src/CompositeChat.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CompositeChat.h b/src/CompositeChat.h index 8963bb520..51600da4f 100644 --- a/src/CompositeChat.h +++ b/src/CompositeChat.h @@ -48,6 +48,9 @@ public: AString m_Style; cBasePart(ePartType a_PartType, const AString & a_Text, const AString & a_Style = ""); + + // Force a virtual destructor in descendants + virtual ~cBasePart() {} } ; class cTextPart : From 3ce8bf9712f09bf670e3cb11138c7be9bb26b211 Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 17 Feb 2014 08:45:31 -0500 Subject: [PATCH 073/106] Fixed Tab spacing of cases. --- lib/inifile/iniFile.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index fbbf5c197..212c1d14d 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -130,8 +130,8 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) switch (line[pLeft]) { - case '[': - { + case '[': + { if ( ((pRight = line.find_last_of("]")) != AString::npos) && (pRight > pLeft) @@ -141,19 +141,19 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) AddKeyName(keyname); } break; - } + } - case '=': - { + case '=': + { valuename = line.substr(0, pLeft); value = line.substr(pLeft + 1); AddValue(keyname, valuename, value); break; - } + } - case ';': - case '#': - { + case ';': + case '#': + { if (names.size() == 0) { AddHeaderComment(line.substr(pLeft + 1)); @@ -163,7 +163,7 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) AddKeyComment(keyname, line.substr(pLeft + 1)); } break; - } + } } // switch (line[pLeft]) } // while(getline(f, line)) From ecabb2b34f8dea427868f76019a1dd7f2b031bf9 Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 17 Feb 2014 08:46:41 -0500 Subject: [PATCH 074/106] Fixed the tab spacing. --- lib/inifile/iniFile.cpp | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index 212c1d14d..9c5300cdf 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -132,37 +132,37 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) { case '[': { - if ( - ((pRight = line.find_last_of("]")) != AString::npos) && - (pRight > pLeft) - ) - { - keyname = line.substr(pLeft + 1, pRight - pLeft - 1); - AddKeyName(keyname); - } - break; + if ( + ((pRight = line.find_last_of("]")) != AString::npos) && + (pRight > pLeft) + ) + { + keyname = line.substr(pLeft + 1, pRight - pLeft - 1); + AddKeyName(keyname); + } + break; } case '=': { - valuename = line.substr(0, pLeft); - value = line.substr(pLeft + 1); - AddValue(keyname, valuename, value); - break; + valuename = line.substr(0, pLeft); + value = line.substr(pLeft + 1); + AddValue(keyname, valuename, value); + break; } case ';': case '#': { - if (names.size() == 0) - { - AddHeaderComment(line.substr(pLeft + 1)); - } - else - { - AddKeyComment(keyname, line.substr(pLeft + 1)); - } - break; + if (names.size() == 0) + { + AddHeaderComment(line.substr(pLeft + 1)); + } + else + { + AddKeyComment(keyname, line.substr(pLeft + 1)); + } + break; } } // switch (line[pLeft]) } // while(getline(f, line)) From 952a338c7f5518bacd5b733ecbcc62c02cfc60b2 Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 17 Feb 2014 08:50:22 -0500 Subject: [PATCH 075/106] Fixed Comment Typo. --- lib/inifile/iniFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index 9c5300cdf..c56292059 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -165,7 +165,7 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) break; } } // switch (line[pLeft]) - } // while(getline(f, line)) + } // while(getline()) f.close(); if (names.size() == 0) From 794be05f229009ae9e00150b50ccff908b71b1fd Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 17 Feb 2014 08:51:36 -0500 Subject: [PATCH 076/106] Fixed comment typo --- lib/inifile/iniFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index c56292059..cf8b63987 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -165,7 +165,7 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) break; } } // switch (line[pLeft]) - } // while(getline()) + } // while (getline()) f.close(); if (names.size() == 0) From 8707f7ddc812037f022e46fa7d0d6a56a9c55728 Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Mon, 17 Feb 2014 17:01:22 +0100 Subject: [PATCH 077/106] Improved formatting --- src/Mobs/Monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 1690d3a31..b5cf693cb 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -142,11 +142,11 @@ void cMonster::TickPathFinding() BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ); BLOCKTYPE BlockAtYM = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY - 1, gCrossCoords[i].z + PosZ); - if (!g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !IsBlockLava(BlockAtYM) && BlockAtY!=E_BLOCK_FENCE && BlockAtY!=E_BLOCK_FENCE_GATE) + if ((!g_BlockIsSolid[BlockAtY]) && (!g_BlockIsSolid[BlockAtYP]) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE)) { m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ)); } - else if (g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !g_BlockIsSolid[BlockAtYPP] && !IsBlockLava(BlockAtYM) && BlockAtY!=E_BLOCK_FENCE && BlockAtY!=E_BLOCK_FENCE_GATE) + else if ((g_BlockIsSolid[BlockAtY]) && (!g_BlockIsSolid[BlockAtYP]) && (!g_BlockIsSolid[BlockAtYPP]) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE)) { m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ)); } From 777041806fb5085e94838fa9bb0b1c3fe0b61696 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 17 Feb 2014 20:14:08 +0100 Subject: [PATCH 078/106] Add Skulls/Heads --- src/BlockEntities/BlockEntity.cpp | 2 + src/BlockEntities/SkullEntity.cpp | 110 ++++++++++++++++++++++++ src/BlockEntities/SkullEntity.h | 79 +++++++++++++++++ src/CMakeLists.txt | 1 + src/Chunk.cpp | 2 + src/Defines.h | 37 ++++++++ src/Items/ItemHandler.cpp | 2 + src/Items/ItemSkull.h | 43 +++++++++ src/Protocol/Protocol17x.cpp | 14 +++ src/WorldStorage/NBTChunkSerializer.cpp | 26 ++++-- src/WorldStorage/NBTChunkSerializer.h | 2 + src/WorldStorage/WSSAnvil.cpp | 40 +++++++++ src/WorldStorage/WSSAnvil.h | 1 + 13 files changed, 354 insertions(+), 5 deletions(-) create mode 100644 src/BlockEntities/SkullEntity.cpp create mode 100644 src/BlockEntities/SkullEntity.h create mode 100644 src/Items/ItemSkull.h diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp index 97b5c1a66..441f54a26 100644 --- a/src/BlockEntities/BlockEntity.cpp +++ b/src/BlockEntities/BlockEntity.cpp @@ -15,6 +15,7 @@ #include "JukeboxEntity.h" #include "NoteEntity.h" #include "SignEntity.h" +#include "SkullEntity.h" @@ -31,6 +32,7 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); + case E_BLOCK_HEAD: return new cSkullEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta, a_World); case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World); diff --git a/src/BlockEntities/SkullEntity.cpp b/src/BlockEntities/SkullEntity.cpp new file mode 100644 index 000000000..3f3bc00ed --- /dev/null +++ b/src/BlockEntities/SkullEntity.cpp @@ -0,0 +1,110 @@ + +// SkullEntity.cpp + +// Implements the cSkullEntity class representing a single skull/head in the world + +#include "Globals.h" +#include "json/json.h" +#include "SkullEntity.h" +#include "../Entities/Player.h" + + + + + +cSkullEntity::cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta, cWorld * a_World) : + super(E_BLOCK_HEAD, a_BlockX, a_BlockY, a_BlockZ, a_World), + //m_SkullType(static_cast(a_BlockMeta)), + m_Owner("") +{ + +} + + + + + +void cSkullEntity::UsedBy(cPlayer * a_Player) +{ + UNUSED(a_Player); +} + + + + + +void cSkullEntity::SetSkullType(const eSkullType & a_SkullType) +{ + if ((!m_Owner.empty()) && (a_SkullType != SKULL_TYPE_PLAYER)) + { + m_Owner = ""; + } + m_SkullType = a_SkullType; +} + + + + + +void cSkullEntity::SetRotation(eSkullRotation a_Rotation) +{ + m_Rotation = a_Rotation; +} + + + + + +void cSkullEntity::SetOwner(const AString & a_Owner) +{ + if ((a_Owner.length() > 16) || (m_SkullType != SKULL_TYPE_PLAYER)) + { + return; + } + m_Owner = a_Owner; +} + + + + + +void cSkullEntity::SendTo(cClientHandle & a_Client) +{ + a_Client.SendUpdateBlockEntity(*this); +} + + + + + +bool cSkullEntity::LoadFromJson(const Json::Value & a_Value) +{ + m_PosX = a_Value.get("x", 0).asInt(); + m_PosY = a_Value.get("y", 0).asInt(); + m_PosZ = a_Value.get("z", 0).asInt(); + + m_SkullType = static_cast(a_Value.get("SkullType", 0).asInt()); + m_Rotation = static_cast(a_Value.get("Rotation", 0).asInt()); + m_Owner = a_Value.get("Owner", "").asString(); + + return true; +} + + + + + +void cSkullEntity::SaveToJson(Json::Value & a_Value) +{ + a_Value["x"] = m_PosX; + a_Value["y"] = m_PosY; + a_Value["z"] = m_PosZ; + + a_Value["SkullType"] = m_SkullType; + a_Value["Rotation"] = m_Rotation; + a_Value["Owner"] = m_Owner; +} + + + + diff --git a/src/BlockEntities/SkullEntity.h b/src/BlockEntities/SkullEntity.h new file mode 100644 index 000000000..6f47c7d30 --- /dev/null +++ b/src/BlockEntities/SkullEntity.h @@ -0,0 +1,79 @@ +// SkullEntity.h + +// Declares the cSkullEntity class representing a single skull/head in the world + + + + + +#pragma once + +#include "BlockEntity.h" + + + + + +namespace Json +{ + class Value; +} + + + + + +// tolua_begin + +class cSkullEntity : + public cBlockEntity +{ + typedef cBlockEntity super; + +public: + + // tolua_end + + /// Creates a new skull entity at the specified block coords. a_World may be NULL + cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta, cWorld * a_World); + + bool LoadFromJson( const Json::Value& a_Value ); + virtual void SaveToJson(Json::Value& a_Value ) override; + + // tolua_begin + + /// Set the Skull Type + void SetSkullType(const eSkullType & a_SkullType); + + /// Set the Rotation + void SetRotation(eSkullRotation a_Rotation); + + // Set the Player Name for Player Skulls + void SetOwner(const AString & a_Owner); + + /// Get the Skull Type + eSkullType GetSkullType(void) const { return m_SkullType; } + + /// Get the Rotation + eSkullRotation GetRotation(void) const { return m_Rotation; } + + /// Get the setted Player Name + AString GetOwner(void) const { return m_Owner; } + + // tolua_end + + virtual void UsedBy(cPlayer * a_Player) override; + virtual void SendTo(cClientHandle & a_Client) override; + + static const char * GetClassStatic(void) { return "cSkullEntity"; } + +private: + + eSkullType m_SkullType; + eSkullRotation m_Rotation; + AString m_Owner; +} ; // tolua_export + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ba952f92..e46aa3ee5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,7 @@ if (NOT MSVC) BlockEntities/JukeboxEntity.h BlockEntities/NoteEntity.h BlockEntities/SignEntity.h + BlockEntities/SkullEntity.h BlockID.h BoundingBox.h ChatColor.h diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 3028d24d0..c66dae7b4 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1314,6 +1314,7 @@ void cChunk::CreateBlockEntities(void) case E_BLOCK_HOPPER: case E_BLOCK_SIGN_POST: case E_BLOCK_WALLSIGN: + case E_BLOCK_HEAD: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_JUKEBOX: { @@ -1442,6 +1443,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, case E_BLOCK_HOPPER: case E_BLOCK_SIGN_POST: case E_BLOCK_WALLSIGN: + case E_BLOCK_HEAD: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_JUKEBOX: { diff --git a/src/Defines.h b/src/Defines.h index f33d1ae56..7e22cbdc5 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -174,6 +174,43 @@ enum eWeather +enum eSkullType +{ + SKULL_TYPE_SKELETON = 0, + SKULL_TYPE_WITHER = 1, + SKULL_TYPE_ZOMBIE = 2, + SKULL_TYPE_PLAYER = 3, + SKULL_TYPE_CREEPER = 4, +} ; + + + + + +enum eSkullRotation +{ + SKULL_ROTATION_NORTH = 0, + SKULL_ROTATION_NORTH_NORTH_EAST = 1, + SKULL_ROTATION_NORTH_EAST = 2, + SKULL_ROTATION_EAST_NORTH_EAST = 3, + SKULL_ROTATION_EAST = 4, + SKULL_ROTATION_EAST_SOUTH_EAST = 5, + SKULL_ROTATION_SOUTH_EAST = 6, + SKULL_ROTATION_SOUTH_SOUTH_EAST = 7, + SKULL_ROTATION_SOUTH = 8, + SKULL_ROTATION_SOUTH_SOUTH_WEST = 9, + SKULL_ROTATION_SOUTH_WEST = 10, + SKULL_ROTATION_WEST_SOUTH_WEST = 11, + SKULL_ROTATION_WEST = 12, + SKULL_ROTATION_WEST_NORTH_WEST = 13, + SKULL_ROTATION_NORTH_WEST = 14, + SKULL_ROTATION_NORTH_NORTH_WEST = 15, +} ; + + + + + inline const char * ClickActionToString(eClickAction a_ClickAction) { switch (a_ClickAction) diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 19913ab24..4ede75cf1 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -35,6 +35,7 @@ #include "ItemShears.h" #include "ItemShovel.h" #include "ItemSign.h" +#include "ItemSkull.h" #include "ItemSpawnEgg.h" #include "ItemSugarcane.h" #include "ItemSword.h" @@ -110,6 +111,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType); case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType); case E_ITEM_SIGN: return new cItemSignHandler(a_ItemType); + case E_ITEM_HEAD: return new cItemSkullHandler(a_ItemType); case E_ITEM_SNOWBALL: return new cItemSnowballHandler(); case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType); case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType); diff --git a/src/Items/ItemSkull.h b/src/Items/ItemSkull.h new file mode 100644 index 000000000..f511c8c4a --- /dev/null +++ b/src/Items/ItemSkull.h @@ -0,0 +1,43 @@ + +#pragma once + +#include "ItemHandler.h" +#include "../World.h" + + + + + +class cItemSkullHandler : + public cItemHandler +{ +public: + cItemSkullHandler(int a_ItemType) : + cItemHandler(a_ItemType) + { + } + + + virtual bool IsPlaceable(void) override + { + return true; + } + + + virtual bool GetPlacementBlockTypeMeta( + cWorld * a_World, cPlayer * a_Player, + int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, + int a_CursorX, int a_CursorY, int a_CursorZ, + BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta + ) override + { + a_BlockType = E_BLOCK_HEAD; + a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x0f); + + return true; + } +} ; + + + + diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f7d13774d..4d55822fb 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -26,6 +26,7 @@ Implements the 1.7.x protocol classes: #include "../Mobs/IncludeAllMonsters.h" #include "../UI/Window.h" #include "../BlockEntities/CommandBlockEntity.h" +#include "../BlockEntities/SkullEntity.h" #include "../CompositeChat.h" @@ -1042,6 +1043,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) { case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text + case E_BLOCK_HEAD: Action = 4; break; // Update Skull entity default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break; } Pkt.WriteByte(Action); @@ -2269,6 +2271,18 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt } break; } + case E_BLOCK_HEAD: + { + cSkullEntity & SkullEntity = (cSkullEntity &)a_BlockEntity; + + Writer.AddInt("x", SkullEntity.GetPosX()); + Writer.AddInt("y", SkullEntity.GetPosY()); + Writer.AddInt("z", SkullEntity.GetPosZ()); + Writer.AddByte("SkullType", SkullEntity.GetSkullType() & 0xFF); + Writer.AddByte("Rot", SkullEntity.GetRotation() & 0xFF); + Writer.AddString("ExtraType", SkullEntity.GetOwner().c_str()); + Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + } default: break; } diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 95b5e66d2..6da141728 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -19,6 +19,7 @@ #include "../BlockEntities/JukeboxEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" +#include "../BlockEntities/SkullEntity.h" #include "../Entities/Entity.h" #include "../Entities/FallingBlock.h" @@ -248,11 +249,25 @@ void cNBTChunkSerializer::AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock void cNBTChunkSerializer::AddSignEntity(cSignEntity * a_Sign) { m_Writer.BeginCompound(""); - AddBasicTileEntity(a_Sign, "Sign"); - m_Writer.AddString("Text1", a_Sign->GetLine(0)); - m_Writer.AddString("Text2", a_Sign->GetLine(1)); - m_Writer.AddString("Text3", a_Sign->GetLine(2)); - m_Writer.AddString("Text4", a_Sign->GetLine(3)); + AddBasicTileEntity(a_Sign, "Sign"); + m_Writer.AddString("Text1", a_Sign->GetLine(0)); + m_Writer.AddString("Text2", a_Sign->GetLine(1)); + m_Writer.AddString("Text3", a_Sign->GetLine(2)); + m_Writer.AddString("Text4", a_Sign->GetLine(3)); + m_Writer.EndCompound(); +} + + + + + +void cNBTChunkSerializer::AddSkullEntity(cSkullEntity * a_Skull) +{ + m_Writer.BeginCompound(""); + AddBasicTileEntity(a_Skull, "Skull"); + m_Writer.AddByte ("SkullType", a_Skull->GetSkullType() & 0xFF); + m_Writer.AddByte ("Rot", a_Skull->GetRotation() & 0xFF); + m_Writer.AddString("ExtraType", a_Skull->GetOwner()); m_Writer.EndCompound(); } @@ -666,6 +681,7 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity) case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break; case E_BLOCK_SIGN_POST: case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break; + case E_BLOCK_HEAD: AddSkullEntity ((cSkullEntity *) a_Entity); break; case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break; case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break; case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *) a_Entity); break; diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 245b68063..fd5601e47 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -29,6 +29,7 @@ class cHopperEntity; class cJukeboxEntity; class cNoteEntity; class cSignEntity; +class cSkullEntity; class cFallingBlock; class cMinecart; class cMinecartWithChest; @@ -93,6 +94,7 @@ protected: void AddJukeboxEntity (cJukeboxEntity * a_Jukebox); void AddNoteEntity (cNoteEntity * a_Note); void AddSignEntity (cSignEntity * a_Sign); + void AddSkullEntity (cSkullEntity * a_Skull); void AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock); // Entities: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index e95813a3c..89a236f07 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -24,6 +24,7 @@ #include "../BlockEntities/JukeboxEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" +#include "../BlockEntities/SkullEntity.h" #include "../Mobs/Monster.h" @@ -597,6 +598,10 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con { LoadSignFromNBT(a_BlockEntities, a_NBT, Child); } + else if (strncmp(a_NBT.GetData(sID), "Skull", a_NBT.GetDataLength(sID)) == 0) + { + LoadSkullFromNBT(a_BlockEntities, a_NBT, Child); + } else if (strncmp(a_NBT.GetData(sID), "Trap", a_NBT.GetDataLength(sID)) == 0) { LoadDispenserFromNBT(a_BlockEntities, a_NBT, Child); @@ -927,6 +932,41 @@ void cWSSAnvil::LoadSignFromNBT(cBlockEntityList & a_BlockEntities, const cParse +void cWSSAnvil::LoadSkullFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx) +{ + ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound); + int x, y, z; + if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z)) + { + return; + } + std::auto_ptr Skull(new cSkullEntity(E_BLOCK_HEAD, x, y, z, m_World)); + + int currentLine = a_NBT.FindChildByName(a_TagIdx, "SkullType"); + if (currentLine >= 0) + { + Skull->SetSkullType(static_cast(a_NBT.GetByte(currentLine))); + } + + currentLine = a_NBT.FindChildByName(a_TagIdx, "Rot"); + if (currentLine >= 0) + { + Skull->SetRotation(static_cast(a_NBT.GetByte(currentLine))); + } + + currentLine = a_NBT.FindChildByName(a_TagIdx, "ExtraType"); + if (currentLine >= 0) + { + Skull->SetOwner(a_NBT.GetString(currentLine)); + } + + a_BlockEntities.push_back(Skull.release()); +} + + + + + void cWSSAnvil::LoadCommandBlockFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx) { ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound); diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h index 5093ad083..9c9e17258 100644 --- a/src/WorldStorage/WSSAnvil.h +++ b/src/WorldStorage/WSSAnvil.h @@ -139,6 +139,7 @@ protected: void LoadJukeboxFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadNoteFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSignFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); + void LoadSkullFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadCommandBlockFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength); From 865ae82114c7c567f3d2580f648979ad5101e0db Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 23:12:46 +0100 Subject: [PATCH 079/106] Add Lua plugin path to package.path and .cpath. Fixes #693. --- src/Bindings/LuaState.cpp | 26 ++++++++++++++++++++++++++ src/Bindings/LuaState.h | 3 +++ src/Bindings/PluginLua.cpp | 8 ++++++++ 3 files changed, 37 insertions(+) diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index c6be7be3c..ca7f6b255 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -173,6 +173,31 @@ void cLuaState::Detach(void) +void cLuaState::AddPackagePath(const AString & a_PathVariable, const AString & a_Path) +{ + // Get the current path: + lua_getfield(m_LuaState, LUA_GLOBALSINDEX, "package"); // Stk: + lua_getfield(m_LuaState, -1, a_PathVariable.c_str()); // Stk: + size_t len = 0; + const char * PackagePath = lua_tolstring(m_LuaState, -1, &len); + + // Append the new path: + AString NewPackagePath(PackagePath, len); + NewPackagePath.append(LUA_PATHSEP); + NewPackagePath.append(a_Path); + + // Set the new path to the environment: + lua_pop(m_LuaState, 1); // Stk: + lua_pushlstring(m_LuaState, NewPackagePath.c_str(), NewPackagePath.length()); // Stk: + lua_setfield(m_LuaState, -2, a_PathVariable.c_str()); // Stk: + lua_pop(m_LuaState, 1); + lua_pop(m_LuaState, 1); // Stk: - +} + + + + + bool cLuaState::LoadFile(const AString & a_FileName) { ASSERT(IsValid()); @@ -1251,6 +1276,7 @@ void cLuaState::LogStack(lua_State * a_LuaState, const char * a_Header) case LUA_TLIGHTUSERDATA: Printf(Value, "%p", lua_touserdata(a_LuaState, i)); break; case LUA_TNUMBER: Printf(Value, "%f", (double)lua_tonumber(a_LuaState, i)); break; case LUA_TSTRING: Printf(Value, "%s", lua_tostring(a_LuaState, i)); break; + case LUA_TTABLE: Printf(Value, "%p", lua_topointer(a_LuaState, i)); break; default: break; } LOGD(" Idx %d: type %d (%s) %s", i, Type, lua_typename(a_LuaState, Type), Value.c_str()); diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index b9bf10142..dcb660c3f 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -154,6 +154,9 @@ public: /** Returns true if the m_LuaState is valid */ bool IsValid(void) const { return (m_LuaState != NULL); } + /** Adds the specified path to package. */ + void AddPackagePath(const AString & a_PathVariable, const AString & a_Path); + /** Loads the specified file Returns false and logs a warning to the console if not successful (but the LuaState is kept open). m_SubsystemName is displayed in the warning log message. diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index 773d522c4..45c8216be 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -82,6 +82,14 @@ bool cPluginLua::Initialize(void) lua_pushstring(m_LuaState, GetName().c_str()); lua_setglobal(m_LuaState, LUA_PLUGIN_NAME_VAR_NAME); + // Add the plugin's folder to the package.path and package.cpath variables (#693): + m_LuaState.AddPackagePath("path", FILE_IO_PREFIX + GetLocalFolder() + "/?.lua"); + #ifdef _WIN32 + m_LuaState.AddPackagePath("cpath", GetLocalFolder() + "\\?.dll"); + #else + m_LuaState.AddPackagePath("cpath", FILE_IO_PREFIX + GetLocalFolder() + "/?.so"); + #endif + tolua_pushusertype(m_LuaState, this, "cPluginLua"); lua_setglobal(m_LuaState, "g_Plugin"); } From 1a26f05ed0e81cb0c2cbd17ee4eb6022f094438e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 23:36:39 +0100 Subject: [PATCH 080/106] Added cPluginManager:GetPluginsPath() to the Lua API. --- src/Bindings/PluginManager.cpp | 2 +- src/Bindings/PluginManager.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index c6c8c081e..c7df6357e 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -56,7 +56,7 @@ void cPluginManager::ReloadPlugins(void) void cPluginManager::FindPlugins(void) { - AString PluginsPath = FILE_IO_PREFIX + AString( "Plugins/" ); + AString PluginsPath = GetPluginsPath() + "/"; // First get a clean list of only the currently running plugins, we don't want to mess those up for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();) diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h index c78bceda1..44bc5a8d7 100644 --- a/src/Bindings/PluginManager.h +++ b/src/Bindings/PluginManager.h @@ -266,6 +266,10 @@ public: // tolua_export Returns false if plugin not found, and the value that the callback has returned otherwise. */ bool DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback); + /** Returns the path where individual plugins' folders are expected. + The path doesn't end in a slash. */ + static AString GetPluginsPath(void) { return FILE_IO_PREFIX + AString("Plugins"); } // tolua_export + private: friend class cRoot; From 89ef81b5e887d5abdace921974f2863926778824 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 23:39:53 +0100 Subject: [PATCH 081/106] Documented the cPluginManager:GetPluginsPath() API function. --- MCServer/Plugins/APIDump/APIDesc.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 34aff5ddb..b0d31e7a8 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -1749,6 +1749,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage); GetCurrentPlugin = { Params = "", Return = "{{cPlugin}}", Notes = "Returns the {{cPlugin}} object for the calling plugin. This is the same object that the Initialize function receives as the argument." }, GetNumPlugins = { Params = "", Return = "number", Notes = "Returns the number of plugins, including the disabled ones" }, GetPlugin = { Params = "PluginName", Return = "{{cPlugin}}", Notes = "(DEPRECATED, UNSAFE) Returns a plugin handle of the specified plugin, or nil if such plugin is not loaded. Note thatdue to multithreading the handle is not guaranteed to be safe for use when stored - a single-plugin reload may have been triggered in the mean time for the requested plugin." }, + GetPluginsPath = { Params = "", Return = "string", Notes = "Returns the path where the individual plugin folders are located. Doesn't include the path separator at the end of the returned string." }, IsCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if in-game Command is already bound (by any plugin)" }, IsConsoleCommandBound = { Params = "Command", Return = "bool", Notes = "Returns true if console Command is already bound (by any plugin)" }, LoadPlugin = { Params = "PluginFolder", Return = "", Notes = "(DEPRECATED) Loads a plugin from the specified folder. NOTE: Loading plugins may be an unsafe operation and may result in a deadlock or a crash. This API is deprecated and might be removed." }, From e924d102e1a03cf148dde57cd35655faeda437e3 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 23:41:48 +0100 Subject: [PATCH 082/106] Added the InfoReg plugin library file. This file should be used by all plugins that use Info.lua to register their commands. It defines the functions that register the commands and provide handling for the subcommands. --- MCServer/Plugins/InfoReg.lua | 157 +++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 MCServer/Plugins/InfoReg.lua diff --git a/MCServer/Plugins/InfoReg.lua b/MCServer/Plugins/InfoReg.lua new file mode 100644 index 000000000..3afb57488 --- /dev/null +++ b/MCServer/Plugins/InfoReg.lua @@ -0,0 +1,157 @@ + +-- InfoReg.lua + +-- Implements registration functions that process g_PluginInfo + + + + + +--- Lists all the subcommands that the player has permissions for +local function ListSubcommands(a_Player, a_Subcommands, a_CmdString) + a_Player:SendMessage("The " .. a_CmdString .. " command requires another verb:"); + local Verbs = {}; + for cmd, info in pairs(a_Subcommands) do + if (a_Player:HasPermission(info.Permission or "")) then + table.insert(Verbs, a_CmdString .. " " .. cmd); + end + end + table.sort(Verbs); + for idx, verb in ipairs(Verbs) do + a_Player:SendMessage(verb); + end +end + + + + + +--- This is a generic command callback used for handling multicommands' parent commands +-- For example, if there are "/gal save" and "/gal load" commands, this callback handles the "/gal" command +local function MultiCommandHandler(a_Split, a_Player, a_CmdString, a_CmdInfo, a_Level) + local Verb = a_Split[a_Level + 1]; + if (Verb == nil) then + -- No verb was specified. If there is a handler for the upper level command, call it: + if (a_CmdInfo.Handler ~= nil) then + return a_CmdInfo.Handler(a_Split, a_Player); + end + -- Let the player know they need to give a subcommand: + ListSubcommands(a_Player, a_CmdInfo.Subcommands, a_CmdString); + return true; + end + + -- A verb was specified, look it up in the subcommands table: + local Subcommand = a_CmdInfo.Subcommands[Verb]; + if (Subcommand == nil) then + if (a_Level > 1) then + -- This is a true subcommand, display the message and make MCS think the command was handled + -- Otherwise we get weird behavior: for "/cmd verb" we get "unknown command /cmd" although "/cmd" is valid + a_Player:SendMessage("The " .. a_CmdString .. " command doesn't support verb " .. Verb); + return true; + end + -- This is a top-level command, let MCS handle the unknown message + return false; + end + + -- Check the permission: + if not(a_Player:HasPermission(Subcommand.Permission or "")) then + a_Player:SendMessage("You don't have permission to execute this command"); + return true; + end + + -- Check if the handler is valid: + if (Subcommand.Handler == nil) then + if (Subcommand.Subcommands == nil) then + LOG("Cannot find handler for command " .. a_CmdString .. " " .. Verb); + return false; + end + ListSubcommands(a_Player, Subcommand.Subcommands, a_CmdString .. " " .. Verb); + return true; + end + + -- Execute: + return Subcommand.Handler(a_Split, a_Player); +end + + + + + +--- Registers all commands specified in the g_PluginInfo.Commands +function RegisterPluginInfoCommands() + -- A sub-function that registers all subcommands of a single command, using the command's Subcommands table + -- The a_Prefix param already contains the space after the previous command + -- a_Level is the depth of the subcommands being registered, with 1 being the top level command + local function RegisterSubcommands(a_Prefix, a_Subcommands, a_Level) + assert(a_Subcommands ~= nil); + + for cmd, info in pairs(a_Subcommands) do + local CmdName = a_Prefix .. cmd; + local Handler = info.Handler; + -- Provide a special handler for multicommands: + if (info.Subcommands ~= nil) then + Handler = function(a_Split, a_Player) + return MultiCommandHandler(a_Split, a_Player, CmdName, info, a_Level); + end + end + + if (Handler == nil) then + LOGWARNING(g_PluginInfo.Name .. ": Invalid handler for command " .. CmdName .. ", command will not be registered."); + else + local HelpString; + if (info.HelpString ~= nil) then + HelpString = " - " .. info.HelpString; + else + HelpString = ""; + end + cPluginManager.BindCommand(CmdName, info.Permission or "", Handler, HelpString); + -- Register all aliases for the command: + if (info.Alias ~= nil) then + if (type(info.Alias) == "string") then + info.Alias = {info.Alias}; + end + for idx, alias in ipairs(info.Alias) do + cPluginManager.BindCommand(a_Prefix .. alias, info.Permission or "", Handler, HelpString); + end + end + end + + -- Recursively register any subcommands: + if (info.Subcommands ~= nil) then + RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands, a_Level + 1); + end + end + end + + -- Loop through all commands in the plugin info, register each: + RegisterSubcommands("", g_PluginInfo.Commands, 1); +end + + + + + +--- Registers all console commands specified in the g_PluginInfo.ConsoleCommands +function RegisterPluginInfoConsoleCommands() + -- A sub-function that registers all subcommands of a single command, using the command's Subcommands table + -- The a_Prefix param already contains the space after the previous command + local function RegisterSubcommands(a_Prefix, a_Subcommands) + assert(a_Subcommands ~= nil); + + for cmd, info in pairs(a_Subcommands) do + local CmdName = a_Prefix .. cmd; + cPluginManager.BindConsoleCommand(cmd, info.Handler, info.HelpString or ""); + -- Recursively register any subcommands: + if (info.Subcommands ~= nil) then + RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands); + end + end + end + + -- Loop through all commands in the plugin info, register each: + RegisterSubcommands("", g_PluginInfo.ConsoleCommands); +end + + + + From 464ec47eb7bf61ca1e9c2af6559ad2225038d06e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 17 Feb 2014 23:00:03 +0000 Subject: [PATCH 083/106] Implemented item frames, a part of #689 + Implemented Item Frames * Fixed Pitch and Yaw being wrongly flipped in the protocol (XOFT!) --- src/Entities/Entity.h | 2 + src/Entities/ItemFrame.cpp | 109 ++++++++++++++++++++++++ src/Entities/ItemFrame.h | 42 +++++++++ src/Items/ItemHandler.cpp | 3 + src/Items/ItemItemFrame.h | 62 ++++++++++++++ src/Protocol/Protocol17x.cpp | 16 +++- src/WorldStorage/NBTChunkSerializer.cpp | 1 + 7 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 src/Entities/ItemFrame.cpp create mode 100644 src/Entities/ItemFrame.h create mode 100644 src/Items/ItemItemFrame.h diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index b2edfc2b4..79150ee51 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -81,6 +81,7 @@ public: etProjectile, etExpOrb, etFloater, + etItemFrame, // Common variations etMob = etMonster, // DEPRECATED, use etMonster instead! @@ -139,6 +140,7 @@ public: bool IsProjectile (void) const { return (m_EntityType == etProjectile); } bool IsExpOrb (void) const { return (m_EntityType == etExpOrb); } bool IsFloater (void) const { return (m_EntityType == etFloater); } + bool IsItemFrame (void) const { return (m_EntityType == etItemFrame); } /// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true) virtual bool IsA(const char * a_ClassName) const; diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp new file mode 100644 index 000000000..e4e50bd8d --- /dev/null +++ b/src/Entities/ItemFrame.cpp @@ -0,0 +1,109 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "ItemFrame.h" +#include "ClientHandle.h" +#include "Player.h" + + + + + +cItemFrame::cItemFrame(int a_BlockFace, double a_X, double a_Y, double a_Z) + : cEntity(etItemFrame, a_X, a_Y, a_Z, 0.8, 0.8), + m_BlockFace(a_BlockFace), + m_Item(E_BLOCK_AIR), + m_Rotation(0) +{ + SetMaxHealth(1); + SetHealth(1); + + if ((a_BlockFace == 0) || (a_BlockFace == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180 + { + SetYaw((a_BlockFace * 90) - 180); + } + else + { + SetYaw(a_BlockFace * 90); + } +} + + + + + +void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle) +{ + a_ClientHandle.SendSpawnObject(*this, 71, m_BlockFace, (Byte)GetYaw(), (Byte)GetPitch()); +} + + + + + +void cItemFrame::OnRightClicked(cPlayer & a_Player) +{ + if (!m_Item.IsEmpty()) + { + // Item not empty, rotate, clipping values to zero to three inclusive + m_Rotation++; + if (m_Rotation >= 4) + m_Rotation = 0; + } + else if (!a_Player.GetEquippedItem().IsEmpty()) + { + // Item empty, and player held item not empty - add this item to self + m_Item = a_Player.GetEquippedItem(); + m_Item.m_ItemCount = 1; + + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + } + + GetWorld()->BroadcastEntityMetadata(*this); // Update clients +} + + + + + + +void cItemFrame::KilledBy(cEntity * a_Killer) +{ + if (m_Item.IsEmpty()) + { + super::KilledBy(a_Killer); + Destroy(); + return; + } + + if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) + { + cItems Item; + Item.push_back(m_Item); + + GetWorld()->SpawnItemPickups(Item, GetPosX(), GetPosY(), GetPosZ()); + } + + SetHealth(GetMaxHealth()); + m_Item.Clear(); + GetWorld()->BroadcastEntityMetadata(*this); +} + + + + + +void cItemFrame::GetDrops(cItems & a_Items, cEntity * a_Killer) +{ + if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) + { + a_Items.push_back(cItem(E_ITEM_ITEM_FRAME)); + } +} + + + + diff --git a/src/Entities/ItemFrame.h b/src/Entities/ItemFrame.h new file mode 100644 index 000000000..15a03e54a --- /dev/null +++ b/src/Entities/ItemFrame.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "Entity.h" + + + + + +// tolua_begin +class cItemFrame : + public cEntity +{ + // tolua_end + typedef cEntity super; + +public: + + CLASS_PROTODEF(cItemFrame); + + cItemFrame(int a_BlockFace, double a_X, double a_Y, double a_Z); + + const cItem & GetItem(void) { return m_Item; } + Byte GetRotation(void) const { return m_Rotation; } + +private: + + virtual void SpawnOn(cClientHandle & a_ClientHandle) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override {}; + virtual void KilledBy(cEntity * a_Killer) override; + virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; + + int m_BlockFace; + cItem m_Item; + Byte m_Rotation; + +}; // tolua_export + + + + diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 19913ab24..da1cd768d 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -21,6 +21,7 @@ #include "ItemFishingRod.h" #include "ItemFlowerPot.h" #include "ItemFood.h" +#include "ItemItemFrame.h" #include "ItemHoe.h" #include "ItemLeaves.h" #include "ItemLighter.h" @@ -105,6 +106,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_FISHING_ROD: return new cItemFishingRodHandler(a_ItemType); case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType); case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType); + case E_ITEM_ITEM_FRAME: return new cItemItemFrameHandler(a_ItemType); case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType); case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType); case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType); @@ -342,6 +344,7 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_GUNPOWDER: return 64; case E_ITEM_HEAD: return 64; case E_ITEM_IRON: return 64; + case E_ITEM_ITEM_FRAME: return 64; case E_ITEM_LEATHER: return 64; case E_ITEM_MAGMA_CREAM: return 64; case E_ITEM_MAP: return 64; diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h new file mode 100644 index 000000000..39be48b54 --- /dev/null +++ b/src/Items/ItemItemFrame.h @@ -0,0 +1,62 @@ + +#pragma once + +#include "ItemHandler.h" +#include "Entities/ItemFrame.h" +#include "../Entities/Player.h" + + + + + +class cItemItemFrameHandler : + public cItemHandler +{ +public: + cItemItemFrameHandler(int a_ItemType) + : cItemHandler(a_ItemType) + { + + } + + virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override + { + if (a_Dir == BLOCK_FACE_NONE) + { + return false; + } + + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); + BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); + + if (Block == E_BLOCK_AIR) + { + int Dir = 0; + switch (a_Dir) + { + case BLOCK_FACE_SOUTH: break; + case BLOCK_FACE_NORTH: Dir = 2; break; + case BLOCK_FACE_WEST: Dir = 1; break; + case BLOCK_FACE_EAST: Dir = 3; break; + default: return false; + } + + cItemFrame * ItemFrame = new cItemFrame(Dir, a_BlockX, a_BlockY, a_BlockZ); + ItemFrame->Initialize(a_World); + + if (!a_Player->IsGameModeCreative()) + { + a_Player->GetInventory().RemoveOneEquippedItem(); + } + + return true; + + } + return false; + } +}; + + + + diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f7d13774d..57a56d1a4 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -23,6 +23,7 @@ Implements the 1.7.x protocol classes: #include "../Entities/FallingBlock.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" +#include "../Entities/ItemFrame.h" #include "../Mobs/IncludeAllMonsters.h" #include "../UI/Window.h" #include "../BlockEntities/CommandBlockEntity.h" @@ -923,8 +924,8 @@ void cProtocol172::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, 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.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteInt(a_ObjectData); if (a_ObjectData != 0) { @@ -946,8 +947,8 @@ void cProtocol172::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleTyp Pkt.WriteFPInt(a_Vehicle.GetPosX()); Pkt.WriteFPInt(a_Vehicle.GetPosY()); Pkt.WriteFPInt(a_Vehicle.GetPosZ()); - Pkt.WriteByteAngle(a_Vehicle.GetYaw()); Pkt.WriteByteAngle(a_Vehicle.GetPitch()); + Pkt.WriteByteAngle(a_Vehicle.GetYaw()); Pkt.WriteInt(a_VehicleSubType); if (a_VehicleSubType != 0) { @@ -2391,6 +2392,16 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) WriteMobMetadata((const cMonster &)a_Entity); break; } + case cEntity::etItemFrame: + { + cItemFrame & Frame = (cItemFrame &)a_Entity; + WriteByte(0xA2); + WriteItem(Frame.GetItem()); + WriteByte(0x3); + WriteByte(Frame.GetRotation()); + break; + } + default: break; } } @@ -2575,6 +2586,7 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) WriteInt(Horse.GetHorseArmour()); break; } + default: break; } // switch (a_Mob.GetType()) } diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 95b5e66d2..4f1e88b21 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -627,6 +627,7 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity) case cEntity::etProjectile: AddProjectileEntity ((cProjectileEntity *)a_Entity); break; case cEntity::etTNT: /* TODO */ break; case cEntity::etExpOrb: /* TODO */ break; + case cEntity::etItemFrame: /* TODO */ break; case cEntity::etPlayer: return; // Players aren't saved into the world default: { From 7c0d11fbb28730a328d0cb422760cb252eb8d73f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 17 Feb 2014 23:38:25 +0000 Subject: [PATCH 084/106] Used new BLOCK_FACE constants Also added more comments --- src/Items/ItemItemFrame.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h index 39be48b54..a403778ad 100644 --- a/src/Items/ItemItemFrame.h +++ b/src/Items/ItemItemFrame.h @@ -23,23 +23,24 @@ public: { if (a_Dir == BLOCK_FACE_NONE) { + // Client sends this if clicked on top or bottom face return false; } - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again if (Block == E_BLOCK_AIR) { int Dir = 0; switch (a_Dir) { - case BLOCK_FACE_SOUTH: break; - case BLOCK_FACE_NORTH: Dir = 2; break; - case BLOCK_FACE_WEST: Dir = 1; break; - case BLOCK_FACE_EAST: Dir = 3; break; - default: return false; + case BLOCK_FACE_ZP: break; // Initialised to zero + case BLOCK_FACE_ZM: Dir = 2; break; + case BLOCK_FACE_XM: Dir = 1; break; + case BLOCK_FACE_XP: Dir = 3; break; + default: ASSERT(!"Unhandled block face when trying spawn item frame!"); return false; } cItemFrame * ItemFrame = new cItemFrame(Dir, a_BlockX, a_BlockY, a_BlockZ); From fb963b6393b1af693a62315e2440dc503ec3648a Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 17 Feb 2014 19:05:11 -0500 Subject: [PATCH 085/106] Issue #673 Fix, Chunkworx now uses QueueUnloadUnusedChunks instead of UnloadUnusedChunks. --- MCServer/Plugins/ChunkWorx/chunkworx_main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua b/MCServer/Plugins/ChunkWorx/chunkworx_main.lua index f74c4ea2d..88ecb3979 100644 --- a/MCServer/Plugins/ChunkWorx/chunkworx_main.lua +++ b/MCServer/Plugins/ChunkWorx/chunkworx_main.lua @@ -122,7 +122,7 @@ function OnTick( DeltaTime ) end end WW_instance:QueueSaveAllChunks() - WW_instance:UnloadUnusedChunks() + WW_instance:QueueUnloadUnusedChunks() end end end \ No newline at end of file From 66cfd29ddca3c61047403422c42fa53682a605a0 Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 17 Feb 2014 19:12:31 -0500 Subject: [PATCH 086/106] Fixed Chunkworx, Issue 673. --- MCServer/Plugins/ChunkWorx/chunkworx_web.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua index 44993f81c..6c5eab676 100644 --- a/MCServer/Plugins/ChunkWorx/chunkworx_web.lua +++ b/MCServer/Plugins/ChunkWorx/chunkworx_web.lua @@ -44,7 +44,7 @@ function HandleRequest_Generation( Request ) if (Request.PostParams["AGHRRRR"] ~= nil) then GENERATION_STATE = 0 WW_instance:SaveAllChunks() - WW_instance:UnloadUnusedChunks() + WW_instance:QueueUnloadUnusedChunks() LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin") end --Content = Content .. "" From 320cc74f0a1a8439f8f80a1fb45a19c950f42377 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 00:16:03 +0000 Subject: [PATCH 087/106] Implemented paintings, fixes #689 + Implemented paintings --- src/BlockID.h | 2 +- src/ClientHandle.cpp | 8 +++ src/ClientHandle.h | 2 + src/Entities/Entity.h | 2 + src/Entities/Painting.cpp | 43 +++++++++++ src/Entities/Painting.h | 42 +++++++++++ src/Items/ItemHandler.cpp | 6 +- src/Items/ItemPainting.h | 95 +++++++++++++++++++++++++ src/Protocol/Protocol.h | 2 + src/Protocol/Protocol125.h | 1 + src/Protocol/Protocol17x.cpp | 15 ++++ src/Protocol/Protocol17x.h | 1 + src/Protocol/ProtocolRecognizer.cpp | 8 +++ src/Protocol/ProtocolRecognizer.h | 1 + src/WorldStorage/NBTChunkSerializer.cpp | 1 + 15 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 src/Entities/Painting.cpp create mode 100644 src/Entities/Painting.h create mode 100644 src/Items/ItemPainting.h diff --git a/src/BlockID.h b/src/BlockID.h index d5b3da672..740c5fc90 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -266,7 +266,7 @@ enum ENUM_ITEM_ID E_ITEM_FLINT = 318, E_ITEM_RAW_PORKCHOP = 319, E_ITEM_COOKED_PORKCHOP = 320, - E_ITEM_PAINTINGS = 321, + E_ITEM_PAINTING = 321, E_ITEM_GOLDEN_APPLE = 322, E_ITEM_SIGN = 323, E_ITEM_WOODEN_DOOR = 324, diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index c91a0c01b..84286fc41 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2091,6 +2091,14 @@ void cClientHandle::SendPickupSpawn(const cPickup & a_Pickup) +void cClientHandle::SendPaintingSpawn(const cPainting & a_Painting) +{ + m_Protocol->SendPaintingSpawn(a_Painting); +} + + + + void cClientHandle::SendEntityAnimation(const cEntity & a_Entity, char a_Animation) { diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 5faa94004..aefca7233 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -27,6 +27,7 @@ class cInventory; class cMonster; class cPawn; class cExpOrb; +class cPainting; class cPickup; class cPlayer; class cProtocol; @@ -111,6 +112,7 @@ public: void SendGameMode (eGameMode a_GameMode); void SendHealth (void); void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item); + void SendPaintingSpawn (const cPainting & a_Painting); void SendPickupSpawn (const cPickup & a_Pickup); void SendEntityAnimation (const cEntity & a_Entity, char a_Animation); void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount); diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index b2edfc2b4..29ffd949d 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -81,6 +81,7 @@ public: etProjectile, etExpOrb, etFloater, + etPainting, // Common variations etMob = etMonster, // DEPRECATED, use etMonster instead! @@ -139,6 +140,7 @@ public: bool IsProjectile (void) const { return (m_EntityType == etProjectile); } bool IsExpOrb (void) const { return (m_EntityType == etExpOrb); } bool IsFloater (void) const { return (m_EntityType == etFloater); } + bool IsPainting (void) const { return (m_EntityType == etPainting); } /// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true) virtual bool IsA(const char * a_ClassName) const; diff --git a/src/Entities/Painting.cpp b/src/Entities/Painting.cpp new file mode 100644 index 000000000..b98c1e67a --- /dev/null +++ b/src/Entities/Painting.cpp @@ -0,0 +1,43 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Painting.h" +#include "ClientHandle.h" +#include "Player.h" + + + + + +cPainting::cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z) + : cEntity(etPainting, a_X, a_Y, a_Z, 1, 1), + m_Name(a_Name), + m_Direction(a_Direction) +{ +} + + + + + + +void cPainting::SpawnOn(cClientHandle & a_Client) +{ + a_Client.SendPaintingSpawn(*this); +} + + + + + +void cPainting::GetDrops(cItems & a_Items, cEntity * a_Killer) +{ + if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) + { + a_Items.push_back(cItem(E_ITEM_PAINTING)); + } +} + + + + diff --git a/src/Entities/Painting.h b/src/Entities/Painting.h new file mode 100644 index 000000000..f401dac79 --- /dev/null +++ b/src/Entities/Painting.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "Entity.h" + + + + + +// tolua_begin +class cPainting : + public cEntity +{ + // tolua_end + typedef cEntity super; + +public: + CLASS_PROTODEF(cPainting); + + cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z); + const AString & GetName(void) const { return m_Name; } + int GetDirection(void) const { return m_Direction; } + +private: + + virtual void SpawnOn(cClientHandle & a_Client) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override {}; + virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; + virtual void KilledBy(cEntity * a_Killer) override + { + super::KilledBy(a_Killer); + Destroy(); + } + + AString m_Name; + int m_Direction; + +}; // tolua_export + + + + diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 19913ab24..5ff74fc2c 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -26,6 +26,7 @@ #include "ItemLighter.h" #include "ItemMinecart.h" #include "ItemNetherWart.h" +#include "ItemPainting.h" #include "ItemPickaxe.h" #include "ItemThrowable.h" #include "ItemRedstoneDust.h" @@ -106,6 +107,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType); case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType); case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType); + case E_ITEM_PAINTING: return new cItemPaintingHandler(a_ItemType); case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType); case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType); case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType); @@ -305,7 +307,7 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_BOWL: return 64; case E_ITEM_BREAD: return 64; case E_ITEM_BREWING_STAND: return 64; - case E_ITEM_BUCKET: return 1; // TODO: change this to 16 when turning compatibility to 1.3 + case E_ITEM_BUCKET: return 16; case E_ITEM_CARROT: return 64; case E_ITEM_CAULDRON: return 64; case E_ITEM_CLAY: return 64; @@ -349,7 +351,7 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_MELON_SLICE: return 64; case E_ITEM_NETHER_BRICK: return 64; case E_ITEM_NETHER_WART: return 64; - case E_ITEM_PAINTINGS: return 64; + case E_ITEM_PAINTING: return 64; case E_ITEM_PAPER: return 64; case E_ITEM_POISONOUS_POTATO: return 64; case E_ITEM_POTATO: return 64; diff --git a/src/Items/ItemPainting.h b/src/Items/ItemPainting.h new file mode 100644 index 000000000..53fc3809b --- /dev/null +++ b/src/Items/ItemPainting.h @@ -0,0 +1,95 @@ + +#pragma once + +#include "ItemHandler.h" +#include "../World.h" +#include "../Entities/Player.h" +#include "../Entities/Painting.h" + + + + + +class cItemPaintingHandler : + public cItemHandler +{ +public: + cItemPaintingHandler(int a_ItemType) + : cItemHandler(a_ItemType) + { + } + + virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override + { + if (a_Dir == BLOCK_FACE_NONE) + { + return false; + } + + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); + BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); + + if (Block == E_BLOCK_AIR) + { + int Dir = 0; + switch (a_Dir) + { + case BLOCK_FACE_SOUTH: break; + case BLOCK_FACE_NORTH: Dir = 2; break; + case BLOCK_FACE_WEST: Dir = 1; break; + case BLOCK_FACE_EAST: Dir = 3; break; + default: return false; + } + + static const struct // Define all the possible painting titles + { + AString Title; + } gPaintingTitlesList[] = + { + { "Kebab" }, + { "Aztec" }, + { "Alban" }, + { "Aztec2" }, + { "Bomb" }, + { "Plant" }, + { "Wasteland" }, + { "Wanderer" }, + { "Graham" }, + { "Pool" }, + { "Courbet" }, + { "Sunset" }, + { "Sea" }, + { "Creebet" }, + { "Match" }, + { "Bust" }, + { "Stage" }, + { "Void" }, + { "SkullAndRoses" }, + { "Wither" }, + { "Fighters" }, + { "Skeleton" }, + { "DonkeyKong" }, + { "Pointer" }, + { "Pigscene" }, + { "BurningSkull" } + }; + + cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, Dir, a_BlockX, a_BlockY, a_BlockZ); + Painting->Initialize(a_World); + + if (!a_Player->IsGameModeCreative()) + { + a_Player->GetInventory().RemoveOneEquippedItem(); + } + + return true; + + } + return false; + } +}; + + + + diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index f5b9fd403..46b627254 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -24,6 +24,7 @@ class cWindow; class cInventory; class cPawn; class cPickup; +class cPainting; class cWorld; class cMonster; class cChunkDataSerializer; @@ -81,6 +82,7 @@ public: virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) = 0; virtual void SendKeepAlive (int a_PingID) = 0; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) = 0; + virtual void SendPaintingSpawn (const cPainting & a_Painting) = 0; virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0; virtual void SendPlayerAbilities (void) = 0; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0; diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 1a3209333..54551ea5f 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -56,6 +56,7 @@ public: virtual void SendKeepAlive (int a_PingID) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override {}; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f7d13774d..7da19a14b 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -21,6 +21,7 @@ Implements the 1.7.x protocol classes: #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" #include "../Entities/FallingBlock.h" +#include "../Entities/Painting.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" #include "../Mobs/IncludeAllMonsters.h" @@ -569,6 +570,20 @@ void cProtocol172::SendLogin(const cPlayer & a_Player, const cWorld & a_World) +void cProtocol172::SendPaintingSpawn(const cPainting & a_Painting) +{ + cPacketizer Pkt(*this, 0x10); // Spawn Painting packet + Pkt.WriteVarInt(a_Painting.GetUniqueID()); + Pkt.WriteString(a_Painting.GetName().c_str()); + Pkt.WriteInt((int)a_Painting.GetPosX()); + Pkt.WriteInt((int)a_Painting.GetPosY()); + Pkt.WriteInt((int)a_Painting.GetPosZ()); + Pkt.WriteInt(a_Painting.GetDirection()); +} + + + + void cProtocol172::SendPickupSpawn(const cPickup & a_Pickup) { diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index d19be0f05..ae3577867 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -87,6 +87,7 @@ public: virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; virtual void SendKeepAlive (int a_PingID) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 6e51ee9cd..b658dc9db 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -405,6 +405,14 @@ void cProtocolRecognizer::SendParticleEffect(const AString & a_ParticleName, flo +void cProtocolRecognizer::SendPaintingSpawn(const cPainting & a_Painting) +{ + m_Protocol->SendPaintingSpawn(a_Painting); +} + + + + void cProtocolRecognizer::SendPickupSpawn(const cPickup & a_Pickup) { diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 800163be6..abbb22827 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -91,6 +91,7 @@ public: virtual void SendKeepAlive (int a_PingID) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 95b5e66d2..8419bd646 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -627,6 +627,7 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity) case cEntity::etProjectile: AddProjectileEntity ((cProjectileEntity *)a_Entity); break; case cEntity::etTNT: /* TODO */ break; case cEntity::etExpOrb: /* TODO */ break; + case cEntity::etPainting: /* TODO */ break; case cEntity::etPlayer: return; // Players aren't saved into the world default: { From ced6eb971d1705330b5a47458a986efb87a8106b Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 00:28:31 +0000 Subject: [PATCH 088/106] Comments & new BLOCK_FACE constants --- src/Items/ItemPainting.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Items/ItemPainting.h b/src/Items/ItemPainting.h index 53fc3809b..b85098221 100644 --- a/src/Items/ItemPainting.h +++ b/src/Items/ItemPainting.h @@ -23,23 +23,26 @@ public: { if (a_Dir == BLOCK_FACE_NONE) { + // Client sends this if clicked on top or bottom face return false; } - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again if (Block == E_BLOCK_AIR) { int Dir = 0; + + // The client uses different values for painting directions and block faces. Our constants are for the block faces, so we convert them here to painting faces switch (a_Dir) { - case BLOCK_FACE_SOUTH: break; - case BLOCK_FACE_NORTH: Dir = 2; break; - case BLOCK_FACE_WEST: Dir = 1; break; - case BLOCK_FACE_EAST: Dir = 3; break; - default: return false; + case BLOCK_FACE_ZP: break; // Initialised to zero + case BLOCK_FACE_ZM: Dir = 2; break; + case BLOCK_FACE_XM: Dir = 1; break; + case BLOCK_FACE_XP: Dir = 3; break; + default: ASSERT(!"Unhandled block face when trying spawn painting!"); return false; } static const struct // Define all the possible painting titles From 7a23e27fc532bdfed0038804b0060a6f7f5c0f54 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 00:29:10 +0000 Subject: [PATCH 089/106] Added an explanatory comment --- src/Items/ItemItemFrame.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h index a403778ad..f286fffd0 100644 --- a/src/Items/ItemItemFrame.h +++ b/src/Items/ItemItemFrame.h @@ -34,6 +34,8 @@ public: if (Block == E_BLOCK_AIR) { int Dir = 0; + + // The client uses different values for painting directions and block faces. Our constants are for the block faces, so we convert them here to painting faces switch (a_Dir) { case BLOCK_FACE_ZP: break; // Initialised to zero From 6788dbe7f21b3c46b1156e232041accf3d8ba200 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 11:37:45 +0000 Subject: [PATCH 090/106] Properly exported and documented paintings --- MCServer/Plugins/APIDump/APIDesc.lua | 18 ++++++++++++++++++ src/Bindings/AllToLua.pkg | 1 + src/CMakeLists.txt | 1 + src/Entities/Painting.h | 4 ++-- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index b0d31e7a8..33e98df69 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -713,6 +713,7 @@ end IsMinecart = { Params = "", Return = "bool", Notes = "Returns true if the entity represents a {{cMinecart|minecart}}" }, IsMob = { Params = "", Return = "bool", Notes = "Returns true if the entity represents any {{cMonster|mob}}." }, IsOnFire = { Params = "", Return = "bool", Notes = "Returns true if the entity is on fire" }, + IsPainting = { Params = "", Return = "bool", Notes = "Returns if this entity is a painting." }, IsPickup = { Params = "", Return = "bool", Notes = "Returns true if the entity represents a {{cPickup|pickup}}." }, IsPlayer = { Params = "", Return = "bool", Notes = "Returns true if the entity represents a {{cPlayer|player}}" }, IsProjectile = { Params = "", Return = "bool", Notes = "Returns true if the entity is a {{cProjectileEntity}} descendant." }, @@ -779,6 +780,7 @@ end etPickup = { Notes = "The entity is a {{cPickup}}" }, etProjectile = { Notes = "The entity is a {{cProjectileEntity}} descendant" }, etTNT = { Notes = "The entity is a {{cTNTEntity}}" }, + etPainting = { Notes = "The entity is a {{cPainting}}" }, }, ConstantGroups = { @@ -1109,6 +1111,9 @@ These ItemGrids are available in the API and can be manipulated by the plugins, IsFullStack = { Params = "", Return = "bool", Notes = "Returns true if the item is stacked up to its maximum stacking" }, IsSameType = { Params = "cItem", Return = "bool", Notes = "Returns true if the item in the parameter is of the same ItemType as the one stored in the object. This is true even if the two items have different enchantments" }, IsStackableWith = { Params = "cItem", Return = "bool", Notes = "Returns true if the item in the parameter is stackable with the one stored in the object. Two items with different enchantments cannot be stacked" }, + IsBothNameAndLoreEmpty = { Params = "", Return = "bool", Notes = "Returns if both the custom name and lore are not set." }, + IsCustomNameEmpty = { Params = "", Return = "bool", Notes = "Returns if the custom name of the cItem is empty." }, + IsLoreEmpty = { Params = "", Return = "", Notes = "Returns if the lore of the cItem is empty." }, }, Variables = { @@ -1116,6 +1121,8 @@ These ItemGrids are available in the API and can be manipulated by the plugins, m_ItemCount = { Type = "number", Notes = "Number of items in this stack" }, m_ItemDamage = { Type = "number", Notes = "The damage of the item. Zero means no damage. Maximum damage can be queried with GetMaxDamage()" }, m_ItemType = { Type = "number", Notes = "The item type. One of E_ITEM_ or E_BLOCK_ constants" }, + m_CustomName = { Type = "string", Notes = "The custom name for an item." }, + m_Lore = { Type = "string", Notes = "The lore for an item. Line breaks are represented by the ` character." }, }, AdditionalInfo = { @@ -1160,6 +1167,17 @@ local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3"); }, }, -- cItem + cPainting = + { + Desc = "This class represents a painting in the world. These paintings are special and different from Vanilla in that they can be critical-hit.", + Functions = + { + GetDirection = { Params = "", Return = "number", Notes = "Returns the direction the painting faces. Directions: ZP - 0, ZM - 2, XM - 1, XP - 3. Note that these are not the BLOCK_FACE constants." }, + GetName = { Params = "", Return = "string", Notes = "Returns the name of the painting" }, + }, + + }, -- cPainting + cItemGrid = { Desc = [[This class represents a 2D array of items. It is used as the underlying storage and API for all cases that use a grid of items: diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg index 6c295102f..1f08c66dc 100644 --- a/src/Bindings/AllToLua.pkg +++ b/src/Bindings/AllToLua.pkg @@ -34,6 +34,7 @@ $cfile "../Entities/Entity.h" $cfile "../Entities/Floater.h" $cfile "../Entities/Pawn.h" $cfile "../Entities/Player.h" +$cfile "../Entities/Painting.h" $cfile "../Entities/Pickup.h" $cfile "../Entities/ProjectileEntity.h" $cfile "../Entities/TNTEntity.h" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ba952f92..16bdad14e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,6 +52,7 @@ if (NOT MSVC) Entities/Entity.h Entities/Floater.h Entities/Pawn.h + Entities/Painting.h Entities/Pickup.h Entities/Player.h Entities/ProjectileEntity.h diff --git a/src/Entities/Painting.h b/src/Entities/Painting.h index f401dac79..95afbed1e 100644 --- a/src/Entities/Painting.h +++ b/src/Entities/Painting.h @@ -18,8 +18,8 @@ public: CLASS_PROTODEF(cPainting); cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z); - const AString & GetName(void) const { return m_Name; } - int GetDirection(void) const { return m_Direction; } + const AString & GetName(void) const { return m_Name; } // tolua_export + int GetDirection(void) const { return m_Direction; } // tolua_export private: From d5ee899d0e3039ace71077b5fe3d7e4a5c3601ad Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 11:44:09 +0000 Subject: [PATCH 091/106] Added a brace ==== { } { __ } { | | } ==== REMOVE ALL THE BRACES!! --- src/Entities/ItemFrame.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp index e4e50bd8d..65b0edb25 100644 --- a/src/Entities/ItemFrame.cpp +++ b/src/Entities/ItemFrame.cpp @@ -48,7 +48,9 @@ void cItemFrame::OnRightClicked(cPlayer & a_Player) // Item not empty, rotate, clipping values to zero to three inclusive m_Rotation++; if (m_Rotation >= 4) + { m_Rotation = 0; + } } else if (!a_Player.GetEquippedItem().IsEmpty()) { From 8ad4ab5bc103427a6ec993b48dbe211c2fc40da4 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 12:48:25 +0000 Subject: [PATCH 092/106] Updated Core --- MCServer/Plugins/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core index 5c8557d4f..3b416b07a 160000 --- a/MCServer/Plugins/Core +++ b/MCServer/Plugins/Core @@ -1 +1 @@ -Subproject commit 5c8557d4fdfa580c100510cde07a1a778ea2e244 +Subproject commit 3b416b07a339b3abcbc127070d56eea05b05373d From fc8743df9671172158d9d491843b8e208d3e25f3 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 08:25:29 +0100 Subject: [PATCH 093/106] Added a bit more documentation to cForEachChunkProvider. --- src/ForEachChunkProvider.h | 27 ++++++++++++++++++++++++++- src/World.h | 11 +++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/ForEachChunkProvider.h b/src/ForEachChunkProvider.h index 70cd2196a..6017173ee 100644 --- a/src/ForEachChunkProvider.h +++ b/src/ForEachChunkProvider.h @@ -1,14 +1,39 @@ +// ForEachChunkProvider.h + +// Declares the cForEachChunkProvider class which acts as an interface for classes that provide a ForEachChunkInRect() function +// Primarily serves as a decoupling between cBlockArea and cWorld + + + + + #pragma once -class cChunkDataCallback; + + +// fwd: +class cChunkDataCallback; class cBlockArea; + + + + class cForEachChunkProvider { public: + /** Calls the callback for each chunk in the specified range. */ virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) = 0; + /** Writes the block area into the specified coords. + Returns true if all chunks have been processed. + a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together. + */ virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) = 0; }; + + + + diff --git a/src/World.h b/src/World.h index 97358b88a..f885040ba 100644 --- a/src/World.h +++ b/src/World.h @@ -64,7 +64,10 @@ typedef cItemCallback cCommandBlockCallback; // tolua_begin -class cWorld : public cForEachChunkProvider, public cWorldInterface, public cBroadcastInterface +class cWorld : + public cForEachChunkProvider, + public cWorldInterface, + public cBroadcastInterface { public: @@ -401,15 +404,15 @@ public: Prefer cBlockArea::Write() instead, this is the internal implementation; cBlockArea does error checking, too. a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together. */ - virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); + virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override; // tolua_begin /** Spawns item pickups for each item in the list. May compress pickups if too many entities: */ - virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false); + virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false); // override; cannot specify it here due to tolua /** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified: */ - virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false); + virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false); // override; cannot specify it here due to tolua /** Spawns an falling block entity at the given position. It returns the UniqueID of the spawned falling block. */ int SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta); From 803ea412361ee2f4b1d74a811ddbee05f50c9345 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 13:06:18 +0100 Subject: [PATCH 094/106] Added cWorld:SetAreaBiome() API function. Fixes #675. --- src/Chunk.cpp | 32 +++++++++++++++++++++++++ src/Chunk.h | 8 +++++++ src/ChunkMap.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++-- src/ChunkMap.h | 9 +++++++ src/World.cpp | 37 +++++++++++++++++++++++++++++ src/World.h | 20 +++++++++++++++- 6 files changed, 164 insertions(+), 3 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 3028d24d0..0587beb9c 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1652,6 +1652,38 @@ void cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) +void cChunk::SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome) +{ + cChunkDef::SetBiome(m_BiomeMap, a_RelX, a_RelZ, a_Biome); + MarkDirty(); +} + + + + + +void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome) +{ + for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) + { + for (int x = a_MinRelX; x <= a_MaxRelX; x++) + { + cChunkDef::SetBiome(m_BiomeMap, x, z, a_Biome); + } + } + MarkDirty(); + + // Re-send the chunk to all clients: + for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) + { + m_World->ForceSendChunkTo(m_PosX, m_PosZ, (*itr)); + } // for itr - m_LoadedByClient[] +} + + + + + void cChunk::CollectPickupsByPlayer(cPlayer * a_Player) { double PosX = a_Player->GetPosX(); diff --git a/src/Chunk.h b/src/Chunk.h index 696690068..682ec6170 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -175,6 +175,14 @@ public: EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); } + /** Sets the biome at the specified relative coords. + Doesn't resend the chunk to clients. */ + void SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome); + + /** Sets the biome in the specified relative coords area. All the coords are inclusive. + Sends the chunk to all relevant clients. */ + void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome); + void CollectPickupsByPlayer(cPlayer * a_Player); /** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */ diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 0c5a8d9b9..01195e8bc 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1390,10 +1390,10 @@ void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks) EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ) { int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ; - cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ ); + cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ); cCSLock Lock(m_CSLayers); - cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ ); + cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ); if ((Chunk != NULL) && Chunk->IsValid()) { return Chunk->GetBiomeAt(X, Z); @@ -1408,6 +1408,63 @@ EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ) +bool cChunkMap::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome) +{ + int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ; + cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ); + + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ); + if ((Chunk != NULL) && Chunk->IsValid()) + { + Chunk->SetBiomeAt(X, Z, a_Biome); + return true; + } + return false; +} + + + + + +bool cChunkMap::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome) +{ + // Translate coords to relative: + int Y = 0; + int MinChunkX, MinChunkZ, MinX = a_MinX, MinZ = a_MinZ; + int MaxChunkX, MaxChunkZ, MaxX = a_MaxX, MaxZ = a_MaxZ; + cChunkDef::AbsoluteToRelative(MinX, Y, MinZ, MinChunkX, MinChunkZ); + cChunkDef::AbsoluteToRelative(MaxX, Y, MaxZ, MaxChunkX, MaxChunkZ); + + // Go through all chunks, set: + bool res = true; + cCSLock Lock(m_CSLayers); + for (int x = MinChunkX; x <= MaxChunkX; x++) + { + int MinRelX = (x == MinChunkX) ? MinX : 0; + int MaxRelX = (x == MaxChunkX) ? MaxX : cChunkDef::Width - 1; + for (int z = MinChunkZ; z <= MaxChunkZ; z++) + { + int MinRelZ = (z == MinChunkZ) ? MinZ : 0; + int MaxRelZ = (z == MaxChunkZ) ? MaxZ : cChunkDef::Width - 1; + cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z); + if ((Chunk != NULL) && Chunk->IsValid()) + { + Chunk->SetAreaBiome(MinRelX, MaxRelX, MinRelZ, MaxRelZ, a_Biome); + } + else + { + res = false; + } + } // for z + } // for x + return res; +} + + + + + bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure) { bool res = true; diff --git a/src/ChunkMap.h b/src/ChunkMap.h index d713d0cf5..9f0dd087e 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -159,8 +159,17 @@ public: /** Special function used for growing trees, replaces only blocks that tree may overwrite */ void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks); + /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */ EMCSBiome GetBiomeAt (int a_BlockX, int a_BlockZ); + /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded). + Doesn't resend the chunk to clients. */ + bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome); + + /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). + (Re)sends the chunks to their relevant clients if successful. */ + bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome); + /** Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read. */ bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure); diff --git a/src/World.cpp b/src/World.cpp index d67ad36d1..c9d7f42be 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1487,6 +1487,33 @@ EMCSBiome cWorld::GetBiomeAt (int a_BlockX, int a_BlockZ) +bool cWorld::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome) +{ + return m_ChunkMap->SetBiomeAt(a_BlockX, a_BlockZ, a_Biome); +} + + + + + +bool cWorld::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome) +{ + return m_ChunkMap->SetAreaBiome(a_MinX, a_MaxX, a_MinZ, a_MaxZ, a_Biome); +} + + + + + +bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome) +{ + return SetAreaBiome(a_Area.p1.x, a_Area.p2.x, a_Area.p1.z, a_Area.p2.z, a_Biome); +} + + + + + void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_ChunkMap->SetBlock(*this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); @@ -2490,6 +2517,16 @@ void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) +void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) +{ + a_Client->AddWantedChunk(a_ChunkX, a_ChunkZ); + m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client); +} + + + + + void cWorld::RemoveClientFromChunkSender(cClientHandle * a_Client) { m_ChunkSender.RemoveClient(a_Client); diff --git a/src/World.h b/src/World.h index f885040ba..dc286598c 100644 --- a/src/World.h +++ b/src/World.h @@ -47,6 +47,7 @@ class cFurnaceEntity; class cNoteEntity; class cMobCensus; class cCompositeChat; +class cCuboid; typedef std::list< cPlayer * > cPlayerList; @@ -306,9 +307,14 @@ public: /** Removes the client from all chunks it is present in */ void RemoveClientFromChunks(cClientHandle * a_Client); - /** Sends the chunk to the client specified, if the chunk is valid. If not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid+lighted) */ + /** Sends the chunk to the client specified, if the client doesn't have the chunk yet. + If chunk not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ void SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); + /** Sends the chunk to the client specified, even if the client already has the chunk. + If the chunk's not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ + void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); + /** Removes client from ChunkSender's queue of chunks to be sent */ void RemoveClientFromChunkSender(cClientHandle * a_Client); @@ -549,6 +555,18 @@ public: /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */ EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); + + /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded). + Doesn't resend the chunk to clients, use ForceSendChunkTo() for that. */ + bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome); + + /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). + (Re)sends the chunks to their relevant clients if successful. */ + bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome); + + /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). + (Re)sends the chunks to their relevant clients if successful. */ + bool SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome); /** Returns the name of the world */ const AString & GetName(void) const { return m_WorldName; } From 71b6fd3da92f5d0956a67e9185b823b6d9e207ef Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 13:06:38 +0100 Subject: [PATCH 095/106] Debuggers: Added a test for the cWorld:SetAreaBiome() function. --- MCServer/Plugins/Debuggers/Debuggers.lua | 40 ++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index 60e84c947..66894d835 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -55,6 +55,7 @@ function Initialize(Plugin) PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()"); PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords"); PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings") + PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one"); Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers) Plugin:AddWebTab("StressTest", HandleRequest_StressTest) @@ -1218,3 +1219,42 @@ end + +function HandleSetBiome(a_Split, a_Player) + local Biome = biJungle + local Size = 20 + local SplitSize = #a_Split + if (SplitSize > 3) then + a_Player:SendMessage("Too many parameters. Usage: " .. a_Split[1] .. " ") + return true + end + + if (SplitSize >= 2) then + Biome = StringToBiome(a_Split[2]) + if (Biome == biInvalidBiome) then + a_Player:SendMessage("Unknown biome: '" .. a_Split[2] .. "'. Command ignored.") + return true + end + end + if (SplitSize >= 3) then + Size = tostring(a_Split[3]) + if (Size == nil) then + a_Player:SendMessage("Unknown size: '" .. a_Split[3] .. "'. Command ignored.") + return true + end + end + + local BlockX = math.floor(a_Player:GetPosX()) + local BlockZ = math.floor(a_Player:GetPosZ()) + a_Player:GetWorld():SetAreaBiome(BlockX - Size, BlockX + Size, BlockZ - Size, BlockZ + Size, Biome) + a_Player:SendMessage( + "Blocks {" .. (BlockX - Size) .. ", " .. (BlockZ - Size) .. + "} - {" .. (BlockX + Size) .. ", " .. (BlockZ + Size) .. + "} set to biome #" .. tostring(Biome) .. "." + ) + return true +end + + + + From b1c6b4f5843d1f466cd12dd159bc717ae46059b5 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 13:44:40 +0100 Subject: [PATCH 096/106] The cuboid for cWorld::SetAreaBiome() doesn't need sorting. --- src/World.cpp | 6 +++++- src/World.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/World.cpp b/src/World.cpp index c9d7f42be..e57675c44 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1507,7 +1507,11 @@ bool cWorld::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBi bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome) { - return SetAreaBiome(a_Area.p1.x, a_Area.p2.x, a_Area.p1.z, a_Area.p2.z, a_Biome); + return SetAreaBiome( + std::min(a_Area.p1.x, a_Area.p2.x), std::max(a_Area.p1.x, a_Area.p2.x), + std::min(a_Area.p1.z, a_Area.p2.z), std::max(a_Area.p1.z, a_Area.p2.z), + a_Biome + ); } diff --git a/src/World.h b/src/World.h index dc286598c..d79de3b87 100644 --- a/src/World.h +++ b/src/World.h @@ -565,7 +565,8 @@ public: bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome); /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). - (Re)sends the chunks to their relevant clients if successful. */ + (Re)sends the chunks to their relevant clients if successful. + The cuboid needn't be sorted. */ bool SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome); /** Returns the name of the world */ From 600861988e40e442534c89e461fdb9b7c460d5b2 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 13:45:10 +0100 Subject: [PATCH 097/106] APIDump: Documented missing cWorld functions. --- MCServer/Plugins/APIDump/APIDesc.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index b0d31e7a8..61b42a1a1 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2027,6 +2027,7 @@ end AreCommandBlocksEnabled = { Params = "", Return = "bool", Notes = "Returns whether command blocks are enabled on the (entire) server" }, BroadcastBlockAction = { Params = "BlockX, BlockY, BlockZ, ActionByte1, ActionByte2, BlockType, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Broadcasts the BlockAction packet to all clients who have the appropriate chunk loaded (except ExcludeClient). The contents of the packet are specified by the parameters for the call, the blocktype needn't match the actual block that is present in the world data at the specified location." }, BroadcastChat = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Sends the Message to all players in this world, except the optional ExcludeClient. No formatting is done by the server." }, + BroadcastChatDeath = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Gray [DEATH] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For when a player dies." }, BroadcastChatFailure = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a command that failed to run because of insufficient permissions, etc." }, BroadcastChatFatal = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a plugin that crashed, or similar." }, BroadcastChatInfo = { Params = "Message, [{{cClientHandle|ExcludeClient}}]", Return = "", Notes = "Prepends Yellow [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For informational messages, such as command usage." }, @@ -2043,6 +2044,7 @@ end DoExplosionAt = { Params = "Force, X, Y, Z, CanCauseFire, Source, SourceData", Return = "", Notes = "Creates an explosion of the specified relative force in the specified position. If CanCauseFire is set, the explosion will set blocks on fire, too. The Source parameter specifies the source of the explosion, one of the esXXX constants. The SourceData parameter is specific to each source type, usually it provides more info about the source." }, DoWithBlockEntityAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a block entity at the specified coords, calls the CallbackFunction with the {{cBlockEntity}} parameter representing the block entity. The CallbackFunction has the following signature:

    function Callback({{cBlockEntity|BlockEntity}}, [CallbackData])
    The function returns false if there is no block entity, or if there is, it returns the bool value that the callback has returned. Use {{tolua}}.cast() to cast the Callback's BlockEntity parameter to the correct {{cBlockEntity}} descendant." }, DoWithChestAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a chest at the specified coords, calls the CallbackFunction with the {{cChestEntity}} parameter representing the chest. The CallbackFunction has the following signature:
    function Callback({{cChestEntity|ChestEntity}}, [CallbackData])
    The function returns false if there is no chest, or if there is, it returns the bool value that the callback has returned." }, + DoWithCommandBlockAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a command block at the specified coords, calls the CallbackFunction with the {{cCommandBlockEntity}} parameter representing the command block. The CallbackFunction has the following signature:
    function Callback({{cCommandBlockEntity|CommandBlockEntity}}, [CallbackData])
    The function returns false if there is no command block, or if there is, it returns the bool value that the callback has returned." }, DoWithDispenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dispenser at the specified coords, calls the CallbackFunction with the {{cDispenserEntity}} parameter representing the dispenser. The CallbackFunction has the following signature:
    function Callback({{cDispenserEntity|DispenserEntity}}, [CallbackData])
    The function returns false if there is no dispenser, or if there is, it returns the bool value that the callback has returned." }, DoWithDropSpenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper or a dispenser at the specified coords, calls the CallbackFunction with the {{cDropSpenserEntity}} parameter representing the dropper or dispenser. The CallbackFunction has the following signature:
    function Callback({{cDropSpenserEntity|DropSpenserEntity}}, [CallbackData])
    Note that this can be used to access both dispensers and droppers in a similar way. The function returns false if there is neither dispenser nor dropper, or if there is, it returns the bool value that the callback has returned." }, DoWithDropperAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper at the specified coords, calls the CallbackFunction with the {{cDropperEntity}} parameter representing the dropper. The CallbackFunction has the following signature:
    function Callback({{cDropperEntity|DropperEntity}}, [CallbackData])
    The function returns false if there is no dropper, or if there is, it returns the bool value that the callback has returned." }, @@ -2088,6 +2090,7 @@ end GetMaxSugarcaneHeight = { Params = "", Return = "number", Notes = "Returns the configured maximum height to which sugarcane will grow naturally." }, GetName = { Params = "", Return = "string", Notes = "Returns the name of the world, as specified in the settings.ini file." }, GetNumChunks = { Params = "", Return = "number", Notes = "Returns the number of chunks currently loaded." }, + GetScoreBoard = { Params = "", Return = "{{cScoreBoard}}", Notes = "Returns the {{cScoreBoard|ScoreBoard}} object used by this world. " }, GetSignLines = { Params = "BlockX, BlockY, BlockZ", Return = "IsValid, [Line1, Line2, Line3, Line4]", Notes = "Returns true and the lines of a sign at the specified coords, or false if there is no sign at the coords." }, GetSpawnX = { Params = "", Return = "number", Notes = "Returns the X coord of the default spawn" }, GetSpawnY = { Params = "", Return = "number", Notes = "Returns the Y coord of the default spawn" }, @@ -2123,6 +2126,11 @@ end RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." }, ScheduleTask = { Params = "DelayTicks, TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the world's tick thread after a the specified number of ticks. This enables operations to be queued for execution in the future. The function signature is
    function({{cWorld|World}})
    All return values from the function are ignored. Note that it is unsafe to store references to MCServer objects, such as entities, across from the caller to the task handler function; store the EntityID instead." }, SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." }, + SetAreaBiome = { + { Params = "MinX, MaxX, MinZ, MaxZ, EMCSBiome", Return = "bool", Notes = "Sets the biome in the rectangular area specified. Returns true if successful, false if any of the chunks were unloaded." }, + { Params = "{{cCuboid|Cuboid}}, EMCSBiome", Return = "bool", Notes = "Sets the biome in the cuboid specified. Returns true if successful, false if any of the chunks were unloaded. The cuboid needn't be sorted." }, + }, + SetBiomeAt = { Params = "BlockX, BlockZ, EMCSBiome", Return = "bool", Notes = "Sets the biome at the specified block coords. Returns true if successful, false otherwise." }, SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." }, SetBlockMeta = { From 29269a6ef82ec71e226f60f986f039d931e367e6 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 13:51:45 +0100 Subject: [PATCH 098/106] ProtoProxy: ignoring PolarSSL build files. --- Tools/ProtoProxy/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/ProtoProxy/.gitignore b/Tools/ProtoProxy/.gitignore index 8def77d0b..158a30080 100644 --- a/Tools/ProtoProxy/.gitignore +++ b/Tools/ProtoProxy/.gitignore @@ -1,6 +1,7 @@ Debug Release Logs/ +lib/ *.log *.nbt *.sln From 52c41f886927cf62ed592ba7fec974eee6b16844 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 18 Feb 2014 21:40:02 +0100 Subject: [PATCH 099/106] Add Heads completely --- src/Bindings/ManualBindings.cpp | 2 + src/BlockEntities/BlockEntity.cpp | 2 +- src/BlockEntities/SkullEntity.cpp | 4 +- src/BlockEntities/SkullEntity.h | 2 +- src/Blocks/BlockHandler.cpp | 2 + src/Blocks/BlockSkull.h | 69 +++++++++++++++++++++++++++++++ src/Chunk.cpp | 33 +++++++++++++++ src/Chunk.h | 7 +++- src/ChunkMap.cpp | 18 ++++++++ src/ChunkMap.h | 5 +++ src/Items/ItemSkull.h | 1 + src/World.cpp | 9 ++++ src/World.h | 5 +++ src/WorldStorage/WSSAnvil.cpp | 2 +- 14 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 src/Blocks/BlockSkull.h diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 2a7631120..70f3fbcf2 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -22,6 +22,7 @@ #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/NoteEntity.h" +#include "../BlockEntities/SkullEntity.h" #include "md5/md5.h" #include "../LineBlockTracer.h" #include "../WorldStorage/SchematicFileSerializer.h" @@ -2416,6 +2417,7 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithCommandBlockAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithSkullBlockAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>); tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>); tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk); diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp index 441f54a26..f01a139d2 100644 --- a/src/BlockEntities/BlockEntity.cpp +++ b/src/BlockEntities/BlockEntity.cpp @@ -30,9 +30,9 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); + case E_BLOCK_HEAD: return new cSkullEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); - case E_BLOCK_HEAD: return new cSkullEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta, a_World); case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World); diff --git a/src/BlockEntities/SkullEntity.cpp b/src/BlockEntities/SkullEntity.cpp index 3f3bc00ed..43b97b93e 100644 --- a/src/BlockEntities/SkullEntity.cpp +++ b/src/BlockEntities/SkullEntity.cpp @@ -12,12 +12,10 @@ -cSkullEntity::cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta, cWorld * a_World) : +cSkullEntity::cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : super(E_BLOCK_HEAD, a_BlockX, a_BlockY, a_BlockZ, a_World), - //m_SkullType(static_cast(a_BlockMeta)), m_Owner("") { - } diff --git a/src/BlockEntities/SkullEntity.h b/src/BlockEntities/SkullEntity.h index 6f47c7d30..ffd84465f 100644 --- a/src/BlockEntities/SkullEntity.h +++ b/src/BlockEntities/SkullEntity.h @@ -35,7 +35,7 @@ public: // tolua_end /// Creates a new skull entity at the specified block coords. a_World may be NULL - cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta, cWorld * a_World); + cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); bool LoadFromJson( const Json::Value& a_Value ); virtual void SaveToJson(Json::Value& a_Value ) override; diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 6c9bbeb02..870de7a7d 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -34,6 +34,7 @@ #include "BlockGlass.h" #include "BlockGlowstone.h" #include "BlockGravel.h" +#include "BlockSkull.h" #include "BlockHopper.h" #include "BlockIce.h" #include "BlockLadder.h" @@ -146,6 +147,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_GRASS: return new cBlockDirtHandler (a_BlockType); case E_BLOCK_GRAVEL: return new cBlockGravelHandler (a_BlockType); case E_BLOCK_HAY_BALE: return new cBlockSidewaysHandler (a_BlockType); + case E_BLOCK_HEAD: return new cBlockSkullHandler (a_BlockType); case E_BLOCK_HOPPER: return new cBlockHopperHandler (a_BlockType); case E_BLOCK_ICE: return new cBlockIceHandler (a_BlockType); case E_BLOCK_INACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType); diff --git a/src/Blocks/BlockSkull.h b/src/Blocks/BlockSkull.h new file mode 100644 index 000000000..eea5ac922 --- /dev/null +++ b/src/Blocks/BlockSkull.h @@ -0,0 +1,69 @@ + +#pragma once + +#include "BlockEntity.h" +#include "../BlockEntities/SkullEntity.h" + + + + + +class cBlockSkullHandler : + public cBlockEntityHandler +{ +public: + cBlockSkullHandler(BLOCKTYPE a_BlockType) + : cBlockEntityHandler(a_BlockType) + { + } + + virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override + { + a_Pickups.push_back(cItem(E_ITEM_HEAD, 1, 0)); + } + + virtual void OnPlacedByPlayer( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, + int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, + int a_CursorX, int a_CursorY, int a_CursorZ, + BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta + ) override + { + class cCallback : public cSkullBlockCallback + { + cPlayer * m_Player; + NIBBLETYPE m_OldBlockMeta; + NIBBLETYPE m_NewBlockMeta; + + virtual bool Item (cSkullEntity * a_SkullEntity) + { + int Rotation = 0; + if (m_NewBlockMeta == 1) + { + Rotation = (int) floor(m_Player->GetYaw() * 16.0F / 360.0F + 0.5) & 0xF; + } + + a_SkullEntity->SetSkullType(static_cast(m_OldBlockMeta)); + a_SkullEntity->SetRotation(static_cast(Rotation)); + return false; + } + + public: + cCallback (cPlayer * a_Player, NIBBLETYPE a_OldBlockMeta, NIBBLETYPE a_NewBlockMeta) : + m_Player(a_Player), + m_OldBlockMeta(a_OldBlockMeta), + m_NewBlockMeta(a_NewBlockMeta) + {} + }; + cCallback Callback(a_Player, a_BlockMeta, static_cast(a_BlockFace)); + + a_BlockMeta = a_BlockFace; + cWorld * World = (cWorld *) &a_WorldInterface; + World->DoWithSkullBlockAt(a_BlockX, a_BlockY, a_BlockZ, Callback); + a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); + } +} ; + + + + diff --git a/src/Chunk.cpp b/src/Chunk.cpp index c66dae7b4..8b03732f3 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -19,6 +19,7 @@ #include "BlockEntities/JukeboxEntity.h" #include "BlockEntities/NoteEntity.h" #include "BlockEntities/SignEntity.h" +#include "BlockEntities/SkullEntity.h" #include "Entities/Pickup.h" #include "Item.h" #include "Noise.h" @@ -2311,6 +2312,38 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom +bool cChunk::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback) +{ + // The blockentity list is locked by the parent chunkmap's CS + for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2) + { + ++itr2; + if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ)) + { + continue; + } + if ((*itr)->GetBlockType() != E_BLOCK_HEAD) + { + // There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out + return false; + } + + // The correct block entity is here, + if (a_Callback.Item((cSkullEntity *)*itr)) + { + return false; + } + return true; + } // for itr - m_BlockEntitites[] + + // Not found: + return false; +} + + + + + bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) { // The blockentity list is locked by the parent chunkmap's CS diff --git a/src/Chunk.h b/src/Chunk.h index 696690068..27388deb4 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -31,6 +31,7 @@ class cChestEntity; class cDispenserEntity; class cFurnaceEntity; class cNoteEntity; +class cSkullEntity; class cBlockArea; class cPawn; class cPickup; @@ -47,6 +48,7 @@ typedef cItemCallback cDispenserCallback; typedef cItemCallback cFurnaceCallback; typedef cItemCallback cNoteBlockCallback; typedef cItemCallback cCommandBlockCallback; +typedef cItemCallback cSkullBlockCallback; @@ -241,7 +243,10 @@ public: bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ - bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); + bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); + + /** Calls the callback for the skull block at the specified coords; returns false if there's no skull block at those coords or callback returns true, returns true if found */ + bool DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback); /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */ bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 0c5a8d9b9..5f1674c03 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -2121,6 +2121,24 @@ bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c +bool cChunkMap::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback) +{ + int ChunkX, ChunkZ; + int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ; + cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ); + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ); + if ((Chunk == NULL) && !Chunk->IsValid()) + { + return false; + } + return Chunk->DoWithSkullBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + + bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) { int ChunkX, ChunkZ; diff --git a/src/ChunkMap.h b/src/ChunkMap.h index d713d0cf5..02c245dc9 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -25,6 +25,7 @@ class cDropSpenserEntity; class cFurnaceEntity; class cNoteEntity; class cCommandBlockEntity; +class cSkullEntity; class cPawn; class cPickup; class cChunkDataSerializer; @@ -43,6 +44,7 @@ typedef cItemCallback cDropSpenserCallback; typedef cItemCallback cFurnaceCallback; typedef cItemCallback cNoteBlockCallback; typedef cItemCallback cCommandBlockCallback; +typedef cItemCallback cSkullBlockCallback; typedef cItemCallback cChunkCallback; @@ -245,6 +247,9 @@ public: /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible + /** Calls the callback for the skull block at the specified coords; returns false if there's no skull block at those coords or callback returns true, returns true if found */ + bool DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback); // Lua-accessible + /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */ bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible diff --git a/src/Items/ItemSkull.h b/src/Items/ItemSkull.h index f511c8c4a..3648f1436 100644 --- a/src/Items/ItemSkull.h +++ b/src/Items/ItemSkull.h @@ -31,6 +31,7 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { + a_BlockType = E_BLOCK_HEAD; a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x0f); diff --git a/src/World.cpp b/src/World.cpp index d67ad36d1..14d904d72 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1165,6 +1165,15 @@ bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom +bool cWorld::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback) +{ + return m_ChunkMap->DoWithSkullBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + + bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) { return m_ChunkMap->GetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4); diff --git a/src/World.h b/src/World.h index 97358b88a..4e83833ed 100644 --- a/src/World.h +++ b/src/World.h @@ -45,6 +45,7 @@ class cChestEntity; class cDispenserEntity; class cFurnaceEntity; class cNoteEntity; +class cSkullEntity; class cMobCensus; class cCompositeChat; @@ -57,6 +58,7 @@ typedef cItemCallback cDispenserCallback; typedef cItemCallback cFurnaceCallback; typedef cItemCallback cNoteBlockCallback; typedef cItemCallback cCommandBlockCallback; +typedef cItemCallback cSkullBlockCallback; @@ -510,6 +512,9 @@ public: /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Exported in ManualBindings.cpp + /** Calls the callback for the skull block at the specified coords; returns false if there's no skull block at those coords or callback returns true, returns true if found */ + bool DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback); // Exported in ManualBindings.cpp + /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */ bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Exported in ManualBindings.cpp diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 89a236f07..58dc2e9e4 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -940,7 +940,7 @@ void cWSSAnvil::LoadSkullFromNBT(cBlockEntityList & a_BlockEntities, const cPars { return; } - std::auto_ptr Skull(new cSkullEntity(E_BLOCK_HEAD, x, y, z, m_World)); + std::auto_ptr Skull(new cSkullEntity(x, y, z, m_World)); int currentLine = a_NBT.FindChildByName(a_TagIdx, "SkullType"); if (currentLine >= 0) From 05789f9e66abd9ad211fb27fb36bb45915c6d19e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 21:33:33 +0000 Subject: [PATCH 100/106] Changed BlockFace type to eBlockFace --- src/Entities/ItemFrame.cpp | 35 ++++++++++++++++++++++++----------- src/Entities/ItemFrame.h | 4 ++-- src/Items/ItemItemFrame.h | 14 +------------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp index 65b0edb25..8cfa5e18d 100644 --- a/src/Entities/ItemFrame.cpp +++ b/src/Entities/ItemFrame.cpp @@ -9,7 +9,7 @@ -cItemFrame::cItemFrame(int a_BlockFace, double a_X, double a_Y, double a_Z) +cItemFrame::cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z) : cEntity(etItemFrame, a_X, a_Y, a_Z, 0.8, 0.8), m_BlockFace(a_BlockFace), m_Item(E_BLOCK_AIR), @@ -17,15 +17,6 @@ cItemFrame::cItemFrame(int a_BlockFace, double a_X, double a_Y, double a_Z) { SetMaxHealth(1); SetHealth(1); - - if ((a_BlockFace == 0) || (a_BlockFace == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180 - { - SetYaw((a_BlockFace * 90) - 180); - } - else - { - SetYaw(a_BlockFace * 90); - } } @@ -34,7 +25,28 @@ cItemFrame::cItemFrame(int a_BlockFace, double a_X, double a_Y, double a_Z) void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle) { - a_ClientHandle.SendSpawnObject(*this, 71, m_BlockFace, (Byte)GetYaw(), (Byte)GetPitch()); + int Dir = 0; + + // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces + switch (m_BlockFace) + { + case BLOCK_FACE_ZP: break; // Initialised to zero + case BLOCK_FACE_ZM: Dir = 2; break; + case BLOCK_FACE_XM: Dir = 1; break; + case BLOCK_FACE_XP: Dir = 3; break; + default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return; + } + + if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180 + { + SetYaw((Dir * 90) - 180); + } + else + { + SetYaw(Dir * 90); + } + + a_ClientHandle.SendSpawnObject(*this, 71, Dir, (Byte)GetYaw(), (Byte)GetPitch()); } @@ -91,6 +103,7 @@ void cItemFrame::KilledBy(cEntity * a_Killer) SetHealth(GetMaxHealth()); m_Item.Clear(); + m_Rotation = 0; GetWorld()->BroadcastEntityMetadata(*this); } diff --git a/src/Entities/ItemFrame.h b/src/Entities/ItemFrame.h index 15a03e54a..43915e3f9 100644 --- a/src/Entities/ItemFrame.h +++ b/src/Entities/ItemFrame.h @@ -18,7 +18,7 @@ public: CLASS_PROTODEF(cItemFrame); - cItemFrame(int a_BlockFace, double a_X, double a_Y, double a_Z); + cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z); const cItem & GetItem(void) { return m_Item; } Byte GetRotation(void) const { return m_Rotation; } @@ -31,7 +31,7 @@ private: virtual void KilledBy(cEntity * a_Killer) override; virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; - int m_BlockFace; + eBlockFace m_BlockFace; cItem m_Item; Byte m_Rotation; diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h index f286fffd0..4875e09dc 100644 --- a/src/Items/ItemItemFrame.h +++ b/src/Items/ItemItemFrame.h @@ -33,19 +33,7 @@ public: if (Block == E_BLOCK_AIR) { - int Dir = 0; - - // The client uses different values for painting directions and block faces. Our constants are for the block faces, so we convert them here to painting faces - switch (a_Dir) - { - case BLOCK_FACE_ZP: break; // Initialised to zero - case BLOCK_FACE_ZM: Dir = 2; break; - case BLOCK_FACE_XM: Dir = 1; break; - case BLOCK_FACE_XP: Dir = 3; break; - default: ASSERT(!"Unhandled block face when trying spawn item frame!"); return false; - } - - cItemFrame * ItemFrame = new cItemFrame(Dir, a_BlockX, a_BlockY, a_BlockZ); + cItemFrame * ItemFrame = new cItemFrame(a_Dir, a_BlockX, a_BlockY, a_BlockZ); ItemFrame->Initialize(a_World); if (!a_Player->IsGameModeCreative()) From 5b961453d12d78a8901910d2f419093b82feb533 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 21:54:53 +0000 Subject: [PATCH 101/106] Fixed possible ASSERT failure --- src/Items/ItemItemFrame.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h index 4875e09dc..74e987445 100644 --- a/src/Items/ItemItemFrame.h +++ b/src/Items/ItemItemFrame.h @@ -21,7 +21,7 @@ public: virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override { - if (a_Dir == BLOCK_FACE_NONE) + if ((a_Dir == BLOCK_FACE_NONE) || (a_Dir == BLOCK_FACE_YP) || (a_Dir == BLOCK_FACE_YM)) { // Client sends this if clicked on top or bottom face return false; From 8b2153ba97cfb5ec545ff84b1329a200b7cbc2a0 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 22:07:21 +0000 Subject: [PATCH 102/106] De-breaked stuff --- src/Protocol/Protocol17x.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 57a56d1a4..3d6a8f807 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2401,7 +2401,6 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) WriteByte(Frame.GetRotation()); break; } - default: break; } } @@ -2586,7 +2585,6 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) WriteInt(Horse.GetHorseArmour()); break; } - default: break; } // switch (a_Mob.GetType()) } From 823ee3a125d1b57880eaa050d25e5bc71180506d Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 19 Feb 2014 14:12:34 +0100 Subject: [PATCH 103/106] Add break to Protocol17x.cpp and use new comment delimiter --- src/BlockEntities/SkullEntity.h | 14 +++++++------- src/Protocol/Protocol17x.cpp | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/BlockEntities/SkullEntity.h b/src/BlockEntities/SkullEntity.h index ffd84465f..3dc355623 100644 --- a/src/BlockEntities/SkullEntity.h +++ b/src/BlockEntities/SkullEntity.h @@ -34,7 +34,7 @@ public: // tolua_end - /// Creates a new skull entity at the specified block coords. a_World may be NULL + /** Creates a new skull entity at the specified block coords. a_World may be NULL */ cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); bool LoadFromJson( const Json::Value& a_Value ); @@ -42,22 +42,22 @@ public: // tolua_begin - /// Set the Skull Type + /** Set the Skull Type */ void SetSkullType(const eSkullType & a_SkullType); - /// Set the Rotation + /** Set the Rotation */ void SetRotation(eSkullRotation a_Rotation); - // Set the Player Name for Player Skulls + /** Set the Player Name for Player Skull */ void SetOwner(const AString & a_Owner); - /// Get the Skull Type + /** Get the Skull Type */ eSkullType GetSkullType(void) const { return m_SkullType; } - /// Get the Rotation + /** Get the Rotation */ eSkullRotation GetRotation(void) const { return m_Rotation; } - /// Get the setted Player Name + /** Get the setted Player Name */ AString GetOwner(void) const { return m_Owner; } // tolua_end diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 4d55822fb..07b23e0ac 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2282,6 +2282,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt Writer.AddByte("Rot", SkullEntity.GetRotation() & 0xFF); Writer.AddString("ExtraType", SkullEntity.GetOwner().c_str()); Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + break; } default: break; } From d63ce62f3bbe4b8e89b8c54af4b71d77bcc7e052 Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 19 Feb 2014 14:45:09 +0100 Subject: [PATCH 104/106] Rename SkullEntity to MobHeadEntity --- src/Bindings/ManualBindings.cpp | 4 +- src/BlockEntities/BlockEntity.cpp | 4 +- src/BlockEntities/MobHeadEntity.cpp | 108 ++++++++++++++++++++ src/BlockEntities/MobHeadEntity.h | 79 ++++++++++++++ src/BlockEntities/SkullEntity.cpp | 108 -------------------- src/BlockEntities/SkullEntity.h | 79 -------------- src/Blocks/BlockHandler.cpp | 4 +- src/Blocks/{BlockSkull.h => BlockMobHead.h} | 16 +-- src/CMakeLists.txt | 2 +- src/Chunk.cpp | 6 +- src/Chunk.h | 8 +- src/ChunkMap.cpp | 4 +- src/ChunkMap.h | 8 +- src/Defines.h | 4 +- src/Items/ItemHandler.cpp | 4 +- src/Items/{ItemSkull.h => ItemMobHead.h} | 6 +- src/Protocol/Protocol17x.cpp | 18 ++-- src/World.cpp | 4 +- src/World.h | 8 +- src/WorldStorage/NBTChunkSerializer.cpp | 14 +-- src/WorldStorage/NBTChunkSerializer.h | 4 +- src/WorldStorage/WSSAnvil.cpp | 16 +-- src/WorldStorage/WSSAnvil.h | 2 +- 23 files changed, 254 insertions(+), 256 deletions(-) create mode 100644 src/BlockEntities/MobHeadEntity.cpp create mode 100644 src/BlockEntities/MobHeadEntity.h delete mode 100644 src/BlockEntities/SkullEntity.cpp delete mode 100644 src/BlockEntities/SkullEntity.h rename src/Blocks/{BlockSkull.h => BlockMobHead.h} (74%) rename src/Items/{ItemSkull.h => ItemMobHead.h} (89%) diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 70f3fbcf2..41b4cc0f4 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -22,7 +22,7 @@ #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/NoteEntity.h" -#include "../BlockEntities/SkullEntity.h" +#include "../BlockEntities/MobHeadEntity.h" #include "md5/md5.h" #include "../LineBlockTracer.h" #include "../WorldStorage/SchematicFileSerializer.h" @@ -2417,7 +2417,7 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithCommandBlockAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithSkullBlockAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithMobHeadBlockAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>); tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>); tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk); diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp index f01a139d2..57ad83de9 100644 --- a/src/BlockEntities/BlockEntity.cpp +++ b/src/BlockEntities/BlockEntity.cpp @@ -15,7 +15,7 @@ #include "JukeboxEntity.h" #include "NoteEntity.h" #include "SignEntity.h" -#include "SkullEntity.h" +#include "MobHeadEntity.h" @@ -30,7 +30,7 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); - case E_BLOCK_HEAD: return new cSkullEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); + case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); diff --git a/src/BlockEntities/MobHeadEntity.cpp b/src/BlockEntities/MobHeadEntity.cpp new file mode 100644 index 000000000..c0a1781f6 --- /dev/null +++ b/src/BlockEntities/MobHeadEntity.cpp @@ -0,0 +1,108 @@ + +// MobHeadEntity.cpp + +// Implements the cMobHeadEntity class representing a single skull/head in the world + +#include "Globals.h" +#include "json/json.h" +#include "MobHeadEntity.h" +#include "../Entities/Player.h" + + + + + +cMobHeadEntity::cMobHeadEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : + super(E_BLOCK_HEAD, a_BlockX, a_BlockY, a_BlockZ, a_World), + m_Owner("") +{ +} + + + + + +void cMobHeadEntity::UsedBy(cPlayer * a_Player) +{ + UNUSED(a_Player); +} + + + + + +void cMobHeadEntity::SetType(const eMobHeadType & a_Type) +{ + if ((!m_Owner.empty()) && (a_Type != SKULL_TYPE_PLAYER)) + { + m_Owner = ""; + } + m_Type = a_Type; +} + + + + + +void cMobHeadEntity::SetRotation(eMobHeadRotation a_Rotation) +{ + m_Rotation = a_Rotation; +} + + + + + +void cMobHeadEntity::SetOwner(const AString & a_Owner) +{ + if ((a_Owner.length() > 16) || (m_Type != SKULL_TYPE_PLAYER)) + { + return; + } + m_Owner = a_Owner; +} + + + + + +void cMobHeadEntity::SendTo(cClientHandle & a_Client) +{ + a_Client.SendUpdateBlockEntity(*this); +} + + + + + +bool cMobHeadEntity::LoadFromJson(const Json::Value & a_Value) +{ + m_PosX = a_Value.get("x", 0).asInt(); + m_PosY = a_Value.get("y", 0).asInt(); + m_PosZ = a_Value.get("z", 0).asInt(); + + m_Type = static_cast(a_Value.get("Type", 0).asInt()); + m_Rotation = static_cast(a_Value.get("Rotation", 0).asInt()); + m_Owner = a_Value.get("Owner", "").asString(); + + return true; +} + + + + + +void cMobHeadEntity::SaveToJson(Json::Value & a_Value) +{ + a_Value["x"] = m_PosX; + a_Value["y"] = m_PosY; + a_Value["z"] = m_PosZ; + + a_Value["Type"] = m_Type; + a_Value["Rotation"] = m_Rotation; + a_Value["Owner"] = m_Owner; +} + + + + diff --git a/src/BlockEntities/MobHeadEntity.h b/src/BlockEntities/MobHeadEntity.h new file mode 100644 index 000000000..367eb15e7 --- /dev/null +++ b/src/BlockEntities/MobHeadEntity.h @@ -0,0 +1,79 @@ +// MobHeadEntity.h + +// Declares the cMobHeadEntity class representing a single skull/head in the world + + + + + +#pragma once + +#include "BlockEntity.h" + + + + + +namespace Json +{ + class Value; +} + + + + + +// tolua_begin + +class cMobHeadEntity : + public cBlockEntity +{ + typedef cBlockEntity super; + +public: + + // tolua_end + + /** Creates a new mob head entity at the specified block coords. a_World may be NULL */ + cMobHeadEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); + + bool LoadFromJson( const Json::Value& a_Value ); + virtual void SaveToJson(Json::Value& a_Value ) override; + + // tolua_begin + + /** Set the Type */ + void SetType(const eMobHeadType & a_SkullType); + + /** Set the Rotation */ + void SetRotation(eMobHeadRotation a_Rotation); + + /** Set the Player Name for Mobheads with Player type */ + void SetOwner(const AString & a_Owner); + + /** Get the Type */ + eMobHeadType GetType(void) const { return m_Type; } + + /** Get the Rotation */ + eMobHeadRotation GetRotation(void) const { return m_Rotation; } + + /** Get the setted Player Name */ + AString GetOwner(void) const { return m_Owner; } + + // tolua_end + + virtual void UsedBy(cPlayer * a_Player) override; + virtual void SendTo(cClientHandle & a_Client) override; + + static const char * GetClassStatic(void) { return "cMobHeadEntity"; } + +private: + + eMobHeadType m_Type; + eMobHeadRotation m_Rotation; + AString m_Owner; +} ; // tolua_export + + + + diff --git a/src/BlockEntities/SkullEntity.cpp b/src/BlockEntities/SkullEntity.cpp deleted file mode 100644 index 43b97b93e..000000000 --- a/src/BlockEntities/SkullEntity.cpp +++ /dev/null @@ -1,108 +0,0 @@ - -// SkullEntity.cpp - -// Implements the cSkullEntity class representing a single skull/head in the world - -#include "Globals.h" -#include "json/json.h" -#include "SkullEntity.h" -#include "../Entities/Player.h" - - - - - -cSkullEntity::cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_HEAD, a_BlockX, a_BlockY, a_BlockZ, a_World), - m_Owner("") -{ -} - - - - - -void cSkullEntity::UsedBy(cPlayer * a_Player) -{ - UNUSED(a_Player); -} - - - - - -void cSkullEntity::SetSkullType(const eSkullType & a_SkullType) -{ - if ((!m_Owner.empty()) && (a_SkullType != SKULL_TYPE_PLAYER)) - { - m_Owner = ""; - } - m_SkullType = a_SkullType; -} - - - - - -void cSkullEntity::SetRotation(eSkullRotation a_Rotation) -{ - m_Rotation = a_Rotation; -} - - - - - -void cSkullEntity::SetOwner(const AString & a_Owner) -{ - if ((a_Owner.length() > 16) || (m_SkullType != SKULL_TYPE_PLAYER)) - { - return; - } - m_Owner = a_Owner; -} - - - - - -void cSkullEntity::SendTo(cClientHandle & a_Client) -{ - a_Client.SendUpdateBlockEntity(*this); -} - - - - - -bool cSkullEntity::LoadFromJson(const Json::Value & a_Value) -{ - m_PosX = a_Value.get("x", 0).asInt(); - m_PosY = a_Value.get("y", 0).asInt(); - m_PosZ = a_Value.get("z", 0).asInt(); - - m_SkullType = static_cast(a_Value.get("SkullType", 0).asInt()); - m_Rotation = static_cast(a_Value.get("Rotation", 0).asInt()); - m_Owner = a_Value.get("Owner", "").asString(); - - return true; -} - - - - - -void cSkullEntity::SaveToJson(Json::Value & a_Value) -{ - a_Value["x"] = m_PosX; - a_Value["y"] = m_PosY; - a_Value["z"] = m_PosZ; - - a_Value["SkullType"] = m_SkullType; - a_Value["Rotation"] = m_Rotation; - a_Value["Owner"] = m_Owner; -} - - - - diff --git a/src/BlockEntities/SkullEntity.h b/src/BlockEntities/SkullEntity.h deleted file mode 100644 index 3dc355623..000000000 --- a/src/BlockEntities/SkullEntity.h +++ /dev/null @@ -1,79 +0,0 @@ -// SkullEntity.h - -// Declares the cSkullEntity class representing a single skull/head in the world - - - - - -#pragma once - -#include "BlockEntity.h" - - - - - -namespace Json -{ - class Value; -} - - - - - -// tolua_begin - -class cSkullEntity : - public cBlockEntity -{ - typedef cBlockEntity super; - -public: - - // tolua_end - - /** Creates a new skull entity at the specified block coords. a_World may be NULL */ - cSkullEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - - bool LoadFromJson( const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; - - // tolua_begin - - /** Set the Skull Type */ - void SetSkullType(const eSkullType & a_SkullType); - - /** Set the Rotation */ - void SetRotation(eSkullRotation a_Rotation); - - /** Set the Player Name for Player Skull */ - void SetOwner(const AString & a_Owner); - - /** Get the Skull Type */ - eSkullType GetSkullType(void) const { return m_SkullType; } - - /** Get the Rotation */ - eSkullRotation GetRotation(void) const { return m_Rotation; } - - /** Get the setted Player Name */ - AString GetOwner(void) const { return m_Owner; } - - // tolua_end - - virtual void UsedBy(cPlayer * a_Player) override; - virtual void SendTo(cClientHandle & a_Client) override; - - static const char * GetClassStatic(void) { return "cSkullEntity"; } - -private: - - eSkullType m_SkullType; - eSkullRotation m_Rotation; - AString m_Owner; -} ; // tolua_export - - - - diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 870de7a7d..09a1244ea 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -34,7 +34,7 @@ #include "BlockGlass.h" #include "BlockGlowstone.h" #include "BlockGravel.h" -#include "BlockSkull.h" +#include "BlockMobHead.h" #include "BlockHopper.h" #include "BlockIce.h" #include "BlockLadder.h" @@ -147,7 +147,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_GRASS: return new cBlockDirtHandler (a_BlockType); case E_BLOCK_GRAVEL: return new cBlockGravelHandler (a_BlockType); case E_BLOCK_HAY_BALE: return new cBlockSidewaysHandler (a_BlockType); - case E_BLOCK_HEAD: return new cBlockSkullHandler (a_BlockType); + case E_BLOCK_HEAD: return new cBlockMobHeadHandler (a_BlockType); case E_BLOCK_HOPPER: return new cBlockHopperHandler (a_BlockType); case E_BLOCK_ICE: return new cBlockIceHandler (a_BlockType); case E_BLOCK_INACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType); diff --git a/src/Blocks/BlockSkull.h b/src/Blocks/BlockMobHead.h similarity index 74% rename from src/Blocks/BlockSkull.h rename to src/Blocks/BlockMobHead.h index eea5ac922..6a00c3acd 100644 --- a/src/Blocks/BlockSkull.h +++ b/src/Blocks/BlockMobHead.h @@ -2,17 +2,17 @@ #pragma once #include "BlockEntity.h" -#include "../BlockEntities/SkullEntity.h" +#include "../BlockEntities/MobHeadEntity.h" -class cBlockSkullHandler : +class cBlockMobHeadHandler : public cBlockEntityHandler { public: - cBlockSkullHandler(BLOCKTYPE a_BlockType) + cBlockMobHeadHandler(BLOCKTYPE a_BlockType) : cBlockEntityHandler(a_BlockType) { } @@ -29,13 +29,13 @@ public: BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) override { - class cCallback : public cSkullBlockCallback + class cCallback : public cMobHeadBlockCallback { cPlayer * m_Player; NIBBLETYPE m_OldBlockMeta; NIBBLETYPE m_NewBlockMeta; - virtual bool Item (cSkullEntity * a_SkullEntity) + virtual bool Item (cMobHeadEntity * a_MobHeadEntity) { int Rotation = 0; if (m_NewBlockMeta == 1) @@ -43,8 +43,8 @@ public: Rotation = (int) floor(m_Player->GetYaw() * 16.0F / 360.0F + 0.5) & 0xF; } - a_SkullEntity->SetSkullType(static_cast(m_OldBlockMeta)); - a_SkullEntity->SetRotation(static_cast(Rotation)); + a_MobHeadEntity->SetType(static_cast(m_OldBlockMeta)); + a_MobHeadEntity->SetRotation(static_cast(Rotation)); return false; } @@ -59,7 +59,7 @@ public: a_BlockMeta = a_BlockFace; cWorld * World = (cWorld *) &a_WorldInterface; - World->DoWithSkullBlockAt(a_BlockX, a_BlockY, a_BlockZ, Callback); + World->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, Callback); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); } } ; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e46aa3ee5..bfece3312 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,7 +39,7 @@ if (NOT MSVC) BlockEntities/JukeboxEntity.h BlockEntities/NoteEntity.h BlockEntities/SignEntity.h - BlockEntities/SkullEntity.h + BlockEntities/MobHeadEntity.h BlockID.h BoundingBox.h ChatColor.h diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 8b03732f3..0e757be6e 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -19,7 +19,7 @@ #include "BlockEntities/JukeboxEntity.h" #include "BlockEntities/NoteEntity.h" #include "BlockEntities/SignEntity.h" -#include "BlockEntities/SkullEntity.h" +#include "BlockEntities/MobHeadEntity.h" #include "Entities/Pickup.h" #include "Item.h" #include "Noise.h" @@ -2312,7 +2312,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom -bool cChunk::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback) +bool cChunk::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback) { // The blockentity list is locked by the parent chunkmap's CS for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2) @@ -2329,7 +2329,7 @@ bool cChunk::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkull } // The correct block entity is here, - if (a_Callback.Item((cSkullEntity *)*itr)) + if (a_Callback.Item((cMobHeadEntity *)*itr)) { return false; } diff --git a/src/Chunk.h b/src/Chunk.h index 27388deb4..6bec60813 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -31,7 +31,7 @@ class cChestEntity; class cDispenserEntity; class cFurnaceEntity; class cNoteEntity; -class cSkullEntity; +class cMobHeadEntity; class cBlockArea; class cPawn; class cPickup; @@ -48,7 +48,7 @@ typedef cItemCallback cDispenserCallback; typedef cItemCallback cFurnaceCallback; typedef cItemCallback cNoteBlockCallback; typedef cItemCallback cCommandBlockCallback; -typedef cItemCallback cSkullBlockCallback; +typedef cItemCallback cMobHeadBlockCallback; @@ -245,8 +245,8 @@ public: /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); - /** Calls the callback for the skull block at the specified coords; returns false if there's no skull block at those coords or callback returns true, returns true if found */ - bool DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback); + /** Calls the callback for the mob head block at the specified coords; returns false if there's no mob header block at those coords or callback returns true, returns true if found */ + bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback); /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */ bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 5f1674c03..0d19ecd28 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -2121,7 +2121,7 @@ bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c -bool cChunkMap::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback) +bool cChunkMap::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback) { int ChunkX, ChunkZ; int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ; @@ -2132,7 +2132,7 @@ bool cChunkMap::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSk { return false; } - return Chunk->DoWithSkullBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); + return Chunk->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); } diff --git a/src/ChunkMap.h b/src/ChunkMap.h index 02c245dc9..fb587a52e 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -25,7 +25,7 @@ class cDropSpenserEntity; class cFurnaceEntity; class cNoteEntity; class cCommandBlockEntity; -class cSkullEntity; +class cMobHeadEntity; class cPawn; class cPickup; class cChunkDataSerializer; @@ -44,7 +44,7 @@ typedef cItemCallback cDropSpenserCallback; typedef cItemCallback cFurnaceCallback; typedef cItemCallback cNoteBlockCallback; typedef cItemCallback cCommandBlockCallback; -typedef cItemCallback cSkullBlockCallback; +typedef cItemCallback cMobHeadBlockCallback; typedef cItemCallback cChunkCallback; @@ -247,8 +247,8 @@ public: /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible - /** Calls the callback for the skull block at the specified coords; returns false if there's no skull block at those coords or callback returns true, returns true if found */ - bool DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback); // Lua-accessible + /** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */ + bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback); // Lua-accessible /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */ bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible diff --git a/src/Defines.h b/src/Defines.h index 7e22cbdc5..ba2866f83 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -174,7 +174,7 @@ enum eWeather -enum eSkullType +enum eMobHeadType { SKULL_TYPE_SKELETON = 0, SKULL_TYPE_WITHER = 1, @@ -187,7 +187,7 @@ enum eSkullType -enum eSkullRotation +enum eMobHeadRotation { SKULL_ROTATION_NORTH = 0, SKULL_ROTATION_NORTH_NORTH_EAST = 1, diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 4ede75cf1..3c3d98858 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -35,7 +35,7 @@ #include "ItemShears.h" #include "ItemShovel.h" #include "ItemSign.h" -#include "ItemSkull.h" +#include "ItemMobHead.h" #include "ItemSpawnEgg.h" #include "ItemSugarcane.h" #include "ItemSword.h" @@ -111,7 +111,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType); case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType); case E_ITEM_SIGN: return new cItemSignHandler(a_ItemType); - case E_ITEM_HEAD: return new cItemSkullHandler(a_ItemType); + case E_ITEM_HEAD: return new cItemMobHeadHandler(a_ItemType); case E_ITEM_SNOWBALL: return new cItemSnowballHandler(); case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType); case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType); diff --git a/src/Items/ItemSkull.h b/src/Items/ItemMobHead.h similarity index 89% rename from src/Items/ItemSkull.h rename to src/Items/ItemMobHead.h index 3648f1436..5ae040282 100644 --- a/src/Items/ItemSkull.h +++ b/src/Items/ItemMobHead.h @@ -8,11 +8,11 @@ -class cItemSkullHandler : +class cItemMobHeadHandler : public cItemHandler { public: - cItemSkullHandler(int a_ItemType) : + cItemMobHeadHandler(int a_ItemType) : cItemHandler(a_ItemType) { } @@ -31,10 +31,8 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - a_BlockType = E_BLOCK_HEAD; a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x0f); - return true; } } ; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 07b23e0ac..344dcc676 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -26,7 +26,7 @@ Implements the 1.7.x protocol classes: #include "../Mobs/IncludeAllMonsters.h" #include "../UI/Window.h" #include "../BlockEntities/CommandBlockEntity.h" -#include "../BlockEntities/SkullEntity.h" +#include "../BlockEntities/MobHeadEntity.h" #include "../CompositeChat.h" @@ -1043,7 +1043,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) { case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text - case E_BLOCK_HEAD: Action = 4; break; // Update Skull entity + case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break; } Pkt.WriteByte(Action); @@ -2273,14 +2273,14 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt } case E_BLOCK_HEAD: { - cSkullEntity & SkullEntity = (cSkullEntity &)a_BlockEntity; + cMobHeadEntity & MobHeadEntity = (cMobHeadEntity &)a_BlockEntity; - Writer.AddInt("x", SkullEntity.GetPosX()); - Writer.AddInt("y", SkullEntity.GetPosY()); - Writer.AddInt("z", SkullEntity.GetPosZ()); - Writer.AddByte("SkullType", SkullEntity.GetSkullType() & 0xFF); - Writer.AddByte("Rot", SkullEntity.GetRotation() & 0xFF); - Writer.AddString("ExtraType", SkullEntity.GetOwner().c_str()); + Writer.AddInt("x", MobHeadEntity.GetPosX()); + Writer.AddInt("y", MobHeadEntity.GetPosY()); + Writer.AddInt("z", MobHeadEntity.GetPosZ()); + Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF); + Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF); + Writer.AddString("ExtraType", MobHeadEntity.GetOwner().c_str()); Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though break; } diff --git a/src/World.cpp b/src/World.cpp index 14d904d72..c0a621a2c 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1165,9 +1165,9 @@ bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom -bool cWorld::DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback) +bool cWorld::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback) { - return m_ChunkMap->DoWithSkullBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); + return m_ChunkMap->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); } diff --git a/src/World.h b/src/World.h index 4e83833ed..9c7079a92 100644 --- a/src/World.h +++ b/src/World.h @@ -45,7 +45,7 @@ class cChestEntity; class cDispenserEntity; class cFurnaceEntity; class cNoteEntity; -class cSkullEntity; +class cMobHeadEntity; class cMobCensus; class cCompositeChat; @@ -58,7 +58,7 @@ typedef cItemCallback cDispenserCallback; typedef cItemCallback cFurnaceCallback; typedef cItemCallback cNoteBlockCallback; typedef cItemCallback cCommandBlockCallback; -typedef cItemCallback cSkullBlockCallback; +typedef cItemCallback cMobHeadBlockCallback; @@ -512,8 +512,8 @@ public: /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Exported in ManualBindings.cpp - /** Calls the callback for the skull block at the specified coords; returns false if there's no skull block at those coords or callback returns true, returns true if found */ - bool DoWithSkullBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cSkullBlockCallback & a_Callback); // Exported in ManualBindings.cpp + /** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */ + bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback); // Exported in ManualBindings.cpp /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */ bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Exported in ManualBindings.cpp diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 6da141728..cf6df114e 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -19,7 +19,7 @@ #include "../BlockEntities/JukeboxEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" -#include "../BlockEntities/SkullEntity.h" +#include "../BlockEntities/MobHeadEntity.h" #include "../Entities/Entity.h" #include "../Entities/FallingBlock.h" @@ -261,13 +261,13 @@ void cNBTChunkSerializer::AddSignEntity(cSignEntity * a_Sign) -void cNBTChunkSerializer::AddSkullEntity(cSkullEntity * a_Skull) +void cNBTChunkSerializer::AddMobHeadEntity(cMobHeadEntity * a_MobHead) { m_Writer.BeginCompound(""); - AddBasicTileEntity(a_Skull, "Skull"); - m_Writer.AddByte ("SkullType", a_Skull->GetSkullType() & 0xFF); - m_Writer.AddByte ("Rot", a_Skull->GetRotation() & 0xFF); - m_Writer.AddString("ExtraType", a_Skull->GetOwner()); + AddBasicTileEntity(a_MobHead, "Skull"); + m_Writer.AddByte ("SkullType", a_MobHead->GetType() & 0xFF); + m_Writer.AddByte ("Rot", a_MobHead->GetRotation() & 0xFF); + m_Writer.AddString("ExtraType", a_MobHead->GetOwner()); m_Writer.EndCompound(); } @@ -681,7 +681,7 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity) case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break; case E_BLOCK_SIGN_POST: case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break; - case E_BLOCK_HEAD: AddSkullEntity ((cSkullEntity *) a_Entity); break; + case E_BLOCK_HEAD: AddMobHeadEntity ((cMobHeadEntity *) a_Entity); break; case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break; case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break; case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *) a_Entity); break; diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index fd5601e47..5f9e16ed1 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -29,7 +29,7 @@ class cHopperEntity; class cJukeboxEntity; class cNoteEntity; class cSignEntity; -class cSkullEntity; +class cMobHeadEntity; class cFallingBlock; class cMinecart; class cMinecartWithChest; @@ -94,7 +94,7 @@ protected: void AddJukeboxEntity (cJukeboxEntity * a_Jukebox); void AddNoteEntity (cNoteEntity * a_Note); void AddSignEntity (cSignEntity * a_Sign); - void AddSkullEntity (cSkullEntity * a_Skull); + void AddMobHeadEntity (cMobHeadEntity * a_MobHead); void AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock); // Entities: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 58dc2e9e4..d4490c7fe 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -24,7 +24,7 @@ #include "../BlockEntities/JukeboxEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" -#include "../BlockEntities/SkullEntity.h" +#include "../BlockEntities/MobHeadEntity.h" #include "../Mobs/Monster.h" @@ -600,7 +600,7 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con } else if (strncmp(a_NBT.GetData(sID), "Skull", a_NBT.GetDataLength(sID)) == 0) { - LoadSkullFromNBT(a_BlockEntities, a_NBT, Child); + LoadMobHeadFromNBT(a_BlockEntities, a_NBT, Child); } else if (strncmp(a_NBT.GetData(sID), "Trap", a_NBT.GetDataLength(sID)) == 0) { @@ -932,7 +932,7 @@ void cWSSAnvil::LoadSignFromNBT(cBlockEntityList & a_BlockEntities, const cParse -void cWSSAnvil::LoadSkullFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx) +void cWSSAnvil::LoadMobHeadFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx) { ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound); int x, y, z; @@ -940,27 +940,27 @@ void cWSSAnvil::LoadSkullFromNBT(cBlockEntityList & a_BlockEntities, const cPars { return; } - std::auto_ptr Skull(new cSkullEntity(x, y, z, m_World)); + std::auto_ptr MobHead(new cMobHeadEntity(x, y, z, m_World)); int currentLine = a_NBT.FindChildByName(a_TagIdx, "SkullType"); if (currentLine >= 0) { - Skull->SetSkullType(static_cast(a_NBT.GetByte(currentLine))); + MobHead->SetType(static_cast(a_NBT.GetByte(currentLine))); } currentLine = a_NBT.FindChildByName(a_TagIdx, "Rot"); if (currentLine >= 0) { - Skull->SetRotation(static_cast(a_NBT.GetByte(currentLine))); + MobHead->SetRotation(static_cast(a_NBT.GetByte(currentLine))); } currentLine = a_NBT.FindChildByName(a_TagIdx, "ExtraType"); if (currentLine >= 0) { - Skull->SetOwner(a_NBT.GetString(currentLine)); + MobHead->SetOwner(a_NBT.GetString(currentLine)); } - a_BlockEntities.push_back(Skull.release()); + a_BlockEntities.push_back(MobHead.release()); } diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h index 9c9e17258..541371560 100644 --- a/src/WorldStorage/WSSAnvil.h +++ b/src/WorldStorage/WSSAnvil.h @@ -139,7 +139,7 @@ protected: void LoadJukeboxFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadNoteFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSignFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); - void LoadSkullFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); + void LoadMobHeadFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadCommandBlockFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength); From a3fa52ec739d6640f7dc4d481de77d633111cf46 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 20 Feb 2014 10:48:29 +0100 Subject: [PATCH 105/106] Fixed bindings for cBlockArea:Get(Rel)BlockTypeMeta(). They no longer require the ghost output params. --- src/Bindings/ManualBindings.cpp | 133 +++++++++++++++++++++++++------- src/BlockArea.h | 6 ++ 2 files changed, 110 insertions(+), 29 deletions(-) diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 41b4cc0f4..c220e5e0a 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -213,7 +213,7 @@ static int tolua_DoWith(lua_State* tolua_S) return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs); } - Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0); + Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, NULL); const char * ItemName = tolua_tocppstring(tolua_S, 2, ""); if ((ItemName == NULL) || (ItemName[0] == 0)) @@ -307,7 +307,7 @@ static int tolua_DoWithID(lua_State* tolua_S) return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs); } - Ty1 * self = (Ty1 *)tolua_tousertype(tolua_S, 1, 0); + Ty1 * self = (Ty1 *)tolua_tousertype(tolua_S, 1, NULL); int ItemID = (int)tolua_tonumber(tolua_S, 2, 0); if (!lua_isfunction(tolua_S, 3)) @@ -397,7 +397,7 @@ static int tolua_DoWithXYZ(lua_State* tolua_S) return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 4 or 5 arguments, got %i", NumArgs); } - Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0); + Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, NULL); if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3) || !lua_isnumber(tolua_S, 4)) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3"); @@ -491,7 +491,7 @@ static int tolua_ForEachInChunk(lua_State* tolua_S) return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 3 or 4 arguments, got %i", NumArgs); } - Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0); + Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, NULL); if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3)) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1 and #2"); @@ -585,7 +585,7 @@ static int tolua_ForEach(lua_State * tolua_S) return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 1 or 2 arguments, got %i", NumArgs); } - Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0); + Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, NULL); if (self == NULL) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance"); @@ -682,7 +682,7 @@ static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S) else #endif { - cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0); + cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, NULL); int BlockX = (int) tolua_tonumber (tolua_S, 2, 0); int BlockY = (int) tolua_tonumber (tolua_S, 3, 0); int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0); @@ -737,7 +737,7 @@ static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S) else #endif { - cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0); + cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, NULL); int BlockX = (int) tolua_tonumber (tolua_S, 2, 0); int BlockY = (int) tolua_tonumber (tolua_S, 3, 0); int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0); @@ -789,7 +789,7 @@ static int tolua_cWorld_GetSignLines(lua_State * tolua_S) else #endif { - cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0); + cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, NULL); int BlockX = (int) tolua_tonumber (tolua_S, 2, 0); int BlockY = (int) tolua_tonumber (tolua_S, 3, 0); int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0); @@ -847,7 +847,7 @@ static int tolua_cWorld_SetSignLines(lua_State * tolua_S) else #endif { - cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0); + cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, NULL); int BlockX = (int) tolua_tonumber (tolua_S, 2, 0); int BlockY = (int) tolua_tonumber (tolua_S, 3, 0); int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0); @@ -896,7 +896,7 @@ static int tolua_cWorld_TryGetHeight(lua_State * tolua_S) else #endif { - cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0); + cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, NULL); int BlockX = (int) tolua_tonumber (tolua_S, 2, 0); int BlockZ = (int) tolua_tonumber (tolua_S, 3, 0); #ifndef TOLUA_RELEASE @@ -968,7 +968,7 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S) } // Retrieve the args: - cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, 0); + cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, NULL); if (self == NULL) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance"); @@ -1066,7 +1066,7 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S) static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S) { - cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, 0); + cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, NULL); const cPluginManager::PluginMap & AllPlugins = self->GetAllPlugins(); @@ -1290,7 +1290,7 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S) return 0; } - cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, 0); + cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, NULL); if (self == NULL) { LOGWARN("Error in function call 'ForEachCommand': Not called on an object instance"); @@ -1365,7 +1365,7 @@ static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S) return 0; } - cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, 0); + cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, NULL); if (self == NULL) { LOGWARN("Error in function call 'ForEachConsoleCommand': Not called on an object instance"); @@ -1687,7 +1687,7 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S) static int tolua_cPlayer_GetGroups(lua_State* tolua_S) { - cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL); const cPlayer::GroupList & AllGroups = self->GetGroups(); @@ -1712,7 +1712,7 @@ static int tolua_cPlayer_GetGroups(lua_State* tolua_S) static int tolua_cPlayer_GetResolvedPermissions(lua_State* tolua_S) { - cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL); cPlayer::StringList AllPermissions = self->GetResolvedPermissions(); @@ -1825,7 +1825,7 @@ static int tolua_SetObjectCallback(lua_State * tolua_S) static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S) { - cPluginLua * self = (cPluginLua *)tolua_tousertype(tolua_S,1,0); + cPluginLua * self = (cPluginLua *)tolua_tousertype(tolua_S, 1, NULL); tolua_Error tolua_err; tolua_err.array = 0; @@ -1869,7 +1869,7 @@ static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S) static int tolua_cPluginLua_AddTab(lua_State* tolua_S) { - cPluginLua * self = (cPluginLua *) tolua_tousertype(tolua_S, 1, 0); + cPluginLua * self = (cPluginLua *) tolua_tousertype(tolua_S, 1, NULL); LOGWARN("WARNING: Using deprecated function AddTab()! Use AddWebTab() instead. (plugin \"%s\" in folder \"%s\")", self->GetName().c_str(), self->GetDirectory().c_str() ); @@ -1889,7 +1889,7 @@ static int tolua_cPlugin_Call(lua_State * tolua_S) L.LogStackTrace(); // Retrieve the params: plugin and the function name to call - cPluginLua * TargetPlugin = (cPluginLua *) tolua_tousertype(tolua_S, 1, 0); + cPluginLua * TargetPlugin = (cPluginLua *) tolua_tousertype(tolua_S, 1, NULL); AString FunctionName = tolua_tostring(tolua_S, 2, ""); // Call the function: @@ -1942,7 +1942,7 @@ static int tolua_push_StringStringMap(lua_State* tolua_S, std::map< std::string, static int tolua_get_HTTPRequest_Params(lua_State* tolua_S) { - HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S,1,0); + HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S, 1, NULL); return tolua_push_StringStringMap(tolua_S, self->Params); } @@ -1952,7 +1952,7 @@ static int tolua_get_HTTPRequest_Params(lua_State* tolua_S) static int tolua_get_HTTPRequest_PostParams(lua_State* tolua_S) { - HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S,1,0); + HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S, 1, NULL); return tolua_push_StringStringMap(tolua_S, self->PostParams); } @@ -1962,7 +1962,7 @@ static int tolua_get_HTTPRequest_PostParams(lua_State* tolua_S) static int tolua_get_HTTPRequest_FormData(lua_State* tolua_S) { - HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S,1,0); + HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S, 1, NULL); std::map< std::string, HTTPFormData >& FormData = self->FormData; lua_newtable(tolua_S); @@ -1985,7 +1985,7 @@ static int tolua_get_HTTPRequest_FormData(lua_State* tolua_S) static int tolua_cWebAdmin_GetPlugins(lua_State * tolua_S) { - cWebAdmin* self = (cWebAdmin*) tolua_tousertype(tolua_S,1,0); + cWebAdmin* self = (cWebAdmin*) tolua_tousertype(tolua_S, 1, NULL); const cWebAdmin::PluginList & AllPlugins = self->GetPlugins(); @@ -2010,7 +2010,7 @@ static int tolua_cWebAdmin_GetPlugins(lua_State * tolua_S) static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S) { - cWebPlugin* self = (cWebPlugin*) tolua_tousertype(tolua_S,1,0); + cWebPlugin* self = (cWebPlugin*) tolua_tousertype(tolua_S, 1, NULL); const cWebPlugin::TabNameList & TabNames = self->GetTabNames(); @@ -2077,7 +2077,7 @@ static int Lua_ItemGrid_GetSlotCoords(lua_State * L) } { - const cItemGrid * self = (const cItemGrid *)tolua_tousertype(L, 1, 0); + const cItemGrid * self = (const cItemGrid *)tolua_tousertype(L, 1, NULL); int SlotNum = (int)tolua_tonumber(L, 2, 0); if (self == NULL) { @@ -2289,7 +2289,7 @@ static int tolua_cHopperEntity_GetOutputBlockPos(lua_State * tolua_S) { return 0; } - cHopperEntity * self = (cHopperEntity *)tolua_tousertype(tolua_S, 1, 0); + cHopperEntity * self = (cHopperEntity *)tolua_tousertype(tolua_S, 1, NULL); if (self == NULL) { tolua_error(tolua_S, "invalid 'self' in function 'cHopperEntity::GetOutputBlockPos()'", NULL); @@ -2315,6 +2315,76 @@ static int tolua_cHopperEntity_GetOutputBlockPos(lua_State * tolua_S) +static int tolua_cBlockArea_GetBlockTypeMeta(lua_State * tolua_S) +{ + // function cBlockArea::GetBlockTypeMeta() + // Exported manually because tolua generates extra input params for the outputs + + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cBlockArea") || + !L.CheckParamNumber (2, 4) + ) + { + return 0; + } + + cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL); + if (self == NULL) + { + tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetRelBlockTypeMeta'", NULL); + return 0; + } + int BlockX = (int)tolua_tonumber(tolua_S, 2, 0); + int BlockY = (int)tolua_tonumber(tolua_S, 3, 0); + int BlockZ = (int)tolua_tonumber(tolua_S, 4, 0); + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + self->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta); + tolua_pushnumber(tolua_S, BlockType); + tolua_pushnumber(tolua_S, BlockMeta); + return 2; +} + + + + + +static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * tolua_S) +{ + // function cBlockArea::GetRelBlockTypeMeta() + // Exported manually because tolua generates extra input params for the outputs + + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cBlockArea") || + !L.CheckParamNumber (2, 4) + ) + { + return 0; + } + + cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL); + if (self == NULL) + { + tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetRelBlockTypeMeta'", NULL); + return 0; + } + int BlockX = (int)tolua_tonumber(tolua_S, 2, 0); + int BlockY = (int)tolua_tonumber(tolua_S, 3, 0); + int BlockZ = (int)tolua_tonumber(tolua_S, 4, 0); + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + self->GetRelBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta); + tolua_pushnumber(tolua_S, BlockType); + tolua_pushnumber(tolua_S, BlockMeta); + return 2; +} + + + + + static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S) { // function cBlockArea::LoadFromSchematicFile @@ -2328,7 +2398,7 @@ static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S) { return 0; } - cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, 0); + cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL); if (self == NULL) { tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::LoadFromSchematicFile'", NULL); @@ -2344,6 +2414,7 @@ static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S) + static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S) { // function cBlockArea::SaveToSchematicFile @@ -2357,7 +2428,7 @@ static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S) { return 0; } - cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, 0); + cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL); if (self == NULL) { tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::SaveToSchematicFile'", NULL); @@ -2371,6 +2442,8 @@ static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S) + + void ManualBindings::Bind(lua_State * tolua_S) { tolua_beginmodule(tolua_S, NULL); @@ -2387,8 +2460,10 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cBlockArea"); + tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta); + tolua_function(tolua_S, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta); tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile); - tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile); + tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cHopperEntity"); diff --git a/src/BlockArea.h b/src/BlockArea.h index 59bc0f241..b4a161f32 100644 --- a/src/BlockArea.h +++ b/src/BlockArea.h @@ -184,9 +184,15 @@ public: void SetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); void SetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); + + // tolua_end + + // These need manual exporting, tolua generates the binding as requiring 2 extra input params void GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; void GetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; + // tolua_begin + int GetSizeX(void) const { return m_SizeX; } int GetSizeY(void) const { return m_SizeY; } int GetSizeZ(void) const { return m_SizeZ; } From 7b8ff7c9868e574f53d4740046db7c686bd978fb Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 20 Feb 2014 11:05:45 +0100 Subject: [PATCH 106/106] APIDump: Fixed cBlockArea:GetRelBlockType() return types. --- MCServer/Plugins/APIDump/APIDesc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index fd4b1d947..73bb5c7fb 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -118,7 +118,7 @@ g_APIDesc = GetRelBlockMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the block meta at the specified relative coords" }, GetRelBlockSkyLight = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the skylight at the specified relative coords" }, GetRelBlockType = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "BLOCKTYPE", Notes = "Returns the block type at the specified relative coords" }, - GetRelBlockTypeMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the block type and meta at the specified relative coords" }, + GetRelBlockTypeMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "BLOCKTYPE, NIBBLETYPE", Notes = "Returns the block type and meta at the specified relative coords" }, GetSizeX = { Params = "", Return = "number", Notes = "Returns the size of the held data in the x-axis" }, GetSizeY = { Params = "", Return = "number", Notes = "Returns the size of the held data in the y-axis" }, GetSizeZ = { Params = "", Return = "number", Notes = "Returns the size of the held data in the z-axis" },