summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Bindings/ManualBindings.cpp14
-rw-r--r--src/BlockEntities/BeaconEntity.cpp62
-rw-r--r--src/BlockEntities/BeaconEntity.h2
-rw-r--r--src/BlockEntities/BlockEntity.h2
-rw-r--r--src/BlockEntities/ChestEntity.cpp42
-rw-r--r--src/BlockEntities/ChestEntity.h3
-rw-r--r--src/BlockEntities/CommandBlockEntity.cpp32
-rw-r--r--src/BlockEntities/CommandBlockEntity.h3
-rw-r--r--src/BlockEntities/DropSpenserEntity.cpp48
-rw-r--r--src/BlockEntities/DropSpenserEntity.h3
-rw-r--r--src/BlockEntities/EnderChestEntity.h1
-rw-r--r--src/BlockEntities/FlowerPotEntity.cpp31
-rw-r--r--src/BlockEntities/FlowerPotEntity.h3
-rw-r--r--src/BlockEntities/FurnaceEntity.cpp54
-rw-r--r--src/BlockEntities/FurnaceEntity.h3
-rw-r--r--src/BlockEntities/HopperEntity.cpp11
-rw-r--r--src/BlockEntities/HopperEntity.h1
-rw-r--r--src/BlockEntities/JukeboxEntity.cpp28
-rw-r--r--src/BlockEntities/JukeboxEntity.h3
-rw-r--r--src/BlockEntities/MobHeadEntity.cpp32
-rw-r--r--src/BlockEntities/MobHeadEntity.h3
-rw-r--r--src/BlockEntities/NoteEntity.cpp29
-rw-r--r--src/BlockEntities/NoteEntity.h3
-rw-r--r--src/BlockEntities/SignEntity.cpp35
-rw-r--r--src/BlockEntities/SignEntity.h3
-rw-r--r--src/BlockID.h72
-rw-r--r--src/BlockInfo.cpp12
-rw-r--r--src/Blocks/BlockDirt.h10
-rw-r--r--src/Blocks/BlockDoor.h18
-rw-r--r--src/Blocks/BlockPiston.h4
-rw-r--r--src/Blocks/BlockTrapdoor.h6
-rw-r--r--src/ClientHandle.h14
-rw-r--r--src/Entities/Player.h8
-rw-r--r--src/Items/ItemHandler.cpp5
-rw-r--r--src/Items/ItemHoe.h27
-rw-r--r--src/Items/ItemPickaxe.h39
-rw-r--r--src/Root.h15
-rw-r--r--src/Simulator/SandSimulator.cpp1
-rw-r--r--src/World.cpp4
-rw-r--r--src/WorldStorage/CMakeLists.txt2
-rw-r--r--src/WorldStorage/WSSCompact.cpp1066
-rw-r--r--src/WorldStorage/WSSCompact.h157
-rw-r--r--src/WorldStorage/WorldStorage.cpp2
43 files changed, 182 insertions, 1731 deletions
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index d8134f159..f4764447c 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -1957,26 +1957,20 @@ static int tolua_cPlayer_PermissionMatches(lua_State * tolua_S)
// Check the params:
cLuaState L(tolua_S);
if (
- !L.CheckParamUserType(1, "cPlayer") ||
- !L.CheckParamString (2, 3) ||
- !L.CheckParamEnd (4)
+ !L.CheckParamUserTable(1, "cPlayer") ||
+ !L.CheckParamString (2, 3) ||
+ !L.CheckParamEnd (4)
)
{
return 0;
}
// Get the params:
- cPlayer * self = (cPlayer *)tolua_tousertype(tolua_S, 1, NULL);
- if (self == NULL)
- {
- LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
- return 0;
- }
AString Permission, Template;
L.GetStackValues(2, Permission, Template);
// Push the result of the match:
- L.Push(self->PermissionMatches(StringSplit(Permission, "."), StringSplit(Template, ".")));
+ L.Push(cPlayer::PermissionMatches(StringSplit(Permission, "."), StringSplit(Template, ".")));
return 1;
}
diff --git a/src/BlockEntities/BeaconEntity.cpp b/src/BlockEntities/BeaconEntity.cpp
index dcf659f47..02f45a097 100644
--- a/src/BlockEntities/BeaconEntity.cpp
+++ b/src/BlockEntities/BeaconEntity.cpp
@@ -303,68 +303,6 @@ void cBeaconEntity::UsedBy(cPlayer * a_Player)
-bool cBeaconEntity::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();
-
- Json::Value AllSlots = a_Value.get("Slots", 0);
- int SlotIdx = 0;
- for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr)
- {
- cItem Item;
- Item.FromJson(*itr);
- SetSlot(SlotIdx, Item);
- SlotIdx++;
- }
-
- m_BeaconLevel = (char)a_Value.get("Level", 0).asInt();
- int PrimaryEffect = a_Value.get("PrimaryEffect", 0).asInt();
- int SecondaryEffect = a_Value.get("SecondaryEffect", 0).asInt();
-
- if ((PrimaryEffect >= 0) && (PrimaryEffect <= (int)cEntityEffect::effSaturation))
- {
- m_PrimaryEffect = (cEntityEffect::eType)PrimaryEffect;
- }
-
- if ((SecondaryEffect >= 0) && (SecondaryEffect <= (int)cEntityEffect::effSaturation))
- {
- m_SecondaryEffect = (cEntityEffect::eType)SecondaryEffect;
- }
-
- return true;
-}
-
-
-
-
-
-void cBeaconEntity::SaveToJson(Json::Value& a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- Json::Value AllSlots;
- int NumSlots = m_Contents.GetNumSlots();
- for (int i = 0; i < NumSlots; i++)
- {
- Json::Value Slot;
- m_Contents.GetSlot(i).GetJson(Slot);
- AllSlots.append(Slot);
- }
- a_Value["Slots"] = AllSlots;
-
- a_Value["Level"] = m_BeaconLevel;
- a_Value["PrimaryEffect"] = (int)m_PrimaryEffect;
- a_Value["SecondaryEffect"] = (int)m_SecondaryEffect;
-}
-
-
-
-
-
void cBeaconEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendUpdateBlockEntity(*this);
diff --git a/src/BlockEntities/BeaconEntity.h b/src/BlockEntities/BeaconEntity.h
index 0d7150aef..8c2dad254 100644
--- a/src/BlockEntities/BeaconEntity.h
+++ b/src/BlockEntities/BeaconEntity.h
@@ -34,9 +34,7 @@ public:
cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
- bool LoadFromJson(const Json::Value & a_Value);
// cBlockEntity overrides:
- virtual void SaveToJson(Json::Value& a_Value) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h
index 066bbc696..54ab40f3e 100644
--- a/src/BlockEntities/BlockEntity.h
+++ b/src/BlockEntities/BlockEntity.h
@@ -74,8 +74,6 @@ public:
int GetRelZ(void) const { return m_RelZ; }
// tolua_end
-
- virtual void SaveToJson (Json::Value & a_Value) = 0;
/// Called when a player uses this entity; should open the UI window
virtual void UsedBy( cPlayer * a_Player) = 0;
diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp
index a89e5747e..19d88b646 100644
--- a/src/BlockEntities/ChestEntity.cpp
+++ b/src/BlockEntities/ChestEntity.cpp
@@ -33,48 +33,6 @@ cChestEntity::~cChestEntity()
-bool cChestEntity::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();
-
- Json::Value AllSlots = a_Value.get("Slots", 0);
- int SlotIdx = 0;
- for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr)
- {
- cItem Item;
- Item.FromJson(*itr);
- SetSlot(SlotIdx, Item);
- SlotIdx++;
- }
- return true;
-}
-
-
-
-
-
-void cChestEntity::SaveToJson(Json::Value & a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- Json::Value AllSlots;
- for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--)
- {
- Json::Value Slot;
- m_Contents.GetSlot(i).GetJson(Slot);
- AllSlots.append(Slot);
- }
- a_Value["Slots"] = AllSlots;
-}
-
-
-
-
-
void cChestEntity::SendTo(cClientHandle & a_Client)
{
// The chest entity doesn't need anything sent to the client when it's created / gets in the viewdistance
diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h
index fa36e08be..af5d851a8 100644
--- a/src/BlockEntities/ChestEntity.h
+++ b/src/BlockEntities/ChestEntity.h
@@ -39,11 +39,8 @@ public:
virtual ~cChestEntity();
static const char * GetClassStatic(void) { return "cChestEntity"; }
-
- bool LoadFromJson(const Json::Value & a_Value);
// cBlockEntity overrides:
- virtual void SaveToJson(Json::Value & a_Value) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual void UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp
index 318874a9b..1a5a3f01e 100644
--- a/src/BlockEntities/CommandBlockEntity.cpp
+++ b/src/BlockEntities/CommandBlockEntity.cpp
@@ -152,38 +152,6 @@ void cCommandBlockEntity::SendTo(cClientHandle & a_Client)
-bool cCommandBlockEntity::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_Command = a_Value.get("Command", "").asString();
- m_LastOutput = a_Value.get("LastOutput", "").asString();
- m_Result = (NIBBLETYPE)a_Value.get("SuccessCount", 0).asInt();
-
- return true;
-}
-
-
-
-
-
-void cCommandBlockEntity::SaveToJson(Json::Value & a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- a_Value["Command"] = m_Command;
- a_Value["LastOutput"] = m_LastOutput;
- a_Value["SuccessCount"] = m_Result;
-}
-
-
-
-
-
void cCommandBlockEntity::Execute()
{
ASSERT(m_World != NULL); // Execute should not be called before the command block is attached to a world
diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h
index 22cd44322..939f38610 100644
--- a/src/BlockEntities/CommandBlockEntity.h
+++ b/src/BlockEntities/CommandBlockEntity.h
@@ -39,9 +39,6 @@ public:
/// Creates a new empty command block entity
cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
- bool LoadFromJson( const Json::Value& a_Value);
- virtual void SaveToJson(Json::Value& a_Value) override;
-
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual void UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp
index 05c7403e7..dac951b27 100644
--- a/src/BlockEntities/DropSpenserEntity.cpp
+++ b/src/BlockEntities/DropSpenserEntity.cpp
@@ -142,54 +142,6 @@ bool cDropSpenserEntity::Tick(float a_Dt, cChunk & a_Chunk)
-bool cDropSpenserEntity::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();
-
- Json::Value AllSlots = a_Value.get("Slots", 0);
- int SlotIdx = 0;
- for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr)
- {
- cItem Contents;
- Contents.FromJson(*itr);
- m_Contents.SetSlot(SlotIdx, Contents);
- SlotIdx++;
- if (SlotIdx >= m_Contents.GetNumSlots())
- {
- return true;
- }
- }
-
- return true;
-}
-
-
-
-
-
-void cDropSpenserEntity::SaveToJson(Json::Value & a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- Json::Value AllSlots;
- int NumSlots = m_Contents.GetNumSlots();
- for (int i = 0; i < NumSlots; i++)
- {
- Json::Value Slot;
- m_Contents.GetSlot(i).GetJson(Slot);
- AllSlots.append(Slot);
- }
- a_Value["Slots"] = AllSlots;
-}
-
-
-
-
-
void cDropSpenserEntity::SendTo(cClientHandle & a_Client)
{
// Nothing needs to be sent
diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h
index c70cd0531..23f0ae89a 100644
--- a/src/BlockEntities/DropSpenserEntity.h
+++ b/src/BlockEntities/DropSpenserEntity.h
@@ -49,11 +49,8 @@ public:
virtual ~cDropSpenserEntity();
static const char * GetClassStatic(void) { return "cDropSpenserEntity"; }
-
- bool LoadFromJson(const Json::Value & a_Value);
// cBlockEntity overrides:
- virtual void SaveToJson(Json::Value & a_Value) override;
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual void UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/EnderChestEntity.h b/src/BlockEntities/EnderChestEntity.h
index 311af8d76..2719eb5e4 100644
--- a/src/BlockEntities/EnderChestEntity.h
+++ b/src/BlockEntities/EnderChestEntity.h
@@ -25,7 +25,6 @@ public:
// cBlockEntity overrides:
virtual void UsedBy(cPlayer * a_Player) override;
- virtual void SaveToJson(Json::Value & a_Value) override { UNUSED(a_Value); }
virtual void SendTo(cClientHandle & a_Client) override { UNUSED(a_Client); }
static void LoadFromJson(const Json::Value & a_Value, cItemGrid & a_Grid);
diff --git a/src/BlockEntities/FlowerPotEntity.cpp b/src/BlockEntities/FlowerPotEntity.cpp
index d2bc59d34..01560f814 100644
--- a/src/BlockEntities/FlowerPotEntity.cpp
+++ b/src/BlockEntities/FlowerPotEntity.cpp
@@ -72,37 +72,6 @@ void cFlowerPotEntity::Destroy(void)
-bool cFlowerPotEntity::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_Item = cItem();
- m_Item.FromJson(a_Value.get("Item", 0));
-
- return true;
-}
-
-
-
-
-
-void cFlowerPotEntity::SaveToJson(Json::Value & a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- Json::Value Item;
- m_Item.GetJson(Item);
- a_Value["Item"] = Item;
-}
-
-
-
-
-
bool cFlowerPotEntity::IsFlower(short m_ItemType, short m_ItemData)
{
switch (m_ItemType)
diff --git a/src/BlockEntities/FlowerPotEntity.h b/src/BlockEntities/FlowerPotEntity.h
index b86f9c840..b68d3b118 100644
--- a/src/BlockEntities/FlowerPotEntity.h
+++ b/src/BlockEntities/FlowerPotEntity.h
@@ -38,9 +38,6 @@ public:
/** Creates a new flowerpot entity at the specified block coords. a_World may be NULL */
cFlowerPotEntity(int a_BlocX, int a_BlockY, int a_BlockZ, cWorld * a_World);
-
- bool LoadFromJson( const Json::Value& a_Value);
- virtual void SaveToJson(Json::Value& a_Value) override;
virtual void Destroy(void) override;
diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp
index fb88e9b35..4452fc00a 100644
--- a/src/BlockEntities/FurnaceEntity.cpp
+++ b/src/BlockEntities/FurnaceEntity.cpp
@@ -129,60 +129,6 @@ bool cFurnaceEntity::Tick(float a_Dt, cChunk & a_Chunk)
-bool cFurnaceEntity::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();
-
- Json::Value AllSlots = a_Value.get("Slots", 0);
- int SlotIdx = 0;
- for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr)
- {
- cItem Item;
- Item.FromJson(*itr);
- SetSlot(SlotIdx, Item);
- SlotIdx++;
- }
-
- m_NeedCookTime = (int)(a_Value.get("CookTime", 0).asDouble() / 50);
- m_TimeCooked = (int)(a_Value.get("TimeCooked", 0).asDouble() / 50);
- m_FuelBurnTime = (int)(a_Value.get("BurnTime", 0).asDouble() / 50);
- m_TimeBurned = (int)(a_Value.get("TimeBurned", 0).asDouble() / 50);
-
- return true;
-}
-
-
-
-
-
-void cFurnaceEntity::SaveToJson( Json::Value& a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- Json::Value AllSlots;
- int NumSlots = m_Contents.GetNumSlots();
- for (int i = 0; i < NumSlots; i++)
- {
- Json::Value Slot;
- m_Contents.GetSlot(i).GetJson(Slot);
- AllSlots.append(Slot);
- }
- a_Value["Slots"] = AllSlots;
-
- a_Value["CookTime"] = m_NeedCookTime * 50;
- a_Value["TimeCooked"] = m_TimeCooked * 50;
- a_Value["BurnTime"] = m_FuelBurnTime * 50;
- a_Value["TimeBurned"] = m_TimeBurned * 50;
-}
-
-
-
-
-
void cFurnaceEntity::SendTo(cClientHandle & a_Client)
{
// Nothing needs to be sent
diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h
index 7ac25cf52..ed3317af6 100644
--- a/src/BlockEntities/FurnaceEntity.h
+++ b/src/BlockEntities/FurnaceEntity.h
@@ -44,11 +44,8 @@ public:
virtual ~cFurnaceEntity();
static const char * GetClassStatic() { return "cFurnaceEntity"; }
-
- bool LoadFromJson(const Json::Value & a_Value);
// cBlockEntity overrides:
- virtual void SaveToJson(Json::Value & a_Value) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp
index 444378c92..103f516fc 100644
--- a/src/BlockEntities/HopperEntity.cpp
+++ b/src/BlockEntities/HopperEntity.cpp
@@ -70,17 +70,6 @@ bool cHopperEntity::Tick(float a_Dt, cChunk & a_Chunk)
-void cHopperEntity::SaveToJson(Json::Value & a_Value)
-{
- UNUSED(a_Value);
- // TODO
- LOGWARNING("%s: Not implemented yet", __FUNCTION__);
-}
-
-
-
-
-
void cHopperEntity::SendTo(cClientHandle & a_Client)
{
// The hopper entity doesn't need anything sent to the client when it's created / gets in the viewdistance
diff --git a/src/BlockEntities/HopperEntity.h b/src/BlockEntities/HopperEntity.h
index 8e856fcda..5d06581c2 100644
--- a/src/BlockEntities/HopperEntity.h
+++ b/src/BlockEntities/HopperEntity.h
@@ -49,7 +49,6 @@ protected:
// cBlockEntity overrides:
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
- virtual void SaveToJson(Json::Value & a_Value) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual void UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/JukeboxEntity.cpp b/src/BlockEntities/JukeboxEntity.cpp
index 1131b99b0..bb9b335e0 100644
--- a/src/BlockEntities/JukeboxEntity.cpp
+++ b/src/BlockEntities/JukeboxEntity.cpp
@@ -117,31 +117,3 @@ void cJukeboxEntity::SetRecord(int a_Record)
-
-bool cJukeboxEntity::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_Record = a_Value.get("Record", 0).asInt();
-
- return true;
-}
-
-
-
-
-
-void cJukeboxEntity::SaveToJson(Json::Value & a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- a_Value["Record"] = m_Record;
-}
-
-
-
-
diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h
index a6fdf3c7e..49d2faa89 100644
--- a/src/BlockEntities/JukeboxEntity.h
+++ b/src/BlockEntities/JukeboxEntity.h
@@ -29,9 +29,6 @@ public:
cJukeboxEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cJukeboxEntity();
- bool LoadFromJson(const Json::Value & a_Value);
- virtual void SaveToJson(Json::Value & a_Value) override;
-
// tolua_begin
int GetRecord(void);
diff --git a/src/BlockEntities/MobHeadEntity.cpp b/src/BlockEntities/MobHeadEntity.cpp
index 9a1a40abe..67e13ffb2 100644
--- a/src/BlockEntities/MobHeadEntity.cpp
+++ b/src/BlockEntities/MobHeadEntity.cpp
@@ -77,35 +77,3 @@ void cMobHeadEntity::SendTo(cClientHandle & a_Client)
-
-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<eMobHeadType>(a_Value.get("Type", 0).asInt());
- m_Rotation = static_cast<eMobHeadRotation>(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
index 45fa0d951..fcdeaa8a6 100644
--- a/src/BlockEntities/MobHeadEntity.h
+++ b/src/BlockEntities/MobHeadEntity.h
@@ -37,9 +37,6 @@ public:
/** 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 */
diff --git a/src/BlockEntities/NoteEntity.cpp b/src/BlockEntities/NoteEntity.cpp
index ecbedbcb1..a9af13c55 100644
--- a/src/BlockEntities/NoteEntity.cpp
+++ b/src/BlockEntities/NoteEntity.cpp
@@ -124,32 +124,3 @@ void cNoteEntity::IncrementPitch(void)
-
-bool cNoteEntity::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_Pitch = (char)a_Value.get("p", 0).asInt();
-
- return true;
-}
-
-
-
-
-
-void cNoteEntity::SaveToJson(Json::Value & a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- a_Value["p"] = m_Pitch;
-}
-
-
-
-
diff --git a/src/BlockEntities/NoteEntity.h b/src/BlockEntities/NoteEntity.h
index f538de060..d1ffa126a 100644
--- a/src/BlockEntities/NoteEntity.h
+++ b/src/BlockEntities/NoteEntity.h
@@ -44,9 +44,6 @@ public:
cNoteEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
virtual ~cNoteEntity() {}
- bool LoadFromJson(const Json::Value & a_Value);
- virtual void SaveToJson(Json::Value & a_Value) override;
-
// tolua_begin
char GetPitch(void);
diff --git a/src/BlockEntities/SignEntity.cpp b/src/BlockEntities/SignEntity.cpp
index 423d254d2..d048d0218 100644
--- a/src/BlockEntities/SignEntity.cpp
+++ b/src/BlockEntities/SignEntity.cpp
@@ -22,7 +22,6 @@ cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorl
-// It don't do anything when 'used'
void cSignEntity::UsedBy(cPlayer * a_Player)
{
UNUSED(a_Player);
@@ -80,37 +79,3 @@ void cSignEntity::SendTo(cClientHandle & a_Client)
-
-bool cSignEntity::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_Line[0] = a_Value.get("Line1", "").asString();
- m_Line[1] = a_Value.get("Line2", "").asString();
- m_Line[2] = a_Value.get("Line3", "").asString();
- m_Line[3] = a_Value.get("Line4", "").asString();
-
- return true;
-}
-
-
-
-
-
-void cSignEntity::SaveToJson(Json::Value & a_Value)
-{
- a_Value["x"] = m_PosX;
- a_Value["y"] = m_PosY;
- a_Value["z"] = m_PosZ;
-
- a_Value["Line1"] = m_Line[0];
- a_Value["Line2"] = m_Line[1];
- a_Value["Line3"] = m_Line[2];
- a_Value["Line4"] = m_Line[3];
-}
-
-
-
-
diff --git a/src/BlockEntities/SignEntity.h b/src/BlockEntities/SignEntity.h
index 33af100a4..53c43b758 100644
--- a/src/BlockEntities/SignEntity.h
+++ b/src/BlockEntities/SignEntity.h
@@ -37,9 +37,6 @@ public:
/// Creates a new empty sign entity at the specified block coords and block type (wall or standing). a_World may be NULL
cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World);
- bool LoadFromJson( const Json::Value& a_Value);
- virtual void SaveToJson(Json::Value& a_Value) override;
-
// tolua_begin
/// Sets all the sign's lines
diff --git a/src/BlockID.h b/src/BlockID.h
index 9a8830710..69b5e2fe0 100644
--- a/src/BlockID.h
+++ b/src/BlockID.h
@@ -186,6 +186,9 @@ enum ENUM_BLOCK_ID
E_BLOCK_BLOCK_OF_COAL = 173,
E_BLOCK_PACKED_ICE = 174,
E_BLOCK_BIG_FLOWER = 175,
+ E_BLOCK_STANDING_BANNER = 176,
+ E_BLOCK_WALL_BANNER = 177,
+ E_BLOCK_INVERTED_DAYLIGHT_SENSOR = 178,
E_BLOCK_RED_SANDSTONE = 179,
E_BLOCK_RED_SANDSTONE_STAIRS = 180,
E_BLOCK_DOUBLE_NEW_STONE_SLAB= 181,
@@ -442,7 +445,7 @@ enum
////////////////////////////////////////////////////////////////////////////////
// Block metas:
- // E_BLOCK_BIG_FLOWER metas
+ // E_BLOCK_BIG_FLOWER metas:
E_META_BIG_FLOWER_SUNFLOWER = 0,
E_META_BIG_FLOWER_LILAC = 1,
E_META_BIG_FLOWER_DOUBLE_TALL_GRASS = 2,
@@ -477,6 +480,7 @@ enum
// E_BLOCK_DIRT metas:
E_META_DIRT_NORMAL = 0,
E_META_DIRT_GRASSLESS = 1,
+ E_META_DIRT_COARSE = 1,
E_META_DIRT_PODZOL = 2,
// E_BLOCK_DISPENSER / E_BLOCK_DROPPER metas:
@@ -497,7 +501,7 @@ enum
E_META_DOUBLE_STONE_SLAB_NETHER_BRICK = 6,
E_META_DOUBLE_STONE_SLAB_STONE_SECRET = 7,
- // E_BLOCK_FLOWER metas
+ // E_BLOCK_FLOWER metas:
E_META_FLOWER_POPPY = 0,
E_META_FLOWER_BLUE_ORCHID = 1,
E_META_FLOWER_ALLIUM = 2,
@@ -507,7 +511,7 @@ enum
E_META_FLOWER_PINK_TULIP = 7,
E_META_FLOWER_OXEYE_DAISY = 8,
- // E_BLOCK_JUKEBOX metas
+ // E_BLOCK_JUKEBOX metas:
E_META_JUKEBOX_OFF = 0,
E_META_JUKEBOX_ON = 1,
@@ -531,30 +535,37 @@ enum
E_META_LOG_BIRCH = 2,
E_META_LOG_JUNGLE = 3,
- // E_BLOCK_NEW_LEAVES metas
+ // E_BLOCK_NEW_LEAVES metas:
E_META_NEW_LEAVES_ACACIA_WOOD = 0,
E_META_NEW_LEAVES_DARK_OAK_WOOD = 1,
- // E_BLOCK_NEW_LOG metas
+ // E_BLOCK_NEW_LOG metas:
E_META_NEW_LOG_ACACIA_WOOD = 0,
E_META_NEW_LOG_DARK_OAK_WOOD = 1,
// E_BLOCK_PLANKS metas:
- E_META_PLANKS_APPLE = 0,
- E_META_PLANKS_CONIFER = 1,
- E_META_PLANKS_BIRCH = 2,
- E_META_PLANKS_JUNGLE = 3,
+ E_META_PLANKS_APPLE = 0,
+ E_META_PLANKS_CONIFER = 1,
+ E_META_PLANKS_BIRCH = 2,
+ E_META_PLANKS_JUNGLE = 3,
+ E_META_PLANKS_ACACIA = 4,
+ E_META_PLANKS_DARK_OAK = 5,
// E_BLOCK_(XXX_WEIGHTED)_PRESSURE_PLATE metas:
E_META_PRESSURE_PLATE_RAISED = 0,
E_META_PRESSURE_PLATE_DEPRESSED = 1,
+ // E_BLOCK_PRISMARINE_BLOCK metas:
+ E_META_PRISMARINE_BLOCK_ROUGH = 0,
+ E_META_PRISMARINE_BLOCK_BRICKS = 1,
+ E_META_PRISMARINE_BLOCK_DARK = 2,
+
// E_BLOCK_QUARTZ_BLOCK metas:
E_META_QUARTZ_NORMAL = 0,
E_META_QUARTZ_CHISELLED = 1,
E_META_QUARTZ_PILLAR = 2,
- // E_BLOCK_RAIL metas
+ // E_BLOCK_RAIL metas:
E_META_RAIL_ZM_ZP = 0,
E_META_RAIL_XM_XP = 1,
E_META_RAIL_ASCEND_XP = 2,
@@ -566,6 +577,11 @@ enum
E_META_RAIL_CURVED_ZM_XM = 8,
E_META_RAIL_CURVED_ZM_XP = 9,
+ // E_BLOCK_RED_SANDSTONE metas:
+ E_META_RED_SANDSTONE_NORMAL = 0,
+ E_META_RED_SANDSTONE_ORNAMENT = 1,
+ E_META_RED_SANDSTONE_SMOOTH = 2,
+
// E_BLOCK_SAND metas:
E_META_SAND_NORMAL = 0,
E_META_SAND_RED = 1,
@@ -598,7 +614,7 @@ enum
E_META_SNOW_LAYER_SEVEN = 6,
E_META_SNOW_LAYER_EIGHT = 7,
- // E_BLOCK_STAINED_CLAY metas
+ // E_BLOCK_STAINED_CLAY metas:
E_META_STAINED_CLAY_WHITE = 0,
E_META_STAINED_CLAY_ORANGE = 1,
E_META_STAINED_CLAY_MAGENTA = 2,
@@ -616,7 +632,7 @@ enum
E_META_STAINED_CLAY_RED = 14,
E_META_STAINED_CLAY_BLACK = 15,
- // E_BLOCK_STAINED_GLASS metas
+ // E_BLOCK_STAINED_GLASS metas:
E_META_STAINED_GLASS_WHITE = 0,
E_META_STAINED_GLASS_ORANGE = 1,
E_META_STAINED_GLASS_MAGENTA = 2,
@@ -634,7 +650,7 @@ enum
E_META_STAINED_GLASS_RED = 14,
E_META_STAINED_GLASS_BLACK = 15,
- // E_BLOCK_STAINED_GLASS_PANE metas
+ // E_BLOCK_STAINED_GLASS_PANE metas:
E_META_STAINED_GLASS_PANE_WHITE = 0,
E_META_STAINED_GLASS_PANE_ORANGE = 1,
E_META_STAINED_GLASS_PANE_MAGENTA = 2,
@@ -655,8 +671,11 @@ enum
// E_BLOCK_STONE metas:
E_META_STONE = 0,
E_META_STONE_GRANITE = 1,
+ E_META_STONE_POLISHED_GRANITE = 2,
E_META_STONE_DIORITE = 3,
+ E_META_STONE_POLISHED_DIORITE = 4,
E_META_STONE_ANDESITE = 5,
+ E_META_STONE_POLISHED_ANDESITE = 6,
// E_BLOCK_STONE_SLAB metas:
E_META_STONE_SLAB_STONE = 0,
@@ -727,6 +746,24 @@ enum
////////////////////////////////////////////////////////////////////////////////
// Item metas:
+ // E_ITEM_BANNER metas:
+ E_META_BANNER_BLACK = 0,
+ E_META_BANNER_RED = 1,
+ E_META_BANNER_GREEN = 2,
+ E_META_BANNER_BROWN = 3,
+ E_META_BANNER_BLUE = 4,
+ E_META_BANNER_PURPLE = 5,
+ E_META_BANNER_CYAN = 6,
+ E_META_BANNER_LIGHTGRAY = 7,
+ E_META_BANNER_GRAY = 8,
+ E_META_BANNER_PINK = 9,
+ E_META_BANNER_LIGHTGREEN = 10,
+ E_META_BANNER_YELLOW = 11,
+ E_META_BANNER_LIGHTBLUE = 12,
+ E_META_BANNER_MAGENTA = 13,
+ E_META_BANNER_ORANGE = 14,
+ E_META_BANNER_WHITE = 15,
+
// E_ITEM_COAL metas:
E_META_COAL_NORMAL = 0,
E_META_COAL_CHARCOAL = 1,
@@ -753,6 +790,13 @@ enum
E_META_GOLDEN_APPLE_NORMAL = 0,
E_META_GOLDEN_APPLE_ENCHANTED = 1,
+ // E_ITEM_HEAD metas:
+ E_META_HEAD_SKELETON = 0,
+ E_META_HEAD_WITHER = 1,
+ E_META_HEAD_ZOMBIE = 2,
+ E_META_HEAD_PLAYER = 3,
+ E_META_HEAD_CREEPER = 4,
+
// E_ITEM_RAW_FISH metas:
E_META_RAW_FISH_FISH = 0,
E_META_RAW_FISH_SALMON = 1,
@@ -762,8 +806,6 @@ enum
// E_ITEM_COOKED_FISH metas:
E_META_COOKED_FISH_FISH = 0,
E_META_COOKED_FISH_SALMON = 1,
- E_META_COOKED_FISH_CLOWNFISH = 2,
- E_META_COOKED_FISH_PUFFERFISH = 3,
// E_ITEM_MINECART_TRACKS metas:
E_META_TRACKS_X = 1,
diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp
index 05a1e13f8..bdd3a9c26 100644
--- a/src/BlockInfo.cpp
+++ b/src/BlockInfo.cpp
@@ -99,6 +99,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_HOPPER ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_ICE ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_INVERTED_DAYLIGHT_SENSOR ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_IRON_BARS ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_IRON_DOOR ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_IRON_TRAPDOOR ].m_SpreadLightFalloff = 1;
@@ -137,6 +138,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_SPRUCE_FENCE_GATE ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_STAINED_GLASS ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_STANDING_BANNER ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_STICKY_PISTON ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_STONE_BUTTON ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_SpreadLightFalloff = 1;
@@ -149,6 +151,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_TRIPWIRE ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_WALL_BANNER ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_WALLSIGN ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_WOODEN_BUTTON ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_WOODEN_DOOR ].m_SpreadLightFalloff = 1;
@@ -256,6 +259,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_Transparent = true;
a_Info[E_BLOCK_STATIONARY_LAVA ].m_Transparent = true;
a_Info[E_BLOCK_STATIONARY_WATER ].m_Transparent = true;
+ a_Info[E_BLOCK_STANDING_BANNER ].m_Transparent = true;
a_Info[E_BLOCK_STICKY_PISTON ].m_Transparent = true;
a_Info[E_BLOCK_STONE_BUTTON ].m_Transparent = true;
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_Transparent = true;
@@ -268,6 +272,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_TRIPWIRE ].m_Transparent = true;
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_Transparent = true;
a_Info[E_BLOCK_VINES ].m_Transparent = true;
+ a_Info[E_BLOCK_WALL_BANNER ].m_Transparent = true;
a_Info[E_BLOCK_WALLSIGN ].m_Transparent = true;
a_Info[E_BLOCK_WATER ].m_Transparent = true;
a_Info[E_BLOCK_WOODEN_BUTTON ].m_Transparent = true;
@@ -329,6 +334,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_PistonBreakable = true;
a_Info[E_BLOCK_IRON_DOOR ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_IRON_TRAPDOOR ].m_PistonBreakable = true;
a_Info[E_BLOCK_JACK_O_LANTERN ].m_PistonBreakable = true;
a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
a_Info[E_BLOCK_LILY_PAD ].m_PistonBreakable = true;
@@ -474,12 +480,14 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_SNOW ].m_IsSolid = false;
a_Info[E_BLOCK_STATIONARY_LAVA ].m_IsSolid = false;
a_Info[E_BLOCK_STATIONARY_WATER ].m_IsSolid = false;
+ a_Info[E_BLOCK_STANDING_BANNER ].m_IsSolid = false;
a_Info[E_BLOCK_STONE_BUTTON ].m_IsSolid = false;
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_IsSolid = false;
a_Info[E_BLOCK_TALL_GRASS ].m_IsSolid = false;
a_Info[E_BLOCK_TORCH ].m_IsSolid = false;
a_Info[E_BLOCK_TRIPWIRE ].m_IsSolid = false;
a_Info[E_BLOCK_VINES ].m_IsSolid = false;
+ a_Info[E_BLOCK_WALL_BANNER ].m_IsSolid = false;
a_Info[E_BLOCK_WALLSIGN ].m_IsSolid = false;
a_Info[E_BLOCK_WATER ].m_IsSolid = false;
a_Info[E_BLOCK_WOODEN_BUTTON ].m_IsSolid = false;
@@ -735,7 +743,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_NEW_LOG ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_ACACIA_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_DARK_OAK_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
- a_Info[E_BLOCK_SLIME_BLOCK ].m_PlaceSound = "dig.slime"; // TODO: Check that this is the correct name
+ a_Info[E_BLOCK_SLIME_BLOCK ].m_PlaceSound = "mob.slime.big";
a_Info[E_BLOCK_BARRIER ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_IRON_TRAPDOOR ].m_PlaceSound = "dig.metal";
a_Info[E_BLOCK_PRISMARINE_BLOCK ].m_PlaceSound = "dig.stone";
@@ -746,6 +754,8 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_BLOCK_OF_COAL ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_PACKED_ICE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_BIG_FLOWER ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_STANDING_BANNER ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_WALL_BANNER ].m_PlaceSound = "dig.wood";
a_Info[E_BLOCK_RED_SANDSTONE ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_RED_SANDSTONE_STAIRS ].m_PlaceSound = "dig.stone";
a_Info[E_BLOCK_NEW_STONE_SLAB ].m_PlaceSound = "dig.stone";
diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h
index 60d81db72..19f889372 100644
--- a/src/Blocks/BlockDirt.h
+++ b/src/Blocks/BlockDirt.h
@@ -21,7 +21,15 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- a_Pickups.push_back(cItem(E_BLOCK_DIRT, 1, 0));
+ if (a_BlockMeta == E_META_DIRT_COARSE)
+ {
+ // Drop the coarse block (dirt, meta 1)
+ a_Pickups.Add(E_BLOCK_DIRT, 1, E_META_DIRT_COARSE);
+ }
+ else
+ {
+ a_Pickups.Add(E_BLOCK_DIRT, 1, E_META_DIRT_NORMAL);
+ }
}
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index 0ff8bcfc8..92ad8da12 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -173,7 +173,23 @@ public:
/** Returns true if the specified blocktype is any kind of door */
inline static bool IsDoor(BLOCKTYPE a_Block)
{
- return (a_Block == E_BLOCK_WOODEN_DOOR) || (a_Block == E_BLOCK_IRON_DOOR);
+ switch (a_Block)
+ {
+ case E_BLOCK_ACACIA_DOOR:
+ case E_BLOCK_BIRCH_DOOR:
+ case E_BLOCK_DARK_OAK_DOOR:
+ case E_BLOCK_IRON_DOOR:
+ case E_BLOCK_JUNGLE_DOOR:
+ case E_BLOCK_SPRUCE_DOOR:
+ case E_BLOCK_WOODEN_DOOR:
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
}
diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h
index 3a3fc7224..f868f4d8e 100644
--- a/src/Blocks/BlockPiston.h
+++ b/src/Blocks/BlockPiston.h
@@ -100,6 +100,7 @@ private:
case E_BLOCK_BREWING_STAND:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
+ case E_BLOCK_DAYLIGHT_SENSOR:
case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER:
case E_BLOCK_ENCHANTMENT_TABLE:
@@ -108,6 +109,7 @@ private:
// Notice the lack of an E_BLOCK_ENDER_CHEST here; its because ender chests can totally be pushed/pulled in MCS :)
case E_BLOCK_FURNACE:
case E_BLOCK_LIT_FURNACE:
+ case E_BLOCK_INVERTED_DAYLIGHT_SENSOR:
case E_BLOCK_HOPPER:
case E_BLOCK_JUKEBOX:
case E_BLOCK_MOB_SPAWNER:
@@ -115,7 +117,9 @@ private:
case E_BLOCK_NOTE_BLOCK:
case E_BLOCK_OBSIDIAN:
case E_BLOCK_PISTON_EXTENSION:
+ case E_BLOCK_STANDING_BANNER:
case E_BLOCK_TRAPPED_CHEST:
+ case E_BLOCK_WALL_BANNER:
{
return false;
}
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 41256ae55..8c96de0f1 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -29,6 +29,12 @@ public:
virtual void OnUse(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) override
{
+ if (m_BlockType == E_BLOCK_IRON_TRAPDOOR)
+ {
+ // Iron doors can only be toggled by redstone, not by right-clicking
+ return;
+ }
+
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x04);
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 1f22762c0..20592c190 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -145,7 +145,9 @@ public:
void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player);
void SendDestroyEntity (const cEntity & a_Entity);
void SendDisconnect (const AString & a_Reason);
+ void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ);
+ void SendEntityAnimation (const cEntity & a_Entity, char a_Animation); // tolua_export
void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration);
void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item);
void SendEntityHeadLook (const cEntity & a_Entity);
@@ -156,6 +158,8 @@ public:
void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ);
void SendEntityStatus (const cEntity & a_Entity, char a_Status);
void SendEntityVelocity (const cEntity & a_Entity);
+ void SendExperience (void);
+ void SendExperienceOrb (const cExpOrb & a_ExpOrb);
void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion);
void SendGameMode (eGameMode a_GameMode);
void SendHealth (void);
@@ -164,15 +168,14 @@ public:
void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale);
void SendMapInfo (int a_ID, unsigned int a_Scale);
void SendPaintingSpawn (const cPainting & a_Painting);
- void SendPickupSpawn (const cPickup & a_Pickup);
- void SendEntityAnimation (const cEntity & a_Entity, char a_Animation); // tolua_export
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_ParticleAmount);
+ void SendPickupSpawn (const cPickup & a_Pickup);
void SendPlayerAbilities (void);
void SendPlayerListAddPlayer (const cPlayer & a_Player);
void SendPlayerListRemovePlayer (const cPlayer & a_Player);
+ void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName);
void SendPlayerListUpdateGameMode (const cPlayer & a_Player);
void SendPlayerListUpdatePing (const cPlayer & a_Player);
- void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName);
void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+)
void SendPlayerMoveLook (void);
void SendPlayerPosition (void);
@@ -180,11 +183,8 @@ public:
void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false);
- void SendExperience (void);
- void SendExperienceOrb (const cExpOrb & a_ExpOrb);
- void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode);
- void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
+ void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch); // tolua_export
void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data);
void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock);
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index ffd0b7e03..22d6a2ae2 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -182,11 +182,11 @@ public:
/** Sets the player team, NULL if none */
void SetTeam(cTeam * a_Team);
+ // tolua_end
+
/** Forces the player to query the scoreboard for his team */
cTeam * UpdateTeam(void);
- // tolua_end
-
/** Return the associated statistic and achievement manager. */
cStatManager & GetStatManager() { return m_Stats; }
@@ -421,9 +421,13 @@ public:
/** Sets the player's bed (home) position */
void SetBedPos(const Vector3i & a_Pos) { m_LastBedPos = a_Pos; }
+
+ // tolua_end
/** Update movement-related statistics. */
void UpdateMovementStats(const Vector3d & a_DeltaPos);
+
+ // tolua_begin
/** Returns wheter the player can fly or not. */
virtual bool CanFly(void) const { return m_CanFly; }
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index caa623abc..912dde022 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -574,6 +574,7 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
case E_BLOCK_COBBLESTONE_WALL:
case E_BLOCK_DIAMOND_BLOCK:
case E_BLOCK_DIAMOND_ORE:
+ case E_BLOCK_DOUBLE_NEW_STONE_SLAB:
case E_BLOCK_DOUBLE_STONE_SLAB:
case E_BLOCK_EMERALD_ORE:
case E_BLOCK_ENCHANTMENT_TABLE:
@@ -587,6 +588,7 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
case E_BLOCK_LAPIS_BLOCK:
case E_BLOCK_LAPIS_ORE:
case E_BLOCK_LIT_FURNACE:
+ case E_BLOCK_MOB_SPAWNER:
case E_BLOCK_MOSSY_COBBLESTONE:
case E_BLOCK_NETHER_BRICK:
case E_BLOCK_NETHER_BRICK_STAIRS:
@@ -594,6 +596,7 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
case E_BLOCK_NETHERRACK:
case E_BLOCK_NEW_STONE_SLAB:
case E_BLOCK_OBSIDIAN:
+ case E_BLOCK_PACKED_ICE:
case E_BLOCK_PRISMARINE_BLOCK:
case E_BLOCK_RED_SANDSTONE:
case E_BLOCK_RED_SANDSTONE_STAIRS:
@@ -608,8 +611,6 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
case E_BLOCK_STONE_PRESSURE_PLATE:
case E_BLOCK_STONE_SLAB:
case E_BLOCK_VINES:
- case E_BLOCK_PACKED_ICE:
- case E_BLOCK_MOB_SPAWNER:
{
return false;
}
diff --git a/src/Items/ItemHoe.h b/src/Items/ItemHoe.h
index de8b9a061..ae3723323 100644
--- a/src/Items/ItemHoe.h
+++ b/src/Items/ItemHoe.h
@@ -24,12 +24,35 @@ public:
{
return false;
}
- BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
BLOCKTYPE UpperBlock = a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
+ BLOCKTYPE Block;
+ NIBBLETYPE BlockMeta;
+ a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, Block, BlockMeta);
+
if (((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS)) && (UpperBlock == E_BLOCK_AIR))
{
- a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, 0);
+ BLOCKTYPE NewBlock = E_BLOCK_FARMLAND;
+ if (Block == E_BLOCK_DIRT)
+ {
+ switch (BlockMeta)
+ {
+ case E_META_DIRT_COARSE:
+ {
+ // Transform to normal dirt
+ NewBlock = E_BLOCK_DIRT;
+ break;
+ }
+ case E_META_DIRT_PODZOL:
+ {
+ // You can't transform this block with a hoe in vanilla
+ return false;
+ }
+ default: break;
+ }
+ }
+
+ a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, NewBlock, 0);
a_World->BroadcastSoundEffect("dig.gravel", a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 1.0f, 0.8f);
a_Player->UseEquippedItem();
return true;
diff --git a/src/Items/ItemPickaxe.h b/src/Items/ItemPickaxe.h
index e0cf5d711..b5dc179f8 100644
--- a/src/Items/ItemPickaxe.h
+++ b/src/Items/ItemPickaxe.h
@@ -41,11 +41,11 @@ public:
case E_BLOCK_DIAMOND_BLOCK:
case E_BLOCK_DIAMOND_ORE:
+ case E_BLOCK_EMERALD_ORE:
case E_BLOCK_GOLD_BLOCK:
case E_BLOCK_GOLD_ORE:
case E_BLOCK_REDSTONE_ORE:
case E_BLOCK_REDSTONE_ORE_GLOWING:
- case E_BLOCK_EMERALD_ORE:
{
return PickaxeLevel() >= 3;
}
@@ -59,29 +59,34 @@ public:
}
case E_BLOCK_ANVIL:
- case E_BLOCK_ENCHANTMENT_TABLE:
- case E_BLOCK_FURNACE:
- case E_BLOCK_LIT_FURNACE:
+ case E_BLOCK_BRICK:
+ case E_BLOCK_CAULDRON:
case E_BLOCK_COAL_ORE:
- case E_BLOCK_STONE:
case E_BLOCK_COBBLESTONE:
+ case E_BLOCK_COBBLESTONE_STAIRS:
+ case E_BLOCK_COBBLESTONE_WALL:
+ case E_BLOCK_DOUBLE_NEW_STONE_SLAB:
+ case E_BLOCK_DOUBLE_STONE_SLAB:
+ case E_BLOCK_ENCHANTMENT_TABLE:
case E_BLOCK_END_STONE:
+ case E_BLOCK_FURNACE:
+ case E_BLOCK_LIT_FURNACE:
+ case E_BLOCK_MOB_SPAWNER:
case E_BLOCK_MOSSY_COBBLESTONE:
- case E_BLOCK_SANDSTONE_STAIRS:
- case E_BLOCK_SANDSTONE:
- case E_BLOCK_STONE_BRICKS:
case E_BLOCK_NETHER_BRICK:
+ case E_BLOCK_NETHER_BRICK_STAIRS:
case E_BLOCK_NETHERRACK:
- case E_BLOCK_STONE_SLAB:
- case E_BLOCK_DOUBLE_STONE_SLAB:
- case E_BLOCK_STONE_PRESSURE_PLATE:
- case E_BLOCK_BRICK:
- case E_BLOCK_COBBLESTONE_STAIRS:
- case E_BLOCK_COBBLESTONE_WALL:
+ case E_BLOCK_NEW_STONE_SLAB:
+ case E_BLOCK_PRISMARINE_BLOCK:
+ case E_BLOCK_RED_SANDSTONE:
+ case E_BLOCK_RED_SANDSTONE_STAIRS:
+ case E_BLOCK_SANDSTONE:
+ case E_BLOCK_SANDSTONE_STAIRS:
+ case E_BLOCK_STONE:
+ case E_BLOCK_STONE_BRICKS:
case E_BLOCK_STONE_BRICK_STAIRS:
- case E_BLOCK_NETHER_BRICK_STAIRS:
- case E_BLOCK_CAULDRON:
- case E_BLOCK_MOB_SPAWNER:
+ case E_BLOCK_STONE_PRESSURE_PLATE:
+ case E_BLOCK_STONE_SLAB:
{
return PickaxeLevel() >= 1;
}
diff --git a/src/Root.h b/src/Root.h
index 9a482556c..84c6a98ec 100644
--- a/src/Root.h
+++ b/src/Root.h
@@ -41,11 +41,12 @@ namespace Json
class cRoot
{
public:
- static bool m_TerminateEventRaised;
-
static cRoot * Get() { return s_Root; }
// tolua_end
+ static bool m_TerminateEventRaised;
+
+
cRoot(void);
~cRoot();
@@ -129,15 +130,15 @@ public:
/// Sends a chat message to all connected clients (in all worlds)
void BroadcastChat (const AString & a_Message, eMessageType a_ChatPrefix = mtCustom);
- void BroadcastChatInfo (const AString & a_Message) { BroadcastChat(a_Message, mtInformation); }
+ void BroadcastChat (const cCompositeChat & a_Message);
+ void BroadcastChatDeath (const AString & a_Message) { BroadcastChat(a_Message, mtDeath); }
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 BroadcastChatInfo (const AString & a_Message) { BroadcastChat(a_Message, mtInformation); }
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);
+ void BroadcastChatSuccess(const AString & a_Message) { BroadcastChat(a_Message, mtSuccess); }
+ void BroadcastChatWarning(const AString & a_Message) { BroadcastChat(a_Message, mtWarning); }
/// 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/Simulator/SandSimulator.cpp b/src/Simulator/SandSimulator.cpp
index e8887ce59..aad41e463 100644
--- a/src/Simulator/SandSimulator.cpp
+++ b/src/Simulator/SandSimulator.cpp
@@ -160,6 +160,7 @@ bool cSandSimulator::CanContinueFallThrough(BLOCKTYPE a_BlockType)
case E_BLOCK_FIRE:
case E_BLOCK_FLOWER_POT:
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
+ case E_BLOCK_IRON_TRAPDOOR:
case E_BLOCK_LAVA:
case E_BLOCK_LEVER:
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
diff --git a/src/World.cpp b/src/World.cpp
index 6059b841f..a3c804b44 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2954,7 +2954,7 @@ bool cWorld::IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ)
BLOCKTYPE Block;
NIBBLETYPE Meta;
GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, Block, Meta);
- if (Block != E_BLOCK_TRAPDOOR)
+ if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR))
{
return false;
}
@@ -2971,7 +2971,7 @@ bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Op
BLOCKTYPE Block;
NIBBLETYPE Meta;
GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, Block, Meta);
- if (Block != E_BLOCK_TRAPDOOR)
+ if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR))
{
return false;
}
diff --git a/src/WorldStorage/CMakeLists.txt b/src/WorldStorage/CMakeLists.txt
index a00ff3b2f..59193db2a 100644
--- a/src/WorldStorage/CMakeLists.txt
+++ b/src/WorldStorage/CMakeLists.txt
@@ -14,7 +14,6 @@ SET (SRCS
ScoreboardSerializer.cpp
StatSerializer.cpp
WSSAnvil.cpp
- WSSCompact.cpp
WorldStorage.cpp)
SET (HDRS
@@ -27,7 +26,6 @@ SET (HDRS
ScoreboardSerializer.h
StatSerializer.h
WSSAnvil.h
- WSSCompact.h
WorldStorage.h)
if(NOT MSVC)
diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp
deleted file mode 100644
index 6760186b2..000000000
--- a/src/WorldStorage/WSSCompact.cpp
+++ /dev/null
@@ -1,1066 +0,0 @@
-
-// WSSCompact.cpp
-
-// Interfaces to the cWSSCompact class representing the "compact" storage schema (PAK-files)
-
-#include "Globals.h"
-#include "WSSCompact.h"
-#include "../World.h"
-#include "zlib/zlib.h"
-#include "json/json.h"
-#include "../StringCompression.h"
-#include "../BlockEntities/BeaconEntity.h"
-#include "../BlockEntities/ChestEntity.h"
-#include "../BlockEntities/CommandBlockEntity.h"
-#include "../BlockEntities/DispenserEntity.h"
-#include "../BlockEntities/FlowerPotEntity.h"
-#include "../BlockEntities/FurnaceEntity.h"
-#include "../BlockEntities/JukeboxEntity.h"
-#include "../BlockEntities/MobHeadEntity.h"
-#include "../BlockEntities/NoteEntity.h"
-#include "../BlockEntities/SignEntity.h"
-#include "../SetChunkData.h"
-
-
-
-
-
-#pragma pack(push, 1)
-/// The chunk header, as stored in the file:
-struct cWSSCompact::sChunkHeader
-{
- int m_ChunkX;
- int m_ChunkZ;
- int m_CompressedSize;
- int m_UncompressedSize;
-} ;
-#pragma pack(pop)
-
-
-
-
-
-/// The maximum number of PAK files that are cached
-const size_t MAX_PAK_FILES = 16;
-
-/// The maximum number of unsaved chunks before the cPAKFile saves them to disk
-const int MAX_DIRTY_CHUNKS = 16;
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cJsonChunkSerializer:
-
-cJsonChunkSerializer::cJsonChunkSerializer(void) :
- m_HasJsonData(false)
-{
-}
-
-
-
-
-
-void cJsonChunkSerializer::Entity(cEntity * a_Entity)
-{
- // TODO: a_Entity->SaveToJson(m_Root);
-}
-
-
-
-
-
-void cJsonChunkSerializer::BlockEntity(cBlockEntity * a_BlockEntity)
-{
- const char * SaveInto = NULL;
- switch (a_BlockEntity->GetBlockType())
- {
- case E_BLOCK_BEACON: SaveInto = "Beacons"; break;
- case E_BLOCK_CHEST: SaveInto = "Chests"; break;
- case E_BLOCK_DISPENSER: SaveInto = "Dispensers"; break;
- case E_BLOCK_DROPPER: SaveInto = "Droppers"; break;
- case E_BLOCK_FLOWER_POT: SaveInto = "FlowerPots"; break;
- case E_BLOCK_FURNACE: SaveInto = "Furnaces"; break;
- case E_BLOCK_SIGN_POST: SaveInto = "Signs"; break;
- case E_BLOCK_WALLSIGN: SaveInto = "Signs"; break;
- case E_BLOCK_NOTE_BLOCK: SaveInto = "Notes"; break;
- case E_BLOCK_JUKEBOX: SaveInto = "Jukeboxes"; break;
- case E_BLOCK_COMMAND_BLOCK: SaveInto = "CommandBlocks"; break;
- case E_BLOCK_HEAD: SaveInto = "MobHeads"; break;
-
- default:
- {
- ASSERT(!"Unhandled blocktype in BlockEntities list while saving to JSON");
- break;
- }
- } // switch (BlockEntity->GetBlockType())
- if (SaveInto == NULL)
- {
- return;
- }
-
- Json::Value val;
- a_BlockEntity->SaveToJson(val);
- m_Root[SaveInto].append(val);
- m_HasJsonData = true;
-}
-
-
-
-
-
-void cJsonChunkSerializer::LightIsValid(bool a_IsLightValid)
-{
- if (a_IsLightValid)
- {
- m_Root["IsLightValid"] = true;
- m_HasJsonData = true;
- }
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cWSSCompact:
-
-cWSSCompact::~cWSSCompact()
-{
- for (cPAKFiles::iterator itr = m_PAKFiles.begin(); itr != m_PAKFiles.end(); ++itr)
- {
- delete *itr;
- }
-}
-
-
-
-
-
-bool cWSSCompact::LoadChunk(const cChunkCoords & a_Chunk)
-{
- AString ChunkData;
- int UncompressedSize = 0;
- if (!GetChunkData(a_Chunk, UncompressedSize, ChunkData))
- {
- // The reason for failure is already printed in GetChunkData()
- return false;
- }
-
- return LoadChunkFromData(a_Chunk, UncompressedSize, ChunkData, m_World);
-}
-
-
-
-
-
-bool cWSSCompact::SaveChunk(const cChunkCoords & a_Chunk)
-{
- cCSLock Lock(m_CS);
-
- cPAKFile * f = LoadPAKFile(a_Chunk);
- if (f == NULL)
- {
- // For some reason we couldn't locate the file
- LOG("Cannot locate a proper PAK file for chunk [%d, %d]", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
- return false;
- }
- return f->SaveChunk(a_Chunk, m_World);
-}
-
-
-
-
-
-cWSSCompact::cPAKFile * cWSSCompact::LoadPAKFile(const cChunkCoords & a_Chunk)
-{
- // ASSUMES that m_CS has been locked
-
- // We need to retain this weird conversion code, because some edge chunks are in the wrong PAK file
- const int LayerX = FAST_FLOOR_DIV(a_Chunk.m_ChunkX, 32);
- const int LayerZ = FAST_FLOOR_DIV(a_Chunk.m_ChunkZ, 32);
-
- // Is it already cached?
- for (cPAKFiles::iterator itr = m_PAKFiles.begin(); itr != m_PAKFiles.end(); ++itr)
- {
- if (((*itr) != NULL) && ((*itr)->GetLayerX() == LayerX) && ((*itr)->GetLayerZ() == LayerZ))
- {
- // Move the file to front and return it:
- cPAKFile * f = *itr;
- if (itr != m_PAKFiles.begin())
- {
- m_PAKFiles.erase(itr);
- m_PAKFiles.push_front(f);
- }
- return f;
- }
- }
-
- // Load it anew:
- AString FileName;
- Printf(FileName, "%s/X%i_Z%i.pak", m_World->GetName().c_str(), LayerX, LayerZ);
- cPAKFile * f = new cPAKFile(FileName, LayerX, LayerZ, m_CompressionFactor);
- if (f == NULL)
- {
- return NULL;
- }
- m_PAKFiles.push_front(f);
-
- // If there are too many PAK files cached, delete the last one used:
- if (m_PAKFiles.size() > MAX_PAK_FILES)
- {
- delete m_PAKFiles.back();
- m_PAKFiles.pop_back();
- }
- return f;
-}
-
-
-
-
-
-bool cWSSCompact::GetChunkData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, AString & a_Data)
-{
- cCSLock Lock(m_CS);
- cPAKFile * f = LoadPAKFile(a_Chunk);
- if (f == NULL)
- {
- return false;
- }
- return f->GetChunkData(a_Chunk, a_UncompressedSize, a_Data);
-}
-
-
-
-
-
-/*
-// TODO: Rewrite saving to use the same principles as loading
-bool cWSSCompact::SetChunkData(const cChunkCoords & a_Chunk, int a_UncompressedSize, const AString & a_Data)
-{
- cCSLock Lock(m_CS);
- cPAKFile * f = LoadPAKFile(a_Chunk);
- if (f == NULL)
- {
- return false;
- }
- return f->SetChunkData(a_Chunk, a_UncompressedSize, a_Data);
-}
-*/
-
-
-
-
-
-bool cWSSCompact::EraseChunkData(const cChunkCoords & a_Chunk)
-{
- cCSLock Lock(m_CS);
- cPAKFile * f = LoadPAKFile(a_Chunk);
- if (f == NULL)
- {
- return false;
- }
- return f->EraseChunkData(a_Chunk);
-}
-
-
-
-
-
-void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities, cWorld * a_World)
-{
- // Load beacon:
- Json::Value AllBeacons = a_Value.get("Beacons", Json::nullValue);
- if (!AllBeacons.empty())
- {
- for (Json::Value::iterator itr = AllBeacons.begin(); itr != AllBeacons.end(); ++itr)
- {
- std::auto_ptr<cBeaconEntity> BeaconEntity(new cBeaconEntity(0, 0, 0, a_World));
- if (!BeaconEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING BEACON FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(BeaconEntity.release());
- }
- } // for itr - AllBeacons[]
- }
-
- // Load chests:
- Json::Value AllChests = a_Value.get("Chests", Json::nullValue);
- if (!AllChests.empty())
- {
- for (Json::Value::iterator itr = AllChests.begin(); itr != AllChests.end(); ++itr)
- {
- std::auto_ptr<cChestEntity> ChestEntity(new cChestEntity(0, 0, 0, a_World, E_BLOCK_CHEST));
- if (!ChestEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING CHEST FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(ChestEntity.release());
- }
- } // for itr - AllChests[]
- }
-
- // Load dispensers:
- Json::Value AllDispensers = a_Value.get("Dispensers", Json::nullValue);
- for (Json::Value::iterator itr = AllDispensers.begin(); itr != AllDispensers.end(); ++itr)
- {
- std::auto_ptr<cDispenserEntity> DispenserEntity(new cDispenserEntity(0, 0, 0, a_World));
- if (!DispenserEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING DISPENSER FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(DispenserEntity.release());
- }
- } // for itr - AllDispensers[]
-
- // Load Flowerpots:
- Json::Value AllFlowerPots = a_Value.get("FlowerPots", Json::nullValue);
- for (Json::Value::iterator itr = AllFlowerPots.begin(); itr != AllFlowerPots.end(); ++itr)
- {
- std::auto_ptr<cFlowerPotEntity> FlowerPotEntity(new cFlowerPotEntity(0, 0, 0, a_World));
- if (!FlowerPotEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING FLOWERPOT FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(FlowerPotEntity.release());
- }
- } // for itr - AllFlowerPots[]
-
- // Load furnaces:
- Json::Value AllFurnaces = a_Value.get("Furnaces", Json::nullValue);
- for (Json::Value::iterator itr = AllFurnaces.begin(); itr != AllFurnaces.end(); ++itr)
- {
- // TODO: The block type and meta aren't correct, there's no way to get them here
- std::auto_ptr<cFurnaceEntity> FurnaceEntity(new cFurnaceEntity(0, 0, 0, E_BLOCK_FURNACE, 0, a_World));
- if (!FurnaceEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING FURNACE FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(FurnaceEntity.release());
- }
- } // for itr - AllFurnaces[]
-
- // Load signs:
- Json::Value AllSigns = a_Value.get("Signs", Json::nullValue);
- for (Json::Value::iterator itr = AllSigns.begin(); itr != AllSigns.end(); ++itr)
- {
- std::auto_ptr<cSignEntity> SignEntity(new cSignEntity(E_BLOCK_SIGN_POST, 0, 0, 0, a_World));
- if (!SignEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING SIGN FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(SignEntity.release());
- }
- } // for itr - AllSigns[]
-
- // Load note blocks:
- Json::Value AllNotes = a_Value.get("Notes", Json::nullValue);
- for (Json::Value::iterator itr = AllNotes.begin(); itr != AllNotes.end(); ++itr)
- {
- std::auto_ptr<cNoteEntity> NoteEntity(new cNoteEntity(0, 0, 0, a_World));
- if (!NoteEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING NOTE BLOCK FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(NoteEntity.release());
- }
- } // for itr - AllNotes[]
-
- // Load jukeboxes:
- Json::Value AllJukeboxes = a_Value.get("Jukeboxes", Json::nullValue);
- for (Json::Value::iterator itr = AllJukeboxes.begin(); itr != AllJukeboxes.end(); ++itr)
- {
- std::auto_ptr<cJukeboxEntity> JukeboxEntity(new cJukeboxEntity(0, 0, 0, a_World));
- if (!JukeboxEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING JUKEBOX FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(JukeboxEntity.release());
- }
- } // for itr - AllJukeboxes[]
-
- // Load command blocks:
- Json::Value AllCommandBlocks = a_Value.get("CommandBlocks", Json::nullValue);
- for (Json::Value::iterator itr = AllCommandBlocks.begin(); itr != AllCommandBlocks.end(); ++itr)
- {
- std::auto_ptr<cCommandBlockEntity> CommandBlockEntity(new cCommandBlockEntity(0, 0, 0, a_World));
- if (!CommandBlockEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING COMMAND BLOCK FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(CommandBlockEntity.release());
- }
- } // for itr - AllCommandBlocks[]
-
- // Load mob heads:
- Json::Value AllMobHeads = a_Value.get("MobHeads", Json::nullValue);
- for (Json::Value::iterator itr = AllMobHeads.begin(); itr != AllMobHeads.end(); ++itr)
- {
- std::auto_ptr<cMobHeadEntity> MobHeadEntity(new cMobHeadEntity(0, 0, 0, a_World));
- if (!MobHeadEntity->LoadFromJson(*itr))
- {
- LOGWARNING("ERROR READING MOB HEAD FROM JSON!");
- }
- else
- {
- a_BlockEntities.push_back(MobHeadEntity.release());
- }
- } // for itr - AllMobHeads[]
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cWSSCompact::cPAKFile
-
-#define READ(Var) \
- if (f.Read(&Var, sizeof(Var)) != sizeof(Var)) \
- { \
- LOGERROR("ERROR READING %s FROM FILE %s (line %d); file offset %d", #Var, m_FileName.c_str(), __LINE__, f.Tell()); \
- return; \
- }
-
-cWSSCompact::cPAKFile::cPAKFile(const AString & a_FileName, int a_LayerX, int a_LayerZ, int a_CompressionFactor) :
- m_FileName(a_FileName),
- m_CompressionFactor(a_CompressionFactor),
- m_LayerX(a_LayerX),
- m_LayerZ(a_LayerZ),
- m_NumDirty(0),
- m_ChunkVersion( CHUNK_VERSION), // Init with latest version
- m_PakVersion( PAK_VERSION)
-{
- cFile f;
- if (!f.Open(m_FileName, cFile::fmRead))
- {
- return;
- }
-
- // Read headers:
- READ(m_PakVersion);
- if (m_PakVersion != 1)
- {
- LOGERROR("File \"%s\" is in an unknown pak format (%d)", m_FileName.c_str(), m_PakVersion);
- return;
- }
-
- READ(m_ChunkVersion);
- switch (m_ChunkVersion)
- {
- case 1:
- {
- m_ChunkSize.Set(16, 128, 16);
- break;
- }
- case 2:
- case 3:
- {
- m_ChunkSize.Set(16, 256, 16);
- break;
- }
- default:
- {
- LOGERROR("File \"%s\" is in an unknown chunk format (%d)", m_FileName.c_str(), m_ChunkVersion);
- return;
- }
- };
-
- short NumChunks = 0;
- READ(NumChunks);
-
- // Read chunk headers:
- for (int i = 0; i < NumChunks; i++)
- {
- sChunkHeader * Header = new sChunkHeader;
-
- // Here we do not use the READ macro, as it does not free the resources
- // allocated with new in case of error.
- if (f.Read(Header, sizeof(*Header)) != sizeof(*Header))
- {
- LOGERROR("ERROR READING %s FROM FILE %s (line %d); file offset %d", "Header", m_FileName.c_str(), __LINE__, f.Tell());
- delete Header;
- Header = NULL;
- return;
- }
- m_ChunkHeaders.push_back(Header);
- } // for i - chunk headers
-
- // Read chunk data:
- if (f.ReadRestOfFile(m_DataContents) == -1)
- {
- LOGERROR("Cannot read file \"%s\" contents", m_FileName.c_str());
- return;
- }
-
- if (m_ChunkVersion == 1) // Convert chunks to version 2
- {
- UpdateChunk1To2();
- }
-#if AXIS_ORDER == AXIS_ORDER_XZY
- if (m_ChunkVersion == 2) // Convert chunks to version 3
- {
- UpdateChunk2To3();
- }
-#endif
-}
-
-
-
-
-
-cWSSCompact::cPAKFile::~cPAKFile()
-{
- if (m_NumDirty > 0)
- {
- SynchronizeFile();
- }
- for (sChunkHeaders::iterator itr = m_ChunkHeaders.begin(); itr != m_ChunkHeaders.end(); ++itr)
- {
- delete *itr;
- }
-}
-
-
-
-
-
-bool cWSSCompact::cPAKFile::GetChunkData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, AString & a_Data)
-{
- int ChunkX = a_Chunk.m_ChunkX;
- int ChunkZ = a_Chunk.m_ChunkZ;
- sChunkHeader * Header = NULL;
- int Offset = 0;
- for (sChunkHeaders::iterator itr = m_ChunkHeaders.begin(); itr != m_ChunkHeaders.end(); ++itr)
- {
- if (((*itr)->m_ChunkX == ChunkX) && ((*itr)->m_ChunkZ == ChunkZ))
- {
- Header = *itr;
- break;
- }
- Offset += (*itr)->m_CompressedSize;
- }
- if ((Header == NULL) || (Offset + Header->m_CompressedSize > (int)m_DataContents.size()))
- {
- // Chunk not found / data invalid
- return false;
- }
-
- a_UncompressedSize = Header->m_UncompressedSize;
- a_Data.assign(m_DataContents, Offset, Header->m_CompressedSize);
- return true;
-}
-
-
-
-
-
-bool cWSSCompact::cPAKFile::SaveChunk(const cChunkCoords & a_Chunk, cWorld * a_World)
-{
- if (!SaveChunkToData(a_Chunk, a_World))
- {
- return false;
- }
- if (m_NumDirty > MAX_DIRTY_CHUNKS)
- {
- SynchronizeFile();
- }
- return true;
-}
-
-
-
-
-
-void cWSSCompact::cPAKFile::UpdateChunk1To2()
-{
- int Offset = 0;
- AString NewDataContents;
- int ChunksConverted = 0;
- for (sChunkHeaders::iterator itr = m_ChunkHeaders.begin(); itr != m_ChunkHeaders.end(); ++itr)
- {
- sChunkHeader * Header = *itr;
-
- if (ChunksConverted % 32 == 0)
- {
- LOGINFO("Updating \"%s\" version 1 to version 2: " SIZE_T_FMT " %%", m_FileName.c_str(), (ChunksConverted * 100) / m_ChunkHeaders.size());
- }
- ChunksConverted++;
-
- AString Data;
- int UncompressedSize = Header->m_UncompressedSize;
- Data.assign(m_DataContents, Offset, Header->m_CompressedSize);
- Offset += Header->m_CompressedSize;
-
- // Crude data integrity check:
- int ExpectedSize = (16*128*16)*2 + (16*128*16)/2; // For version 1
- if (UncompressedSize < ExpectedSize)
- {
- LOGWARNING("Chunk [%d, %d] has too short decompressed data (%d bytes out of %d needed), erasing",
- Header->m_ChunkX, Header->m_ChunkZ,
- UncompressedSize, ExpectedSize
- );
- Offset += Header->m_CompressedSize;
- continue;
- }
-
- // Decompress the data:
- AString UncompressedData;
- {
- int errorcode = UncompressString(Data.data(), Data.size(), UncompressedData, (size_t)UncompressedSize);
- if (errorcode != Z_OK)
- {
- LOGERROR("Error %d decompressing data for chunk [%d, %d]",
- errorcode,
- Header->m_ChunkX, Header->m_ChunkZ
- );
- Offset += Header->m_CompressedSize;
- continue;
- }
- }
-
- if (UncompressedSize != (int)UncompressedData.size())
- {
- LOGWARNING("Uncompressed data size differs (exp %d bytes, got " SIZE_T_FMT ") for chunk [%d, %d]",
- UncompressedSize, UncompressedData.size(),
- Header->m_ChunkX, Header->m_ChunkZ
- );
- Offset += Header->m_CompressedSize;
- continue;
- }
-
-
- // Old version is 128 blocks high with YZX axis order
- char ConvertedData[cChunkDef::BlockDataSize];
- int Index = 0;
- unsigned int InChunkOffset = 0;
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z)
- {
- for (int y = 0; y < 128; ++y)
- {
- ConvertedData[Index++] = UncompressedData[y + z * 128 + x * 128 * 16 + InChunkOffset];
- }
- // Add 128 empty blocks after an old y column
- memset(ConvertedData + Index, E_BLOCK_AIR, 128);
- Index += 128;
- }
- InChunkOffset += (16 * 128 * 16);
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) // Metadata
- {
- for (int y = 0; y < 64; ++y)
- {
- ConvertedData[Index++] = UncompressedData[y + z * 64 + x * 64 * 16 + InChunkOffset];
- }
- memset(ConvertedData + Index, 0, 64);
- Index += 64;
- }
- InChunkOffset += (16 * 128 * 16) / 2;
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) // Block light
- {
- for (int y = 0; y < 64; ++y)
- {
- ConvertedData[Index++] = UncompressedData[y + z * 64 + x * 64 * 16 + InChunkOffset];
- }
- memset(ConvertedData + Index, 0, 64);
- Index += 64;
- }
- InChunkOffset += (16*128*16)/2;
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) // Sky light
- {
- for (int y = 0; y < 64; ++y)
- {
- ConvertedData[Index++] = UncompressedData[y + z * 64 + x * 64 * 16 + InChunkOffset];
- }
- memset(ConvertedData + Index, 0, 64);
- Index += 64;
- }
- InChunkOffset += (16 * 128 * 16) / 2;
-
- AString Converted(ConvertedData, ARRAYCOUNT(ConvertedData));
-
- // Add JSON data afterwards
- if (UncompressedData.size() > InChunkOffset)
- {
- Converted.append( UncompressedData.begin() + InChunkOffset, UncompressedData.end());
- }
-
- // Re-compress data
- AString CompressedData;
- {
- int errorcode = CompressString(Converted.data(), Converted.size(), CompressedData, m_CompressionFactor);
- if (errorcode != Z_OK)
- {
- LOGERROR("Error %d compressing data for chunk [%d, %d]",
- errorcode,
- Header->m_ChunkX, Header->m_ChunkZ
- );
- continue;
- }
- }
-
- // Save into file's cache
- Header->m_UncompressedSize = (int)Converted.size();
- Header->m_CompressedSize = (int)CompressedData.size();
- NewDataContents.append(CompressedData);
- }
-
- // Done converting
- m_DataContents = NewDataContents;
- m_ChunkVersion = 2;
- SynchronizeFile();
-
- LOGINFO("Updated \"%s\" version 1 to version 2", m_FileName.c_str());
-}
-
-
-
-
-
-void cWSSCompact::cPAKFile::UpdateChunk2To3()
-{
- int Offset = 0;
- AString NewDataContents;
- int ChunksConverted = 0;
- for (sChunkHeaders::iterator itr = m_ChunkHeaders.begin(); itr != m_ChunkHeaders.end(); ++itr)
- {
- sChunkHeader * Header = *itr;
-
- if (ChunksConverted % 32 == 0)
- {
- LOGINFO("Updating \"%s\" version 2 to version 3: " SIZE_T_FMT " %%", m_FileName.c_str(), (ChunksConverted * 100) / m_ChunkHeaders.size());
- }
- ChunksConverted++;
-
- AString Data;
- int UncompressedSize = Header->m_UncompressedSize;
- Data.assign(m_DataContents, Offset, Header->m_CompressedSize);
- Offset += Header->m_CompressedSize;
-
- // Crude data integrity check:
- const int ExpectedSize = (16 * 256 * 16) * 2 + (16 * 256 * 16) / 2; // For version 2
- if (UncompressedSize < ExpectedSize)
- {
- LOGWARNING("Chunk [%d, %d] has too short decompressed data (%d bytes out of %d needed), erasing",
- Header->m_ChunkX, Header->m_ChunkZ,
- UncompressedSize, ExpectedSize
- );
- Offset += Header->m_CompressedSize;
- continue;
- }
-
- // Decompress the data:
- AString UncompressedData;
- {
- int errorcode = UncompressString(Data.data(), Data.size(), UncompressedData, (size_t)UncompressedSize);
- if (errorcode != Z_OK)
- {
- LOGERROR("Error %d decompressing data for chunk [%d, %d]",
- errorcode,
- Header->m_ChunkX, Header->m_ChunkZ
- );
- Offset += Header->m_CompressedSize;
- continue;
- }
- }
-
- if (UncompressedSize != (int)UncompressedData.size())
- {
- LOGWARNING("Uncompressed data size differs (exp %d bytes, got " SIZE_T_FMT ") for chunk [%d, %d]",
- UncompressedSize, UncompressedData.size(),
- Header->m_ChunkX, Header->m_ChunkZ
- );
- Offset += Header->m_CompressedSize;
- continue;
- }
-
- char ConvertedData[ExpectedSize];
- memset(ConvertedData, 0, ExpectedSize);
-
- // Cannot use cChunk::MakeIndex because it might change again?????????
- // For compatibility, use what we know is current
- #define MAKE_3_INDEX( x, y, z) ( x + (z * 16) + (y * 16 * 16))
-
- unsigned int InChunkOffset = 0;
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y) // YZX Loop order is important, in 1.1 Y was first then Z then X
- {
- ConvertedData[ MAKE_3_INDEX(x, y, z) ] = UncompressedData[InChunkOffset];
- ++InChunkOffset;
- } // for y, z, x
-
-
- unsigned int index2 = 0;
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y)
- {
- ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4)) & 0x0f) << ((x&1)*4);
- ++index2;
- }
- InChunkOffset += index2 / 2;
- index2 = 0;
-
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y)
- {
- ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4)) & 0x0f) << ((x&1)*4);
- ++index2;
- }
- InChunkOffset += index2 / 2;
- index2 = 0;
-
- for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y)
- {
- ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4)) & 0x0f) << ((x&1)*4);
- ++index2;
- }
- InChunkOffset += index2 / 2;
-
- AString Converted(ConvertedData, ExpectedSize);
-
- // Add JSON data afterwards
- if (UncompressedData.size() > InChunkOffset)
- {
- Converted.append( UncompressedData.begin() + InChunkOffset, UncompressedData.end());
- }
-
- // Re-compress data
- AString CompressedData;
- {
- int errorcode = CompressString(Converted.data(), Converted.size(), CompressedData, m_CompressionFactor);
- if (errorcode != Z_OK)
- {
- LOGERROR("Error %d compressing data for chunk [%d, %d]",
- errorcode,
- Header->m_ChunkX, Header->m_ChunkZ
- );
- continue;
- }
- }
-
- // Save into file's cache
- Header->m_UncompressedSize = (int)Converted.size();
- Header->m_CompressedSize = (int)CompressedData.size();
- NewDataContents.append(CompressedData);
- }
-
- // Done converting
- m_DataContents = NewDataContents;
- m_ChunkVersion = 3;
- SynchronizeFile();
-
- LOGINFO("Updated \"%s\" version 2 to version 3", m_FileName.c_str());
-}
-
-
-
-
-
-bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_UncompressedSize, const AString & a_Data, cWorld * a_World)
-{
- // Crude data integrity check:
- if (a_UncompressedSize < cChunkDef::BlockDataSize)
- {
- LOGWARNING("Chunk [%d, %d] has too short decompressed data (%d bytes out of %d needed), erasing",
- a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
- a_UncompressedSize, cChunkDef::BlockDataSize
- );
- EraseChunkData(a_Chunk);
- return false;
- }
-
- // Decompress the data:
- AString UncompressedData;
- int errorcode = UncompressString(a_Data.data(), a_Data.size(), UncompressedData, (size_t)a_UncompressedSize);
- if (errorcode != Z_OK)
- {
- LOGERROR("Error %d decompressing data for chunk [%d, %d]",
- errorcode,
- a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ
- );
- return false;
- }
-
- if (a_UncompressedSize != (int)UncompressedData.size())
- {
- LOGWARNING("Uncompressed data size differs (exp %d bytes, got " SIZE_T_FMT ") for chunk [%d, %d]",
- a_UncompressedSize, UncompressedData.size(),
- a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ
- );
- return false;
- }
-
- cEntityList Entities;
- cBlockEntityList BlockEntities;
- bool IsLightValid = false;
-
- if (a_UncompressedSize > cChunkDef::BlockDataSize)
- {
- Json::Value root; // will contain the root value after parsing.
- Json::Reader reader;
- if (!reader.parse( UncompressedData.data() + cChunkDef::BlockDataSize, root, false))
- {
- LOGERROR("Failed to parse trailing JSON in chunk [%d, %d]!",
- a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ
- );
- }
- else
- {
- LoadEntitiesFromJson(root, Entities, BlockEntities, a_World);
- IsLightValid = root.get("IsLightValid", false).asBool();
- }
- }
-
- BLOCKTYPE * BlockData = (BLOCKTYPE *)UncompressedData.data();
- NIBBLETYPE * MetaData = (NIBBLETYPE *)(BlockData + MetaOffset);
- NIBBLETYPE * BlockLight = (NIBBLETYPE *)(BlockData + LightOffset);
- NIBBLETYPE * SkyLight = (NIBBLETYPE *)(BlockData + SkyLightOffset);
-
- a_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
- a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
- BlockData, MetaData,
- IsLightValid ? BlockLight : NULL,
- IsLightValid ? SkyLight : NULL,
- NULL, NULL,
- Entities, BlockEntities,
- false
- )));
-
- return true;
-}
-
-
-
-
-
-bool cWSSCompact::cPAKFile::EraseChunkData(const cChunkCoords & a_Chunk)
-{
- int ChunkX = a_Chunk.m_ChunkX;
- int ChunkZ = a_Chunk.m_ChunkZ;
- int Offset = 0;
- for (sChunkHeaders::iterator itr = m_ChunkHeaders.begin(); itr != m_ChunkHeaders.end(); ++itr)
- {
- if (((*itr)->m_ChunkX == ChunkX) && ((*itr)->m_ChunkZ == ChunkZ))
- {
- m_DataContents.erase(Offset, (*itr)->m_CompressedSize);
- delete *itr;
- itr = m_ChunkHeaders.erase(itr);
- return true;
- }
- Offset += (*itr)->m_CompressedSize;
- }
-
- return false;
-}
-
-
-
-
-
-bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld * a_World)
-{
- // Serialize the chunk:
- cJsonChunkSerializer Serializer;
- if (!a_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Serializer))
- {
- // Chunk not valid
- LOG("cWSSCompact: Trying to save chunk [%d, %d] that has no data, ignoring request.", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
- return false;
- }
-
- AString Data;
- Data.assign((const char *)Serializer.GetBlockData(), cChunkDef::BlockDataSize);
- if (Serializer.HasJsonData())
- {
- AString JsonData;
- Json::StyledWriter writer;
- JsonData = writer.write(Serializer.GetRoot());
- Data.append(JsonData);
- }
-
- // Compress the data:
- AString CompressedData;
- int errorcode = CompressString(Data.data(), Data.size(), CompressedData, m_CompressionFactor);
- if (errorcode != Z_OK)
- {
- LOGERROR("Error %i compressing data for chunk [%d, %d]", errorcode, a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
- return false;
- }
-
- // Erase any existing data for the chunk:
- EraseChunkData(a_Chunk);
-
- // Save the header:
- sChunkHeader * Header = new sChunkHeader;
- if (Header == NULL)
- {
- LOGWARNING("Cannot create a new chunk header to save chunk [%d, %d]", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
- return false;
- }
- Header->m_CompressedSize = (int)CompressedData.size();
- Header->m_ChunkX = a_Chunk.m_ChunkX;
- Header->m_ChunkZ = a_Chunk.m_ChunkZ;
- Header->m_UncompressedSize = (int)Data.size();
- m_ChunkHeaders.push_back(Header);
-
- m_DataContents.append(CompressedData.data(), CompressedData.size());
-
- m_NumDirty++;
- return true;
-}
-
-
-
-
-
-#define WRITE(Var) \
- if (f.Write(&Var, sizeof(Var)) != sizeof(Var)) \
- { \
- LOGERROR("cWSSCompact: ERROR writing %s to file \"%s\" (line %d); file offset %d", #Var, m_FileName.c_str(), __LINE__, f.Tell()); \
- return; \
- }
-
-void cWSSCompact::cPAKFile::SynchronizeFile(void)
-{
- cFile f;
- if (!f.Open(m_FileName, cFile::fmWrite))
- {
- LOGERROR("Cannot open PAK file \"%s\" for writing", m_FileName.c_str());
- return;
- }
-
- WRITE(m_PakVersion);
- WRITE(m_ChunkVersion);
- short NumChunks = (short)m_ChunkHeaders.size();
- WRITE(NumChunks);
- for (sChunkHeaders::iterator itr = m_ChunkHeaders.begin(); itr != m_ChunkHeaders.end(); ++itr)
- {
- WRITE(**itr);
- }
- if (f.Write(m_DataContents.data(), m_DataContents.size()) != (int)m_DataContents.size())
- {
- LOGERROR("cWSSCompact: ERROR writing chunk contents to file \"%s\" (line %d); file offset %d", m_FileName.c_str(), __LINE__, f.Tell());
- return;
- }
- m_NumDirty = 0;
-}
-
-
-
-
diff --git a/src/WorldStorage/WSSCompact.h b/src/WorldStorage/WSSCompact.h
deleted file mode 100644
index 83e9cb49f..000000000
--- a/src/WorldStorage/WSSCompact.h
+++ /dev/null
@@ -1,157 +0,0 @@
-
-// WSSCompact.h
-
-// Interfaces to the cWSSCompact class representing the "Compact" storage schema (PAK-files)
-
-
-
-
-
-#pragma once
-#ifndef WSSCOMPACT_H_INCLUDED
-#define WSSCOMPACT_H_INCLUDED
-
-#include "WorldStorage.h"
-#include "../Vector3.h"
-#include "json/json.h"
-#include "ChunkDataCallback.h"
-
-
-
-
-
-/// Helper class for serializing a chunk into Json
-class cJsonChunkSerializer :
- public cChunkDataArrayCollector
-{
-public:
-
- cJsonChunkSerializer(void);
-
- Json::Value & GetRoot (void) {return m_Root; }
- BLOCKTYPE * GetBlockData(void) {return (BLOCKTYPE *)m_BlockData; }
- bool HasJsonData (void) const {return m_HasJsonData; }
-
-protected:
-
- // NOTE: block data is serialized into inherited cChunkDataCollector's m_BlockData[] array
-
- // Entities and BlockEntities are serialized to Json
- Json::Value m_Root;
- bool m_HasJsonData;
-
- // cChunkDataCollector overrides:
- virtual void Entity (cEntity * a_Entity) override;
- virtual void BlockEntity (cBlockEntity * a_Entity) override;
- virtual void LightIsValid (bool a_IsLightValid) override;
-} ;
-
-
-
-
-
-class cWSSCompact :
- public cWSSchema
-{
-public:
- cWSSCompact(cWorld * a_World, int a_CompressionFactor) : cWSSchema(a_World), m_CompressionFactor(a_CompressionFactor) {}
- virtual ~cWSSCompact();
-
-protected:
-
- enum
- {
- // Offsets to individual components in the joined blockdata array
- MetaOffset = cChunkDef::NumBlocks,
- LightOffset = MetaOffset + cChunkDef::NumBlocks / 2,
- SkyLightOffset = LightOffset + cChunkDef::NumBlocks / 2,
- } ;
-
- struct sChunkHeader;
- typedef std::vector<sChunkHeader *> sChunkHeaders;
-
- /// Implements a cache for a single PAK file; implements lazy-write in order to be able to write multiple chunks fast
- class cPAKFile
- {
- public:
-
- cPAKFile(const AString & a_FileName, int a_LayerX, int a_LayerZ, int a_CompressionFactor);
- ~cPAKFile();
-
- bool GetChunkData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, AString & a_Data);
- bool SetChunkData(const cChunkCoords & a_Chunk, int a_UncompressedSize, const AString & a_Data);
- bool EraseChunkData(const cChunkCoords & a_Chunk);
-
- bool SaveChunk(const cChunkCoords & a_Chunk, cWorld * a_World);
-
- int GetLayerX(void) const {return m_LayerX; }
- int GetLayerZ(void) const {return m_LayerZ; }
-
- static const int PAK_VERSION = 1;
-#if AXIS_ORDER == AXIS_ORDER_XZY
- static const int CHUNK_VERSION = 3;
-#elif AXIS_ORDER == AXIS_ORDER_YZX
- static const int CHUNK_VERSION = 2;
-#endif
- protected:
-
- AString m_FileName;
- int m_CompressionFactor;
- int m_LayerX;
- int m_LayerZ;
-
- sChunkHeaders m_ChunkHeaders;
- AString m_DataContents; // Data contents of the file, cached
-
- int m_NumDirty; // Number of chunks that were written into m_DataContents but not into the file
-
- Vector3i m_ChunkSize; // Is related to m_ChunkVersion
- char m_ChunkVersion;
- char m_PakVersion;
-
- bool SaveChunkToData(const cChunkCoords & a_Chunk, cWorld * a_World); // Saves the chunk to m_DataContents, updates headers and m_NumDirty
- void SynchronizeFile(void); // Writes m_DataContents along with the headers to file, resets m_NumDirty
-
- void UpdateChunk1To2(void); // Height from 128 to 256
- void UpdateChunk2To3(void); // Axis order from YZX to XZY
- } ;
-
- typedef std::list<cPAKFile *> cPAKFiles;
-
- cCriticalSection m_CS;
- cPAKFiles m_PAKFiles; // A MRU cache of PAK files
-
- int m_CompressionFactor;
-
- /// Loads the correct PAK file either from cache or from disk, manages the m_PAKFiles cache
- cPAKFile * LoadPAKFile(const cChunkCoords & a_Chunk);
-
- /// Gets chunk data from the correct file; locks CS as needed
- bool GetChunkData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, AString & a_Data);
-
- /// Sets chunk data to the correct file; locks CS as needed
- bool SetChunkData(const cChunkCoords & a_Chunk, int a_UncompressedSize, const AString & a_Data);
-
- /// Erases chunk data from the correct file; locks CS as needed
- bool EraseChunkData(const cChunkCoords & a_Chunk);
-
- /// Loads the chunk from the data (no locking needed)
- bool LoadChunkFromData(const cChunkCoords & a_Chunk, int a_UncompressedSize, const AString & a_Data, cWorld * a_World);
-
- void LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities, cWorld * a_World);
-
- // cWSSchema overrides:
- virtual bool LoadChunk(const cChunkCoords & a_Chunk) override;
- virtual bool SaveChunk(const cChunkCoords & a_Chunk) override;
- virtual const AString GetName(void) const override {return "compact"; }
-} ;
-
-
-
-
-
-#endif // WSSCOMPACT_H_INCLUDED
-
-
-
-
diff --git a/src/WorldStorage/WorldStorage.cpp b/src/WorldStorage/WorldStorage.cpp
index 179cf9393..c611bfd90 100644
--- a/src/WorldStorage/WorldStorage.cpp
+++ b/src/WorldStorage/WorldStorage.cpp
@@ -7,7 +7,6 @@
#include "Globals.h"
#include "WorldStorage.h"
-#include "WSSCompact.h"
#include "WSSAnvil.h"
#include "../World.h"
#include "../Generating/ChunkGenerator.h"
@@ -187,7 +186,6 @@ void cWorldStorage::InitSchemas(int a_StorageCompressionFactor)
{
// The first schema added is considered the default
m_Schemas.push_back(new cWSSAnvil (m_World, a_StorageCompressionFactor));
- m_Schemas.push_back(new cWSSCompact (m_World, a_StorageCompressionFactor));
m_Schemas.push_back(new cWSSForgetful(m_World));
// Add new schemas here