1
0

Merge pull request #1269 from Howaner/BlockEntitys

Added beacon.
This commit is contained in:
Mattes D 2014-08-01 17:43:02 +02:00
commit 35cfbfd51a
28 changed files with 903 additions and 49 deletions

View File

@ -2244,6 +2244,7 @@ end
DigBlock = { Params = "X, Y, Z", Return = "", Notes = "Replaces the specified block with air, without dropping the usual pickups for the block. Wakes up the simulators for the block and its neighbors." },
DoExplosionAt = { Params = "Force, X, Y, Z, CanCauseFire, Source, SourceData", Return = "", Notes = "Creates an explosion of the specified relative force in the specified position. If CanCauseFire is set, the explosion will set blocks on fire, too. The Source parameter specifies the source of the explosion, one of the esXXX constants. The SourceData parameter is specific to each source type, usually it provides more info about the source." },
DoWithBlockEntityAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a block entity at the specified coords, calls the CallbackFunction with the {{cBlockEntity}} parameter representing the block entity. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBlockEntity|BlockEntity}}, [CallbackData])</pre> The function returns false if there is no block entity, or if there is, it returns the bool value that the callback has returned. Use {{tolua}}.cast() to cast the Callback's BlockEntity parameter to the correct {{cBlockEntity}} descendant." },
DoWithBeaconAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a beacon at the specified coords, calls the CallbackFunction with the {{cBeaconEntity}} parameter representing the beacon. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBeaconEntity|BeaconEntity}}, [CallbackData])</pre> The function returns false if there is no beacon, or if there is, it returns the bool value that the callback has returned." },
DoWithChestAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a chest at the specified coords, calls the CallbackFunction with the {{cChestEntity}} parameter representing the chest. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cChestEntity|ChestEntity}}, [CallbackData])</pre> The function returns false if there is no chest, or if there is, it returns the bool value that the callback has returned." },
DoWithCommandBlockAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a command block at the specified coords, calls the CallbackFunction with the {{cCommandBlockEntity}} parameter representing the command block. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cCommandBlockEntity|CommandBlockEntity}}, [CallbackData])</pre> The function returns false if there is no command block, or if there is, it returns the bool value that the callback has returned." },
DoWithDispenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dispenser at the specified coords, calls the CallbackFunction with the {{cDispenserEntity}} parameter representing the dispenser. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cDispenserEntity|DispenserEntity}}, [CallbackData])</pre> The function returns false if there is no dispenser, or if there is, it returns the bool value that the callback has returned." },

View File

@ -50,6 +50,32 @@ return
},
},
cBeaconEntity =
{
Desc = [[
A beacon entity is a {{cBlockEntityWithItems|cBlockEntityWithItems}} descendant that represents a beacon
in the world.
]],
Inherits = "cBlockEntityWithItems",
Functions =
{
IsActive = { Params = "", Return = "bool", Notes = "Is the beacon active?" },
GetBeaconLevel = { Params = "", Return = "number", Notes = "Returns the beacon level. (0 - 4)" },
GetPrimaryEffect = { Params = "", Return = "EffectType", Notes = "Returns the primary effect." },
GetSecondaryEffect = { Params = "", Return = "EffectType", Notes = "Returns the secondary effect." },
SetPrimaryEffect = { Params = "EffectType", Return = "bool", Notes = "Select the primary effect. Returns false when the effect is invalid." },
SetSecondaryEffect = { Params = "EffectType", Return = "bool", Notes = "Select the secondary effect. Returns false when the effect is invalid." },
CalculatePyramidLevel = { Params = "", Return = "number", Notes = "Calculate the amount of layers the pyramid below the beacon has." },
IsBeaconBlocked = { Params = "", Return = "bool", Notes = "Is the beacon blocked by non-transparent blocks that are higher than the beacon?" },
UpdateBeacon = { Params = "", Return = "", Notes = "Update the beacon." },
GiveEffects = { Params = "", Return = "", Notes = "Give the near-players the effects." },
IsMineralBlock = { Params = "BLOCKTYPE", Return = "bool", Notes = "Returns true if the block is a diamond block, a golden block, an iron block or an emerald block." },
IsValidEffect = { Params = "EffectType", Return = "bool", Notes = "Returns true if the effect can be used." },
},
},
cChestEntity =
{
Desc = [[

View File

@ -47,6 +47,7 @@ $cfile "../Inventory.h"
$cfile "../Enchantments.h"
$cfile "../Item.h"
$cfile "../ItemGrid.h"
$cfile "../BlockEntities/BeaconEntity.h"
$cfile "../BlockEntities/BlockEntity.h"
$cfile "../BlockEntities/BlockEntityWithItems.h"
$cfile "../BlockEntities/ChestEntity.h"

View File

@ -53,6 +53,7 @@ set(BINDING_DEPENDENCIES
../Bindings/WebPlugin.h
../BiomeDef.h
../BlockArea.h
../BlockEntities/BeaconEntity.h
../BlockEntities/BlockEntity.h
../BlockEntities/BlockEntityWithItems.h
../BlockEntities/ChestEntity.h

View File

@ -16,6 +16,7 @@
#include "../WebAdmin.h"
#include "../ClientHandle.h"
#include "../BlockArea.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/DispenserEntity.h"
@ -2996,6 +2997,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_beginmodule(tolua_S, "cWorld");
tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
tolua_function(tolua_S, "DoWithBlockEntityAt", tolua_DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
tolua_function(tolua_S, "DoWithBeaconAt", tolua_DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>);
tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>);
tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ<cWorld, cDropSpenserEntity, &cWorld::DoWithDropSpenserAt>);

View File

@ -3,33 +3,31 @@
#include "BeaconEntity.h"
#include "../BlockArea.h"
#include "../Entities/Player.h"
cBeaconEntity::cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_BEACON, a_BlockX, a_BlockY, a_BlockZ, a_World)
cBeaconEntity::cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
: super(E_BLOCK_BEACON, a_BlockX, a_BlockY, a_BlockZ, 1, 1, a_World)
, m_IsActive(false)
, m_BeaconLevel(0)
, m_PrimaryEffect(cEntityEffect::effNoEffect)
, m_SecondaryEffect(cEntityEffect::effNoEffect)
{
UpdateBeacon();
}
int cBeaconEntity::GetPyramidLevel(void)
char cBeaconEntity::CalculatePyramidLevel(void)
{
cBlockArea Area;
int MinY = GetPosY() - 4;
if (MinY < 0)
{
MinY = 0;
}
int MaxY = GetPosY() - 1;
if (MaxY < 0)
{
MaxY = 0;
}
int MinY = std::max(GetPosY() - 4, 0);
int MaxY = std::max(GetPosY() - 1, 0);
Area.Read(
m_World,
@ -42,7 +40,7 @@ int cBeaconEntity::GetPyramidLevel(void)
int Layer = 1;
int MiddleXZ = 4;
for (int Y = Area.GetSizeY() - 1; Y > 0; Y--)
for (int Y = (Area.GetSizeY() - 1); Y >= 0; Y--)
{
for (int X = MiddleXZ - Layer; X <= (MiddleXZ + Layer); X++)
{
@ -50,14 +48,97 @@ int cBeaconEntity::GetPyramidLevel(void)
{
if (!IsMineralBlock(Area.GetRelBlockType(X, Y, Z)))
{
return Layer - 1;
return (Layer - 1);
}
}
}
Layer++;
}
return Layer - 1;
return (Layer - 1);
}
bool cBeaconEntity::IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel)
{
switch (a_Effect)
{
case cEntityEffect::effRegeneration: return (a_BeaconLevel >= 4);
case cEntityEffect::effStrength: return (a_BeaconLevel >= 3);
case cEntityEffect::effResistance: return (a_BeaconLevel >= 2);
case cEntityEffect::effJumpBoost: return (a_BeaconLevel >= 2);
case cEntityEffect::effSpeed: return (a_BeaconLevel >= 1);
case cEntityEffect::effHaste: return (a_BeaconLevel >= 1);
case cEntityEffect::effNoEffect: return true;
default:
{
LOGD("%s: Invalid beacon effect: %d", __FUNCTION__, (int)a_Effect);
return false;
}
}
}
bool cBeaconEntity::SetPrimaryEffect(cEntityEffect::eType a_Effect)
{
if (!IsValidEffect(a_Effect, m_BeaconLevel))
{
return false;
}
m_PrimaryEffect = a_Effect;
// Send window update:
if (GetWindow() != NULL)
{
GetWindow()->SetProperty(1, m_PrimaryEffect);
}
return true;
}
bool cBeaconEntity::SetSecondaryEffect(cEntityEffect::eType a_Effect)
{
if (!IsValidEffect(a_Effect, m_BeaconLevel))
{
return false;
}
m_SecondaryEffect = a_Effect;
// Send window update:
if (GetWindow() != NULL)
{
GetWindow()->SetProperty(2, m_SecondaryEffect);
}
return true;
}
bool cBeaconEntity::IsBeaconBlocked(void)
{
for (int Y = m_PosY; Y < cChunkDef::Height; ++Y)
{
BLOCKTYPE Block = m_World->GetBlock(m_PosX, Y, m_PosZ);
if (!cBlockInfo::IsTransparent(Block))
{
return true;
}
}
return false;
}
@ -83,24 +164,114 @@ bool cBeaconEntity::IsMineralBlock(BLOCKTYPE a_BlockType)
bool cBeaconEntity::Tick(float a_Dt, cChunk & a_Chunk)
void cBeaconEntity::UpdateBeacon(void)
{
int OldBeaconLevel = m_BeaconLevel;
if (IsBeaconBlocked())
{
m_IsActive = false;
m_BeaconLevel = 0;
}
else
{
m_BeaconLevel = CalculatePyramidLevel();
m_IsActive = (m_BeaconLevel > 0);
}
if (m_BeaconLevel != OldBeaconLevel)
{
// Send window update:
if (GetWindow() != NULL)
{
GetWindow()->SetProperty(0, m_BeaconLevel);
}
}
// TODO: Add achievement
}
void cBeaconEntity::GiveEffects(void)
{
if (!m_IsActive || (m_BeaconLevel < 0))
{
return;
}
int Radius = m_BeaconLevel * 10 + 10;
short EffectLevel = 0;
if ((m_BeaconLevel >= 4) && (m_PrimaryEffect == m_SecondaryEffect))
{
EffectLevel = 1;
}
cEntityEffect::eType SecondaryEffect = cEntityEffect::effNoEffect;
if ((m_BeaconLevel >= 4) && (m_PrimaryEffect != m_SecondaryEffect) && (m_SecondaryEffect > 0))
{
SecondaryEffect = m_SecondaryEffect;
}
class cPlayerCallback : public cPlayerListCallback
{
int m_Radius;
int m_PosX, m_PosY, m_PosZ;
cEntityEffect::eType m_PrimaryEffect, m_SecondaryEffect;
short m_EffectLevel;
virtual bool Item(cPlayer * a_Player)
{
Vector3d PlayerPosition = Vector3d(a_Player->GetPosition());
if (PlayerPosition.y > (double)m_PosY)
{
PlayerPosition.y = (double)m_PosY;
}
// TODO: Vanilla minecraft uses an AABB check instead of a radius one
Vector3d BeaconPosition = Vector3d(m_PosX, m_PosY, m_PosZ);
if ((PlayerPosition - BeaconPosition).Length() <= m_Radius)
{
a_Player->AddEntityEffect(m_PrimaryEffect, 180, m_EffectLevel);
if (m_SecondaryEffect != cEntityEffect::effNoEffect)
{
a_Player->AddEntityEffect(m_SecondaryEffect, 180, 0);
}
}
return false;
}
public:
cPlayerCallback(int a_Radius, int a_PosX, int a_PosY, int a_PosZ, cEntityEffect::eType a_PrimaryEffect, cEntityEffect::eType a_SecondaryEffect, short a_EffectLevel)
: m_Radius(a_Radius)
, m_PosX(a_PosX)
, m_PosY(a_PosY)
, m_PosZ(a_PosZ)
, m_PrimaryEffect(a_PrimaryEffect)
, m_SecondaryEffect(a_SecondaryEffect)
, m_EffectLevel(a_EffectLevel)
{};
void cBeaconEntity::SaveToJson(Json::Value& a_Value)
{
} PlayerCallback(Radius, m_PosX, m_PosY, m_PosZ, m_PrimaryEffect, SecondaryEffect, EffectLevel);
GetWorld()->ForEachPlayer(PlayerCallback);
}
void cBeaconEntity::SendTo(cClientHandle & a_Client)
bool cBeaconEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
// Update the beacon every 4 seconds
if ((GetWorld()->GetWorldAge() % 80) == 0)
{
UpdateBeacon();
GiveEffects();
}
return false;
}
@ -109,6 +280,92 @@ void cBeaconEntity::SendTo(cClientHandle & a_Client)
void cBeaconEntity::UsedBy(cPlayer * a_Player)
{
cWindow * Window = GetWindow();
if (Window == NULL)
{
OpenWindow(new cBeaconWindow(m_PosX, m_PosY, m_PosZ, this));
Window = GetWindow();
}
if (Window != NULL)
{
// if (a_Player->GetWindow() != Window)
// -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ...
{
a_Player->OpenWindow(Window);
}
}
}
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);
}

View File

@ -1,7 +1,14 @@
// BeaconEntity.h
// Declares the cBeaconEntity class representing a single beacon in the world
#pragma once
#include "BlockEntity.h"
#include "BlockEntityWithItems.h"
@ -16,28 +23,70 @@ namespace Json
// tolua_begin
class cBeaconEntity :
public cBlockEntity
public cBlockEntityWithItems
{
typedef cBlockEntity super;
typedef cBlockEntityWithItems super;
public:
// tolua_end
/** The initial constructor */
cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
/** Returns the amount of layers the pyramid below the beacon has. */
int GetPyramidLevel(void);
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;
/** Modify the beacon level. (It is needed to load the beacon corectly) */
void SetBeaconLevel(char a_Level) { m_BeaconLevel = a_Level; }
// tolua_begin
/** Is the beacon active? */
bool IsActive(void) const { return m_IsActive; }
/** Returns the beacon level. (0 - 4) */
char GetBeaconLevel(void) const { return m_BeaconLevel; }
cEntityEffect::eType GetPrimaryEffect(void) const { return m_PrimaryEffect; }
cEntityEffect::eType GetSecondaryEffect(void) const { return m_SecondaryEffect; }
/** Sets the primary effect. Returns false when the effect is invalid. */
bool SetPrimaryEffect(cEntityEffect::eType a_Effect);
/** Sets the secondary effect. Returns false when the effect is invalid. */
bool SetSecondaryEffect(cEntityEffect::eType a_Effect);
/** Calculate the amount of layers the pyramid below the beacon has. */
char CalculatePyramidLevel(void);
/** Is the beacon blocked by non-transparent blocks that are higher than the beacon? */
bool IsBeaconBlocked(void);
/** Update the beacon. */
void UpdateBeacon(void);
/** Give the near-players the effects. */
void GiveEffects(void);
/** Returns true if the block is a diamond block, a golden block, an iron block or an emerald block. */
static bool IsMineralBlock(BLOCKTYPE a_BlockType);
// cBlockEntity overrides:
virtual void SaveToJson(Json::Value& a_Value) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual void UsedBy(cPlayer * a_Player) override;
virtual bool Tick(float a_Dt, cChunk & /* a_Chunk */) override;
} ;
/** Returns true if the effect can be used. */
static bool IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel);
// tolua_end
protected:
bool m_IsActive;
char m_BeaconLevel;
cEntityEffect::eType m_PrimaryEffect, m_SecondaryEffect;
} ; // tolua_export

View File

@ -1,7 +1,7 @@
// FlowerPotEntity.cpp
// Implements the cFlowerPotEntity class representing a single sign in the world
// Implements the cFlowerPotEntity class representing a single flower pot in the world
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "json/json.h"

View File

@ -181,6 +181,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
case E_BLOCK_BEACON: return new cBlockEntityHandler (a_BlockType);
case E_BLOCK_BED: return new cBlockBedHandler (a_BlockType);
case E_BLOCK_BIG_FLOWER: return new cBlockBigFlowerHandler (a_BlockType);
case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);

View File

@ -94,6 +94,7 @@ private:
switch (a_BlockType)
{
case E_BLOCK_ANVIL:
case E_BLOCK_BEACON:
case E_BLOCK_BEDROCK:
case E_BLOCK_BREWING_STAND:
case E_BLOCK_CHEST:

View File

@ -11,6 +11,7 @@
#include "Server.h"
#include "zlib/zlib.h"
#include "Defines.h"
#include "BlockEntities/BeaconEntity.h"
#include "BlockEntities/ChestEntity.h"
#include "BlockEntities/DispenserEntity.h"
#include "BlockEntities/DropperEntity.h"
@ -2126,6 +2127,38 @@ bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBloc
bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
{
// The blockentity list is locked by the parent chunkmap's CS
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
{
++itr2;
if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
{
continue;
}
if ((*itr)->GetBlockType() != E_BLOCK_BEACON)
{
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
return false;
}
// The correct block entity is here
if (a_Callback.Item((cBeaconEntity *)*itr))
{
return false;
}
return true;
} // for itr - m_BlockEntitites[]
// Not found:
return false;
}
bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
{
// The blockentity list is locked by the parent chunkmap's CS

View File

@ -28,6 +28,7 @@ class cServer;
class MTRand;
class cPlayer;
class cChunkMap;
class cBeaconEntity;
class cChestEntity;
class cDispenserEntity;
class cFurnaceEntity;
@ -45,6 +46,7 @@ class cMobSpawner;
typedef std::list<cClientHandle *> cClientHandleList;
typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
@ -236,6 +238,9 @@ public:
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible

View File

@ -1839,6 +1839,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
}
case E_BLOCK_OBSIDIAN:
case E_BLOCK_BEACON:
case E_BLOCK_BEDROCK:
case E_BLOCK_WATER:
case E_BLOCK_LAVA:
@ -2115,6 +2116,24 @@ bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cB
bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
{
int ChunkX, ChunkZ;
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
}
return Chunk->DoWithBeaconAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
{
int ChunkX, ChunkZ;

View File

@ -19,6 +19,7 @@ class MTRand;
class cChunkStay;
class cChunk;
class cPlayer;
class cBeaconEntity;
class cChestEntity;
class cDispenserEntity;
class cDropperEntity;
@ -40,6 +41,7 @@ typedef std::list<cClientHandle *> cClientHandleList;
typedef cChunk * cChunkPtr;
typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cDropperEntity> cDropperCallback;
@ -234,6 +236,9 @@ public:
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible

View File

@ -7,6 +7,7 @@
#include "Bindings/PluginManager.h"
#include "Entities/Player.h"
#include "Inventory.h"
#include "BlockEntities/BeaconEntity.h"
#include "BlockEntities/ChestEntity.h"
#include "BlockEntities/CommandBlockEntity.h"
#include "BlockEntities/SignEntity.h"
@ -659,6 +660,10 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
// Client <-> Server branding exchange
SendPluginMessage("MC|Brand", "MCServer");
}
else if (a_Channel == "MC|Beacon")
{
HandleBeaconSelection(a_Message.c_str(), a_Message.size());
}
else if (a_Channel == "MC|ItemName")
{
HandleAnvilItemName(a_Message.c_str(), a_Message.size());
@ -746,6 +751,55 @@ void cClientHandle::UnregisterPluginChannels(const AStringVector & a_ChannelList
void cClientHandle::HandleBeaconSelection(const char * a_Data, size_t a_Length)
{
if (a_Length < 14)
{
SendChat("Failure setting beacon selection; bad request", mtFailure);
LOGD("Malformed MC|Beacon packet.");
return;
}
cWindow * Window = m_Player->GetWindow();
if ((Window == NULL) || (Window->GetWindowType() != cWindow::wtBeacon))
{
return;
}
cBeaconWindow * BeaconWindow = (cBeaconWindow *) Window;
if (Window->GetSlot(*m_Player, 0)->IsEmpty())
{
return;
}
cByteBuffer Buffer(a_Length);
Buffer.Write(a_Data, a_Length);
int PrimaryEffectID, SecondaryEffectID;
Buffer.ReadBEInt(PrimaryEffectID);
Buffer.ReadBEInt(SecondaryEffectID);
cEntityEffect::eType PrimaryEffect = cEntityEffect::effNoEffect;
if ((PrimaryEffectID >= 0) && (PrimaryEffectID <= (int)cEntityEffect::effSaturation))
{
PrimaryEffect = (cEntityEffect::eType)PrimaryEffectID;
}
cEntityEffect::eType SecondaryEffect = cEntityEffect::effNoEffect;
if ((SecondaryEffectID >= 0) && (SecondaryEffectID <= (int)cEntityEffect::effSaturation))
{
SecondaryEffect = (cEntityEffect::eType)SecondaryEffectID;
}
Window->SetSlot(*m_Player, 0, cItem());
BeaconWindow->GetBeaconEntity()->SetPrimaryEffect(PrimaryEffect);
BeaconWindow->GetBeaconEntity()->SetSecondaryEffect(SecondaryEffect);
}
void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Length)
{
if (a_Length < 14)

View File

@ -400,6 +400,9 @@ private:
/** Removes all of the channels from the list of current plugin channels. Ignores channels that are not found. */
void UnregisterPluginChannels(const AStringVector & a_ChannelList);
/** Handles the "MC|Beacon" plugin message */
void HandleBeaconSelection(const char * a_Data, size_t a_Length);
/** Handles the "MC|AdvCdm" plugin message */
void HandleCommandBlockMessage(const char * a_Data, size_t a_Length);

View File

@ -37,6 +37,7 @@ Implements the 1.7.x protocol classes:
#include "../Mobs/IncludeAllMonsters.h"
#include "../UI/Window.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
@ -1328,6 +1329,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
{
case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity
case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
@ -2581,6 +2583,19 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
switch (a_BlockEntity.GetBlockType())
{
case E_BLOCK_BEACON:
{
cBeaconEntity & BeaconEntity = (cBeaconEntity &)a_BlockEntity;
Writer.AddInt("x", BeaconEntity.GetPosX());
Writer.AddInt("y", BeaconEntity.GetPosY());
Writer.AddInt("z", BeaconEntity.GetPosZ());
Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect());
Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect());
Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel());
Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
break;
}
case E_BLOCK_COMMAND_BLOCK:
{
cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;

View File

@ -5,6 +5,7 @@
#include "Globals.h"
#include "SlotArea.h"
#include "../Entities/Player.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
@ -1190,6 +1191,200 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaBeacon:
cSlotAreaBeacon::cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow) :
cSlotArea(1, a_ParentWindow),
m_Beacon(a_Beacon)
{
m_Beacon->GetContents().AddListener(*this);
}
cSlotAreaBeacon::~cSlotAreaBeacon()
{
m_Beacon->GetContents().RemoveListener(*this);
}
bool cSlotAreaBeacon::IsPlaceableItem(short a_ItemType)
{
switch (a_ItemType)
{
case E_ITEM_EMERALD:
case E_ITEM_DIAMOND:
case E_ITEM_GOLD:
case E_ITEM_IRON:
{
return true;
}
}
return false;
}
void cSlotAreaBeacon::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
{
ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots()));
bool bAsync = false;
if (GetSlot(a_SlotNum, a_Player) == NULL)
{
LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum);
return;
}
switch (a_ClickAction)
{
case caShiftLeftClick:
case caShiftRightClick:
{
ShiftClicked(a_Player, a_SlotNum, a_ClickedItem);
return;
}
case caMiddleClick:
{
MiddleClicked(a_Player, a_SlotNum);
return;
}
case caDropKey:
case caCtrlDropKey:
{
DropClicked(a_Player, a_SlotNum, false);
return;
}
case caNumber1:
case caNumber2:
case caNumber3:
case caNumber4:
case caNumber5:
case caNumber6:
case caNumber7:
case caNumber8:
case caNumber9:
{
NumberClicked(a_Player, a_SlotNum, a_ClickAction);
return;
}
default:
{
break;
}
}
cItem Slot(*GetSlot(a_SlotNum, a_Player));
if (!Slot.IsSameType(a_ClickedItem))
{
LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots);
LOGWARNING("My item: %s", ItemToFullString(Slot).c_str());
LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str());
bAsync = true;
}
cItem & DraggingItem = a_Player.GetDraggingItem();
if (DraggingItem.IsEmpty())
{
DraggingItem = Slot;
Slot.Empty();
}
else if (Slot.IsEmpty())
{
if (!IsPlaceableItem(DraggingItem.m_ItemType))
{
return;
}
Slot = DraggingItem.CopyOne();
DraggingItem.m_ItemCount -= 1;
if (DraggingItem.m_ItemCount <= 0)
{
DraggingItem.Empty();
}
}
else if (DraggingItem.m_ItemCount == 1)
{
if (!IsPlaceableItem(DraggingItem.m_ItemCount))
{
return;
}
// Switch contents
cItem tmp(DraggingItem);
DraggingItem = Slot;
Slot = tmp;
}
SetSlot(a_SlotNum, a_Player, Slot);
if (bAsync)
{
m_ParentWindow.BroadcastWholeWindow();
}
}
void cSlotAreaBeacon::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
{
const cItem * Slot = GetSlot(0, a_Player);
if (!Slot->IsEmpty() || !IsPlaceableItem(a_ItemStack.m_ItemType) || (a_ItemStack.m_ItemCount != 1))
{
return;
}
if (a_ShouldApply)
{
SetSlot(0, a_Player, a_ItemStack.CopyOne());
}
a_ItemStack.Empty();
}
const cItem * cSlotAreaBeacon::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
UNUSED(a_Player);
return &(m_Beacon->GetSlot(a_SlotNum));
}
void cSlotAreaBeacon::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
{
UNUSED(a_Player);
m_Beacon->SetSlot(a_SlotNum, a_Item);
}
void cSlotAreaBeacon::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
{
UNUSED(a_SlotNum);
// Something has changed in the window, broadcast the entire window to all clients
ASSERT(a_ItemGrid == &(m_Beacon->GetContents()));
m_ParentWindow.BroadcastWholeWindow();
}
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnchanting:

View File

@ -15,6 +15,7 @@
class cWindow;
class cPlayer;
class cBeaconEntity;
class cChestEntity;
class cDropSpenserEntity;
class cEnderChestEntity;
@ -314,6 +315,34 @@ protected:
class cSlotAreaBeacon :
public cSlotArea,
public cItemGrid::cListener
{
typedef cSlotArea super;
public:
cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow);
virtual ~cSlotAreaBeacon();
bool IsPlaceableItem(short a_ItemType);
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
protected:
cBeaconEntity * m_Beacon;
// cItemGrid::cListener overrides:
virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
} ;
class cSlotAreaEnchanting :
public cSlotAreaTemporary
{

View File

@ -9,6 +9,7 @@
#include "../Entities/Pickup.h"
#include "../Inventory.h"
#include "../Items/ItemHandler.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
@ -840,6 +841,36 @@ void cAnvilWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
////////////////////////////////////////////////////////////////////////////////
// cBeaconWindow:
cBeaconWindow::cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon) :
cWindow(wtBeacon, "Beacon"),
m_Beacon(a_Beacon)
{
m_ShouldDistributeToHotbarFirst = true;
m_SlotAreas.push_back(new cSlotAreaBeacon(m_Beacon, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cBeaconWindow::OpenedByPlayer(cPlayer & a_Player)
{
super::OpenedByPlayer(a_Player);
a_Player.GetClientHandle()->SendWindowProperty(*this, 0, m_Beacon->GetBeaconLevel());
a_Player.GetClientHandle()->SendWindowProperty(*this, 1, m_Beacon->GetPrimaryEffect());
a_Player.GetClientHandle()->SendWindowProperty(*this, 2, m_Beacon->GetSecondaryEffect());
}
////////////////////////////////////////////////////////////////////////////////
// cEnchantingWindow:

View File

@ -23,6 +23,7 @@ class cDropSpenserEntity;
class cEnderChestEntity;
class cFurnaceEntity;
class cHopperEntity;
class cBeaconEntity;
class cSlotArea;
class cSlotAreaAnvil;
class cWorld;
@ -258,6 +259,26 @@ protected:
class cBeaconWindow :
public cWindow
{
typedef cWindow super;
public:
cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon);
cBeaconEntity * GetBeaconEntity(void) const { return m_Beacon; }
// cWindow Overrides:
virtual void OpenedByPlayer(cPlayer & a_Player) override;
protected:
cBeaconEntity * m_Beacon;
} ;
class cEnchantingWindow :
public cWindow
{

View File

@ -25,6 +25,7 @@
#include "Entities/TNTEntity.h"
#include "BlockEntities/CommandBlockEntity.h"
#include "BlockEntities/BeaconEntity.h"
// Simulators:
#include "Simulator/SimulatorManager.h"
@ -1232,6 +1233,15 @@ bool cWorld::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBloc
bool cWorld::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback& a_Callback)
{
return m_ChunkMap->DoWithBeaconAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
{
return m_ChunkMap->DoWithChestAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);

View File

@ -41,6 +41,7 @@ class cEntity;
class cBlockEntity;
class cWorldGenerator; // The generator that actually generates the chunks for a single world
class cChunkGenerator; // The thread responsible for generating chunks
class cBeaconEntity;
class cChestEntity;
class cDispenserEntity;
class cFlowerPotEntity;
@ -59,6 +60,7 @@ typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs;
typedef cItemCallback<cPlayer> cPlayerListCallback;
typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
@ -523,6 +525,9 @@ public:
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) override; // Exported in ManualBindings.cpp
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Exported in ManualBindings.cpp
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp

View File

@ -10,6 +10,7 @@
#include "../StringCompression.h"
#include "FastNBT.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/DispenserEntity.h"
@ -176,6 +177,23 @@ void cNBTChunkSerializer::AddBasicTileEntity(cBlockEntity * a_Entity, const char
void cNBTChunkSerializer::AddBeaconEntity(cBeaconEntity * a_Entity)
{
m_Writer.BeginCompound("");
AddBasicTileEntity(a_Entity, "Beacon");
m_Writer.AddInt("Levels", a_Entity->GetBeaconLevel());
m_Writer.AddInt("Primary", (int)a_Entity->GetPrimaryEffect());
m_Writer.AddInt("Secondary", (int)a_Entity->GetSecondaryEffect());
m_Writer.BeginList("Items", TAG_Compound);
AddItemGrid(a_Entity->GetContents());
m_Writer.EndList();
m_Writer.EndCompound();
}
void cNBTChunkSerializer::AddChestEntity(cChestEntity * a_Entity, BLOCKTYPE a_ChestType)
{
m_Writer.BeginCompound("");
@ -825,6 +843,7 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity)
// Add tile-entity into NBT:
switch (a_Entity->GetBlockType())
{
case E_BLOCK_BEACON: AddBeaconEntity ((cBeaconEntity *) a_Entity); break;
case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity, a_Entity->GetBlockType()); break;
case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *)a_Entity); break;
case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break;

View File

@ -20,6 +20,7 @@ class cFastNBTWriter;
class cEntity;
class cBlockEntity;
class cBoat;
class cBeaconEntity;
class cChestEntity;
class cCommandBlockEntity;
class cDispenserEntity;
@ -93,6 +94,7 @@ protected:
// Block entities:
void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID);
void AddBeaconEntity (cBeaconEntity * a_Entity);
void AddChestEntity (cChestEntity * a_Entity, BLOCKTYPE a_ChestType);
void AddDispenserEntity(cDispenserEntity * a_Entity);
void AddDropperEntity (cDropperEntity * a_Entity);

View File

@ -16,6 +16,7 @@
#include "../StringCompression.h"
#include "../SetChunkData.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/DispenserEntity.h"
@ -582,7 +583,11 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
{
continue;
}
if (strncmp(a_NBT.GetData(sID), "Chest", a_NBT.GetDataLength(sID)) == 0)
if (strncmp(a_NBT.GetData(sID), "Beacon", a_NBT.GetDataLength(sID)) == 0)
{
LoadBeaconFromNBT(a_BlockEntities, a_NBT, Child);
}
else if (strncmp(a_NBT.GetData(sID), "Chest", a_NBT.GetDataLength(sID)) == 0)
{
LoadChestFromNBT(a_BlockEntities, a_NBT, Child, E_BLOCK_CHEST);
}
@ -746,6 +751,49 @@ void cWSSAnvil::LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a
void cWSSAnvil::LoadBeaconFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
{
ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
int x, y, z;
if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
{
return;
}
std::auto_ptr<cBeaconEntity> Beacon(new cBeaconEntity(x, y, z, m_World));
int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Levels");
if (CurrentLine >= 0)
{
Beacon->SetBeaconLevel((char)a_NBT.GetInt(CurrentLine));
}
CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Primary");
if (CurrentLine >= 0)
{
Beacon->SetPrimaryEffect((cEntityEffect::eType)a_NBT.GetInt(CurrentLine));
}
CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Secondary");
if (CurrentLine >= 0)
{
Beacon->SetSecondaryEffect((cEntityEffect::eType)a_NBT.GetInt(CurrentLine));
}
// We are better than mojang, we load/save the beacon inventory!
int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
if ((Items >= 0) && (a_NBT.GetType(Items) == TAG_List))
{
LoadItemGridFromNBT(Beacon->GetContents(), a_NBT, Items);
}
a_BlockEntities.push_back(Beacon.release());
}
void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType)
{
ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);

View File

@ -133,6 +133,7 @@ protected:
*/
void LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int s_SlotOffset = 0);
void LoadBeaconFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType);
void LoadDispenserFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadDropperFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);

View File

@ -9,6 +9,7 @@
#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"
@ -75,6 +76,7 @@ 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;
@ -268,6 +270,24 @@ bool cWSSCompact::EraseChunkData(const cChunkCoords & 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())