From e8e76a6058988cb0cff222579049fb6aa3cdb9c1 Mon Sep 17 00:00:00 2001 From: narroo Date: Mon, 10 Feb 2014 20:00:07 -0500 Subject: 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. --- src/World.cpp | 10 ++++++++++ src/World.h | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'src') 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); -- cgit v1.2.3 From d7f32ed682b19cded6c54f14e4e46792695399a7 Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 08:01:25 -0500 Subject: Fixed formatting of previous commit. --- src/World.cpp | 5 +++++ src/World.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') 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); -- cgit v1.2.3 From e53b331b4a17234c89f0ac54e724a5f48de4c4be Mon Sep 17 00:00:00 2001 From: narroo Date: Tue, 11 Feb 2014 14:38:28 -0500 Subject: Fixed formatting. Moved UnloadUnusedChunks from public to private. --- src/World.cpp | 7 +++++++ src/World.h | 7 +++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src') 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 */ -- cgit v1.2.3 From c53406f0d4d83f795e2a445059952b61abb12f34 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 22:04:11 +0000 Subject: Fixed #612 * Chests send contents updates to client --- src/BlockEntities/ChestEntity.cpp | 15 +++++++++++++++ src/BlockEntities/ChestEntity.h | 1 + 2 files changed, 16 insertions(+) (limited to 'src') 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); -- cgit v1.2.3 From 06239c8336a340459a62b45b6d633a55058e4677 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 22:09:56 +0000 Subject: 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(-) (limited to 'src') 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; } -- cgit v1.2.3 From 9d54f2b761370afb04ebb49e0920de460f269efd Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 22:54:01 +0000 Subject: Fixed #190 + Hoppers now collect pickups above them --- src/BlockEntities/HopperEntity.cpp | 69 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'src') 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(); } -- cgit v1.2.3 From a0a44b969ece88d32bcc89fea51b25d819424a06 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Feb 2014 23:13:49 +0000 Subject: 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(-) (limited to 'src') 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; } -- cgit v1.2.3 From 7ced2f290fc2018d93e324d384d87cfd826312a5 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 21:53:21 +0000 Subject: Simplified Attack() tracing --- src/Mobs/AggressiveMonster.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') 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); -- cgit v1.2.3 From 91ebb6cef09ff8437beaa0c17ca2a1c094741200 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 21:53:46 +0000 Subject: Made player jump reset less ambiguous --- src/Entities/Player.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') 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(); -- cgit v1.2.3 From f97ce3015171fcc6f6c5316810d19eb37c89c5f7 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 22:01:22 +0000 Subject: 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 | 53 +++++++++++++++++++++----------- src/BlockEntities/HopperEntity.h | 4 +-- src/ItemGrid.cpp | 7 +++++ 8 files changed, 54 insertions(+), 33 deletions(-) (limited to 'src') 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,25 +220,42 @@ 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())) + 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()) { - m_bFoundPickupsAbove = true; - m_Contents.ChangeSlotCount(i, ((cPickup *)a_Entity)->GetItem().m_ItemCount); - a_Entity->Destroy(); - return false; + //LOGINFO("Pickup was empty!"); + a_Pickup->Destroy(); // Kill pickup if all items were added } + return true; } } - return false; } @@ -248,7 +265,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) } 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; } -- cgit v1.2.3 From e915a0df4cf78f41a200f0a06aabf069aec1bb07 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 22:06:13 +0000 Subject: 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(-) (limited to 'src') 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: -- cgit v1.2.3 From 6ed4f476ce1365c5878c2726de331c892d00c256 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Feb 2014 22:06:59 +0000 Subject: Added more missing GetClassStatic()s --- src/BlockEntities/JukeboxEntity.h | 2 ++ src/BlockEntities/NoteEntity.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') 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 -- cgit v1.2.3 From c0e7d6fec9c8349321849b933183ef3f49ff87d2 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 13 Feb 2014 19:57:23 +0000 Subject: Fancy stuff with constant references --- src/BlockEntities/HopperEntity.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') 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; }; -- cgit v1.2.3 From f4f0099947a017085574bff681d76aa1d4d53058 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 13 Feb 2014 20:20:37 +0000 Subject: Added proper debug messages --- src/BlockEntities/HopperEntity.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') 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; -- cgit v1.2.3 From ceb16ea2f714cc1b9f52750446e3842e2b6a5820 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sat, 15 Feb 2014 11:38:20 +0100 Subject: Exported cWorld::BroadcastParticleEffect. --- src/World.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') 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); -- cgit v1.2.3 From c6a2e8c6889aca8aa422ac704b79bf7fc43856ec Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 12:58:17 +0000 Subject: Removed debug messages again --- src/BlockEntities/HopperEntity.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') 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()) { -- cgit v1.2.3 From b0fd5511eab236b69fb0805789917e91f8bb6b6e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 13:55:58 +0000 Subject: Fixed typographical error --- src/BlockEntities/SignEntity.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') 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: -- cgit v1.2.3 From 87e79de4b7d435366862c3b70ccdad559bb2e286 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 11 Feb 2014 15:01:24 +0100 Subject: Add Fence Gate to Redstone Simulator --- src/Simulator/IncrementalRedstoneSimulator.cpp | 29 ++++++++++++++++++++++++++ src/Simulator/IncrementalRedstoneSimulator.h | 2 ++ 2 files changed, 31 insertions(+) (limited to 'src') 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 */ -- cgit v1.2.3 From 70a0dcb1ebf8c79dce3a2c3bad553b9ee4606540 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 11 Feb 2014 15:08:17 +0100 Subject: Add more Sounds to Redstone Simulator --- src/Simulator/IncrementalRedstoneSimulator.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src') 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); } } -- cgit v1.2.3 From 6eeeb2aa0129ee9664b6cf21a68517bd4b9c7348 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 15:51:49 +0000 Subject: 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 ++- src/Simulator/IncrementalRedstoneSimulator.cpp | 161 ++++++++++++++----------- src/Simulator/IncrementalRedstoneSimulator.h | 35 ++++-- 3 files changed, 127 insertions(+), 83 deletions(-) (limited to 'src') 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: } } }; + + + + -- cgit v1.2.3 From 8fbb936b6326b46fb3f4b85d654288a6b2ccc240 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 15:53:02 +0000 Subject: Fixed TNT fizzing everywhere --- src/Items/ItemLighter.h | 2 +- src/Mobs/Creeper.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') 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); } -- cgit v1.2.3 From 0040a88b9b40817c04e54259fcb61e31dc4f4213 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sat, 15 Feb 2014 19:51:05 +0100 Subject: 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(+) (limited to 'src') 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 ! -- cgit v1.2.3 From c494d0f6f2645baa4fd356ef2250dbc3202f883a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 19:56:45 +0000 Subject: 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 --- src/Simulator/IncrementalRedstoneSimulator.cpp | 63 +++++++++++++++++--------- src/Simulator/IncrementalRedstoneSimulator.h | 3 +- 2 files changed, 43 insertions(+), 23 deletions(-) (limited to 'src') 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 -- cgit v1.2.3 From d273cc414241e11d56d336535501955d413cec89 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 15 Feb 2014 20:22:51 +0000 Subject: Added a 'default:' for SimChunk()'s switch --- src/Simulator/IncrementalRedstoneSimulator.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') 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; } -- cgit v1.2.3 From 0f1f7583aeea65335b2ee051585a857b1142a927 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 15 Feb 2014 23:16:44 +0100 Subject: 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 (limited to 'src') 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); -- cgit v1.2.3 From 52cd9dfe9f7cfc7c229049d98993f13b6b8ddd5d Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 15 Feb 2014 23:26:19 +0100 Subject: 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(-) (limited to 'src') 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 -- cgit v1.2.3 From d15d6acc5837b0f2aa6814b2d9c9a2e440a952e6 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 11 Feb 2014 15:34:18 +0100 Subject: Disable Hunger Death --- src/Entities/Player.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') 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); -- cgit v1.2.3 From 507a8a4b844f1c0a36bfc7063804ddca1012948d Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 14 Feb 2014 21:33:16 +0100 Subject: Set max. Players in the Tablist to 60 --- src/Protocol/Protocol17x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') 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? } -- cgit v1.2.3 From f3bd288f020a8f004179513c0e260ac0f2855767 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 14 Feb 2014 22:49:23 +0100 Subject: 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(-) (limited to 'src') 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(); -- cgit v1.2.3 From 707916b404e8ba16b8f39b43cb9e91af9d4b37b4 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 15 Feb 2014 19:52:15 +0100 Subject: 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(-) (limited to 'src') 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(); -- cgit v1.2.3 From 55a6306e2bfa1b8ddf87ee2287fe1217904ac547 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 00:45:14 +0000 Subject: 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 --- src/Simulator/IncrementalRedstoneSimulator.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'src') 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; } -- cgit v1.2.3 From 48d28a0f94ab168b7cb022107f6a62e3250043bc Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 16 Feb 2014 13:26:07 +0100 Subject: 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(-) (limited to 'src') 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 } -- cgit v1.2.3 From 4908b6f500aa31ca550536c7e5a49e660ff72b65 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 13:37:36 +0000 Subject: 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(-) (limited to 'src') 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; -- cgit v1.2.3 From 1a84102b102304945ea1e2c5ecf13075946b3a4a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 13:47:55 +0000 Subject: Slight cleanup of wolf code --- src/Mobs/Wolf.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) (limited to 'src') 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); } } } -- cgit v1.2.3 From 2350b77bb5fa2de05a619a3646662c9fc00ace28 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 16 Feb 2014 17:08:49 +0000 Subject: Fixes to previous commit --- src/Mobs/Wolf.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src') 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 { -- cgit v1.2.3 From 60bcf2807a293dcf0a6fcc604a7e36c824a02110 Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Sun, 16 Feb 2014 18:18:07 +0100 Subject: Now mobs can't escape from fences. --- src/Mobs/Monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') 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)); } -- cgit v1.2.3 From b0dbe512100dd2ce506d78065e415a648faf7f0d Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 16 Feb 2014 23:30:50 +0100 Subject: 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(-) (limited to 'src') 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 -- cgit v1.2.3 From 4a24e39ac10de4389bcbda29f51ae09f93e794ca Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 16 Feb 2014 23:31:47 +0100 Subject: Implemented cCompositeChat::ParseText(), incl. self-test. --- src/CompositeChat.cpp | 207 +++++++++++++++++++++++++++++++++++++++++++++++++- src/CompositeChat.h | 5 ++ 2 files changed, 211 insertions(+), 1 deletion(-) (limited to 'src') 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 -- cgit v1.2.3 From ea55a22a71a6fd46877bc4b6b56d6205dd20608f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 16 Feb 2014 23:51:32 +0100 Subject: 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(-) (limited to 'src') 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 */ -- cgit v1.2.3 From a4ff63f223d5a9b20e71286975d7a6d5f0c00f17 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 10:15:18 +0100 Subject: Fixed a memory leak in CompositeChat. --- src/CompositeChat.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') 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 : -- cgit v1.2.3 From 8707f7ddc812037f022e46fa7d0d6a56a9c55728 Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Mon, 17 Feb 2014 17:01:22 +0100 Subject: Improved formatting --- src/Mobs/Monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') 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)); } -- cgit v1.2.3 From 777041806fb5085e94838fa9bb0b1c3fe0b61696 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 17 Feb 2014 20:14:08 +0100 Subject: 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 (limited to 'src') 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); -- cgit v1.2.3 From 865ae82114c7c567f3d2580f648979ad5101e0db Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 23:12:46 +0100 Subject: 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(+) (limited to 'src') 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"); } -- cgit v1.2.3 From 1a26f05ed0e81cb0c2cbd17ee4eb6022f094438e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 17 Feb 2014 23:36:39 +0100 Subject: Added cPluginManager:GetPluginsPath() to the Lua API. --- src/Bindings/PluginManager.cpp | 2 +- src/Bindings/PluginManager.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') 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; -- cgit v1.2.3 From 464ec47eb7bf61ca1e9c2af6559ad2225038d06e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 17 Feb 2014 23:00:03 +0000 Subject: 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 (limited to 'src') 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: { -- cgit v1.2.3 From 7c0d11fbb28730a328d0cb422760cb252eb8d73f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 17 Feb 2014 23:38:25 +0000 Subject: Used new BLOCK_FACE constants Also added more comments --- src/Items/ItemItemFrame.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src') 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); -- cgit v1.2.3 From 320cc74f0a1a8439f8f80a1fb45a19c950f42377 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 00:16:03 +0000 Subject: 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 (limited to 'src') 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: { -- cgit v1.2.3 From ced6eb971d1705330b5a47458a986efb87a8106b Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 00:28:31 +0000 Subject: Comments & new BLOCK_FACE constants --- src/Items/ItemPainting.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') 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 -- cgit v1.2.3 From 7a23e27fc532bdfed0038804b0060a6f7f5c0f54 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 00:29:10 +0000 Subject: Added an explanatory comment --- src/Items/ItemItemFrame.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') 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 -- cgit v1.2.3 From 6788dbe7f21b3c46b1156e232041accf3d8ba200 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 11:37:45 +0000 Subject: Properly exported and documented paintings --- src/Bindings/AllToLua.pkg | 1 + src/CMakeLists.txt | 1 + src/Entities/Painting.h | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') 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: -- cgit v1.2.3 From d5ee899d0e3039ace71077b5fe3d7e4a5c3601ad Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 11:44:09 +0000 Subject: Added a brace ==== { } { __ } { | | } ==== REMOVE ALL THE BRACES!! --- src/Entities/ItemFrame.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') 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()) { -- cgit v1.2.3 From fc8743df9671172158d9d491843b8e208d3e25f3 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 08:25:29 +0100 Subject: Added a bit more documentation to cForEachChunkProvider. --- src/ForEachChunkProvider.h | 27 ++++++++++++++++++++++++++- src/World.h | 11 +++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') 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); -- cgit v1.2.3 From 803ea412361ee2f4b1d74a811ddbee05f50c9345 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 13:06:18 +0100 Subject: 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(-) (limited to 'src') 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; } -- cgit v1.2.3 From b1c6b4f5843d1f466cd12dd159bc717ae46059b5 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 18 Feb 2014 13:44:40 +0100 Subject: The cuboid for cWorld::SetAreaBiome() doesn't need sorting. --- src/World.cpp | 6 +++++- src/World.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') 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 */ -- cgit v1.2.3 From 52c41f886927cf62ed592ba7fec974eee6b16844 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 18 Feb 2014 21:40:02 +0100 Subject: 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 (limited to 'src') 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) -- cgit v1.2.3 From 05789f9e66abd9ad211fb27fb36bb45915c6d19e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 21:33:33 +0000 Subject: 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(-) (limited to 'src') 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()) -- cgit v1.2.3 From 5b961453d12d78a8901910d2f419093b82feb533 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 21:54:53 +0000 Subject: Fixed possible ASSERT failure --- src/Items/ItemItemFrame.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') 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; -- cgit v1.2.3 From 8b2153ba97cfb5ec545ff84b1329a200b7cbc2a0 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Feb 2014 22:07:21 +0000 Subject: De-breaked stuff --- src/Protocol/Protocol17x.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') 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()) } -- cgit v1.2.3 From 823ee3a125d1b57880eaa050d25e5bc71180506d Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 19 Feb 2014 14:12:34 +0100 Subject: 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(-) (limited to 'src') 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; } -- cgit v1.2.3 From d63ce62f3bbe4b8e89b8c54af4b71d77bcc7e052 Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 19 Feb 2014 14:45:09 +0100 Subject: 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/BlockMobHead.h | 69 ++++++++++++++++++++ src/Blocks/BlockSkull.h | 69 -------------------- 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/ItemMobHead.h | 42 +++++++++++++ src/Items/ItemSkull.h | 44 ------------- 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 +- 25 files changed, 355 insertions(+), 357 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 create mode 100644 src/Blocks/BlockMobHead.h delete mode 100644 src/Blocks/BlockSkull.h create mode 100644 src/Items/ItemMobHead.h delete mode 100644 src/Items/ItemSkull.h (limited to 'src') 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/BlockMobHead.h b/src/Blocks/BlockMobHead.h new file mode 100644 index 000000000..6a00c3acd --- /dev/null +++ b/src/Blocks/BlockMobHead.h @@ -0,0 +1,69 @@ + +#pragma once + +#include "BlockEntity.h" +#include "../BlockEntities/MobHeadEntity.h" + + + + + +class cBlockMobHeadHandler : + public cBlockEntityHandler +{ +public: + cBlockMobHeadHandler(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 cMobHeadBlockCallback + { + cPlayer * m_Player; + NIBBLETYPE m_OldBlockMeta; + NIBBLETYPE m_NewBlockMeta; + + virtual bool Item (cMobHeadEntity * a_MobHeadEntity) + { + int Rotation = 0; + if (m_NewBlockMeta == 1) + { + Rotation = (int) floor(m_Player->GetYaw() * 16.0F / 360.0F + 0.5) & 0xF; + } + + a_MobHeadEntity->SetType(static_cast(m_OldBlockMeta)); + a_MobHeadEntity->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->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, Callback); + a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); + } +} ; + + + + diff --git a/src/Blocks/BlockSkull.h b/src/Blocks/BlockSkull.h deleted file mode 100644 index eea5ac922..000000000 --- a/src/Blocks/BlockSkull.h +++ /dev/null @@ -1,69 +0,0 @@ - -#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/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/ItemMobHead.h b/src/Items/ItemMobHead.h new file mode 100644 index 000000000..5ae040282 --- /dev/null +++ b/src/Items/ItemMobHead.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "ItemHandler.h" +#include "../World.h" + + + + + +class cItemMobHeadHandler : + public cItemHandler +{ +public: + cItemMobHeadHandler(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/Items/ItemSkull.h b/src/Items/ItemSkull.h deleted file mode 100644 index 3648f1436..000000000 --- a/src/Items/ItemSkull.h +++ /dev/null @@ -1,44 +0,0 @@ - -#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 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); -- cgit v1.2.3 From a3fa52ec739d6640f7dc4d481de77d633111cf46 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 20 Feb 2014 10:48:29 +0100 Subject: 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(-) (limited to 'src') 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; } -- cgit v1.2.3