From 3b24bc870bb39a8b8812ed307250e1188b9ff788 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 17 Feb 2014 16:27:12 +0200 Subject: [PATCH] Map item handler; Fixed several bugs --- src/ClientHandle.cpp | 2 - src/Entities/Player.cpp | 3 ++ src/Inventory.cpp | 25 ++++++++++++ src/Inventory.h | 3 ++ src/Items/ItemEmptyMap.h | 16 +++++++- src/Items/ItemHandler.cpp | 2 + src/Items/ItemHandler.h | 8 ++++ src/Items/ItemMap.h | 43 ++++++++++++++++++++ src/Map.cpp | 63 ++++++++++++++++++++++++------ src/Map.h | 13 ++++-- src/World.cpp | 28 +++++++++---- src/WorldStorage/MapSerializer.cpp | 11 +++++- src/WorldStorage/MapSerializer.h | 7 +++- 13 files changed, 195 insertions(+), 29 deletions(-) create mode 100644 src/Items/ItemMap.h diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index ff8775771..a2cbaefff 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1199,8 +1199,6 @@ void cClientHandle::HandleSlotSelected(short a_SlotNum) if (Map != NULL) { - Map->UpdateRadius(*m_Player, 128); // Temporary - // TODO 2014-02-14 xdot: Optimization - Do not send the whole map. Map->SendTo(*this); } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 286d43cf6..fdf8d4303 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -254,6 +254,9 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) HandleFloater(); } + // Update items (e.g. Maps) + m_Inventory.UpdateItems(); + // Send Player List (Once per m_LastPlayerListTime/1000 ms) cTimer t1; if (m_LastPlayerListTime + cPlayer::PLAYER_LIST_TIME_MS <= t1.GetNowTime()) diff --git a/src/Inventory.cpp b/src/Inventory.cpp index 0e1cedc85..7f434adfd 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -515,6 +515,31 @@ bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, +void cInventory::UpdateItems(void) +{ + const cItem & Slot = GetEquippedItem(); + + if (Slot.IsEmpty()) + { + return; + } + + switch (Slot.m_ItemType) + { + case E_ITEM_MAP: + { + ItemHandler(Slot.m_ItemType)->OnUpdate(m_Owner.GetWorld(), &m_Owner, Slot); + break; + } + + default: break; + } +} + + + + + void cInventory::SaveToJson(Json::Value & a_Value) { // The JSON originally included the 4 crafting slots and the result, so we have to put empty items there, too: diff --git a/src/Inventory.h b/src/Inventory.h index 3c6a19de8..fd2089a13 100644 --- a/src/Inventory.h +++ b/src/Inventory.h @@ -150,6 +150,9 @@ public: /// Sends the slot contents to the owner void SendSlot(int a_SlotNum); + /// Update items (e.g. Maps) + void UpdateItems(void); + /// Converts an armor slot number into the ID for the EntityEquipment packet static int ArmorSlotNumToEntityEquipmentID(short a_ArmorSlotNum); diff --git a/src/Items/ItemEmptyMap.h b/src/Items/ItemEmptyMap.h index 24d31151b..b06cf9d13 100644 --- a/src/Items/ItemEmptyMap.h +++ b/src/Items/ItemEmptyMap.h @@ -41,7 +41,21 @@ public: int CenterX = round(a_Player->GetPosX() / (float) RegionWidth) * RegionWidth; int CenterZ = round(a_Player->GetPosZ() / (float) RegionWidth) * RegionWidth; - a_World->CreateMap(CenterX, CenterZ, DEFAULT_SCALE); + cMap * NewMap = a_World->CreateMap(CenterX, CenterZ, DEFAULT_SCALE); + + // Remove empty map from inventory + if (!a_Player->GetInventory().RemoveOneEquippedItem()) + { + ASSERT(!"Inventory mismatch"); + return true; + } + + if (NewMap == NULL) + { + return true; + } + + a_Player->GetInventory().AddItem(cItem(E_ITEM_MAP, 1, NewMap->GetID()), true, true); return true; } diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 755766d64..cab8dec97 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -25,6 +25,7 @@ #include "ItemHoe.h" #include "ItemLeaves.h" #include "ItemLighter.h" +#include "ItemMap.h" #include "ItemMinecart.h" #include "ItemNetherWart.h" #include "ItemPickaxe.h" @@ -107,6 +108,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_MAP: return new cItemMapHandler(); 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); diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h index 1a6bb044f..ef3f37a7a 100644 --- a/src/Items/ItemHandler.h +++ b/src/Items/ItemHandler.h @@ -32,6 +32,14 @@ public: UNUSED(a_BlockZ); UNUSED(a_BlockFace); } + + /// Called every tick while the item is on the player's inventory (Used by maps) - For now, called only for equipped items + virtual void OnUpdate(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item) + { + UNUSED(a_World); + UNUSED(a_Player); + UNUSED(a_Item); + } /// Called while the player diggs a block using this item virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace); diff --git a/src/Items/ItemMap.h b/src/Items/ItemMap.h new file mode 100644 index 000000000..c3e605547 --- /dev/null +++ b/src/Items/ItemMap.h @@ -0,0 +1,43 @@ + +// ItemMap.h + + + + + +#pragma once + +#include "../Entities/Entity.h" +#include "../Item.h" + + + + + +class cItemMapHandler : + public cItemHandler +{ + typedef cItemHandler super; + + static const unsigned int DEFAULT_RADIUS = 128; + +public: + cItemMapHandler() : + super(E_ITEM_MAP) + { + } + + virtual void OnUpdate(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item) + { + cMap * Map = a_World->GetMapData(a_Item.m_ItemDamage); + + if (Map == NULL) + { + return; + } + + // Map->AddTrackedPlayer(a_Player); + + Map->UpdateRadius(*a_Player, DEFAULT_RADIUS); + } +} ; diff --git a/src/Map.cpp b/src/Map.cpp index e0f991693..e85c23d3a 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -50,15 +50,25 @@ cMap::cMap(unsigned int a_ID, int a_CenterX, int a_CenterZ, cWorld * a_World, un +template +T Clamp(T a_X, T a_Min, T a_Max) +{ + return std::min(std::max(a_X, a_Min), a_Max); +} + + + + + void cMap::UpdateRadius(int a_PixelX, int a_PixelZ, unsigned int a_Radius) { int PixelRadius = a_Radius / GetPixelWidth(); - unsigned int StartX = std::max(a_PixelX - PixelRadius, 0); - unsigned int StartZ = std::max(a_PixelZ - PixelRadius, 0); + unsigned int StartX = Clamp(a_PixelX - PixelRadius, 0, (int)m_Width); + unsigned int StartZ = Clamp(a_PixelZ - PixelRadius, 0, (int)m_Height); - unsigned int EndX = std::min(a_PixelX + PixelRadius, (int)m_Width); - unsigned int EndZ = std::min(a_PixelZ + PixelRadius, (int)m_Height); + unsigned int EndX = Clamp(a_PixelX + PixelRadius, 0, (int)m_Width); + unsigned int EndZ = Clamp(a_PixelZ + PixelRadius, 0, (int)m_Height); for (unsigned int X = StartX; X < EndX; ++X) { @@ -93,11 +103,9 @@ void cMap::UpdateRadius(cPlayer & a_Player, unsigned int a_Radius) -bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Y) +bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z) { - ASSERT(m_World != NULL); - - unsigned int PixelWidth = GetPixelWidth(); + /*unsigned int PixelWidth = GetPixelWidth(); int BlockX = m_CenterX + ((a_X - m_Width) * PixelWidth); int BlockZ = m_CenterZ + ((a_Y - m_Height) * PixelWidth); @@ -119,7 +127,7 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Y) public: cCalculatePixelCb(cMap * a_Map, int a_RelX, int a_RelZ) - : m_Map(a_Map), m_RelX(a_RelX), m_RelZ(a_RelZ), m_PixelData(0) {} + : m_Map(a_Map), m_RelX(a_RelX), m_RelZ(a_RelZ), m_PixelData(4) {} virtual bool Item(cChunk * a_Chunk) override { @@ -155,9 +163,9 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Y) } CalculatePixelCb(this, RelX, RelZ); ASSERT(m_World != NULL); - m_World->DoWithChunk(ChunkX, ChunkZ, CalculatePixelCb); + m_World->DoWithChunk(ChunkX, ChunkZ, CalculatePixelCb);*/ - m_Data[a_Y + (a_X * m_Height)] = CalculatePixelCb.GetPixelData(); + m_Data[a_Z + (a_X * m_Height)] = 4; return true; } @@ -166,6 +174,39 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Y) +void cMap::UpdateTrackedPlayers(void) +{ + cTrackedPlayerList NewList; + + for (cTrackedPlayerList::iterator it = m_TrackedPlayers.begin(); it != m_TrackedPlayers.end(); ++it) + { + cPlayer * Player = *it; + + UpdateRadius(*Player, DEFAULT_RADIUS); + + if (true) + { + NewList.insert(Player); + } + } + + std::swap(m_TrackedPlayers, NewList); +} + + + + + +void cMap::AddTrackedPlayer(cPlayer * a_Player) +{ + ASSERT(a_Player != NULL); + m_TrackedPlayers.insert(a_Player); +} + + + + + void cMap::EraseData(void) { m_Data.assign(m_Width * m_Height, 0); diff --git a/src/Map.h b/src/Map.h index 4134d53a1..805dfb845 100644 --- a/src/Map.h +++ b/src/Map.h @@ -38,6 +38,8 @@ public: typedef std::vector cColorList; + static const unsigned int DEFAULT_RADIUS = 128; + public: @@ -54,6 +56,10 @@ public: void UpdateRadius(cPlayer & a_Player, unsigned int a_Radius); + void UpdateTrackedPlayers(void); + + void AddTrackedPlayer(cPlayer * a_Player); + // tolua_begin /** Erase pixel data */ @@ -93,7 +99,7 @@ public: private: /** Update the specified pixel. */ - bool UpdatePixel(unsigned int a_X, unsigned int a_Y); + bool UpdatePixel(unsigned int a_X, unsigned int a_Z); unsigned int m_ID; @@ -111,8 +117,9 @@ private: cWorld * m_World; - //typedef std::vector cPlayerList; - //cPlayerList m_TrackedPlayers; + typedef std::set cTrackedPlayerList; + + cTrackedPlayerList m_TrackedPlayers; AString m_Name; diff --git a/src/World.cpp b/src/World.cpp index 2a3e53332..55c6fbb7a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1574,8 +1574,7 @@ cMap * cWorld::CreateMap(int a_CenterX, int a_CenterY, int a_Scale) { if (m_MapData.size() >= 65536) { - LOGD("cWorld::CreateMap - Too many maps in use"); - + LOGWARN("Could not craft map - Too many maps in use"); return NULL; } @@ -2992,9 +2991,12 @@ void cWorld::LoadMapData(void) { cIDCountSerializer IDSerializer(GetName()); - IDSerializer.Load(); + if (!IDSerializer.Load()) + { + return; + } - unsigned int MapCount = IDSerializer.GetMapCount() + 1; + unsigned int MapCount = IDSerializer.GetMapCount(); m_MapData.clear(); @@ -3004,7 +3006,10 @@ void cWorld::LoadMapData(void) cMapSerializer Serializer(GetName(), &Map); - Serializer.Load(); + if (!Serializer.Load()) + { + LOGWARN("Could not load map #%i", Map.GetID()); + } m_MapData.push_back(Map); } @@ -3023,9 +3028,13 @@ void cWorld::SaveMapData(void) cIDCountSerializer IDSerializer(GetName()); - IDSerializer.SetMapCount(m_MapData.size() - 1); + IDSerializer.SetMapCount(m_MapData.size()); - IDSerializer.Save(); + if (!IDSerializer.Save()) + { + LOGERROR("Could not save idcounts.dat"); + return; + } for (cMapList::iterator it = m_MapData.begin(); it != m_MapData.end(); ++it) { @@ -3033,7 +3042,10 @@ void cWorld::SaveMapData(void) cMapSerializer Serializer(GetName(), &Map); - Serializer.Save(); + if (!Serializer.Save()) + { + LOGWARN("Could not save map #%i", Map.GetID()); + } } } diff --git a/src/WorldStorage/MapSerializer.cpp b/src/WorldStorage/MapSerializer.cpp index 6dab19d4f..0bbe71a60 100644 --- a/src/WorldStorage/MapSerializer.cpp +++ b/src/WorldStorage/MapSerializer.cpp @@ -223,7 +223,11 @@ bool cIDCountSerializer::Load(void) int CurrLine = NBT.FindChildByName(0, "map"); if (CurrLine >= 0) { - m_MapCount = (int)NBT.GetShort(CurrLine); + m_MapCount = (int)NBT.GetShort(CurrLine) + 1; + } + else + { + m_MapCount = 0; } return true; @@ -237,7 +241,10 @@ bool cIDCountSerializer::Save(void) { cFastNBTWriter Writer; - Writer.AddShort("map", m_MapCount); + if (m_MapCount > 0) + { + Writer.AddShort("map", m_MapCount - 1); + } Writer.Finish(); diff --git a/src/WorldStorage/MapSerializer.h b/src/WorldStorage/MapSerializer.h index d9da107bc..296cc92c8 100644 --- a/src/WorldStorage/MapSerializer.h +++ b/src/WorldStorage/MapSerializer.h @@ -27,10 +27,10 @@ public: cMapSerializer(const AString& a_WorldName, cMap * a_Map); - /// Try to load the scoreboard + /** Try to load the scoreboard */ bool Load(void); - /// Try to save the scoreboard + /** Try to save the scoreboard */ bool Save(void); @@ -56,8 +56,10 @@ public: cIDCountSerializer(const AString & a_WorldName); + /** Try to load the ID counts */ bool Load(void); + /** Try to save the ID counts */ bool Save(void); inline unsigned int GetMapCount(void) const { return m_MapCount; } @@ -70,6 +72,7 @@ private: AString m_Path; unsigned int m_MapCount; + };