diff --git a/CMake/GenerateBindings.cmake b/CMake/GenerateBindings.cmake index 7c0913ad5..6d702a778 100644 --- a/CMake/GenerateBindings.cmake +++ b/CMake/GenerateBindings.cmake @@ -46,6 +46,7 @@ function(enable_bindings_generation) Entities/ArrowEntity.h Entities/Entity.h Entities/ExpOrb.h + Entities/EnderCrystal.h Entities/EntityEffect.h Entities/ExpBottleEntity.h Entities/FallingBlock.h diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index fb74d8032..3b46577de 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -5061,8 +5061,8 @@ cFile:DeleteFile("/usr/bin/virus.exe"); { Returns = { - Name = "BitePosition", - Type = "Vector3d", + Name = "BitePosition", + Type = "Vector3d", }, Notes = "Returns the position of the floater just before a fish bites. If a fish hasn't bitten the floater, this function returns the position the floater was cast from.", }, @@ -8900,16 +8900,16 @@ a_Player:OpenWindow(Window); ]], Functions = { - BurnsInDaylight = - { - Returns = - { - { - Type = "boolean", - }, - }, - Notes = "Returns whether the mob burns in daylight.", - }, + BurnsInDaylight = + { + Returns = + { + { + Type = "boolean", + }, + }, + Notes = "Returns whether the mob burns in daylight.", + }, CanBeLeashed = { Returns = @@ -9539,6 +9539,79 @@ a_Player:OpenWindow(Window); }, Inherits = "cEntity", }, + cEnderCrystal = + { + Desc = [[ + This class represents an ender crystal. This entity can be spawned by using {{cWorld#SpawnEnderCrystal_1|cWorld:SpawnEnderCrystal}}. + ]], + Functions = + { + DisplaysBeam = + { + Returns = + { + { + Type = "boolean", + }, + Notes = "Returns true if the ender crystal displays its beam.", + }, + }, + GetBeamTarget = + { + Returns = + { + { + Type = "Vector3i", + }, + }, + Notes = "Returns the Block position the beam is pointing to.", + }, + SetBeamTarget = + { + Params = + { + { + Name = "BeamTarget", + Type = "Vector3i", + }, + }, + Notes = "Sets the target of the beam of this ender crystal.", + }, + SetDisplayBeam = + { + Params = + { + { + Name = "DisplaysBeam", + Type = "boolean", + }, + Notes = "Sets if the ender crystal should display its beam.", + }, + }, + SetShowBottom = + { + Params = + { + { + Name = "ShowsBottom", + Type = "boolean", + }, + Notes = "Sets if the ender crystal should broadcast its bedrock base.", + }, + }, + ShowsBottom = + { + Returns = + { + { + Type = "boolean", + }, + Notes = "Returns true if the bedrock base is displayed.", + }, + }, + }, + Inherits = "cEntity", + }, cExpOrb = { Desc = [[ diff --git a/Server/Plugins/APIDump/Classes/World.lua b/Server/Plugins/APIDump/Classes/World.lua index 50db080a8..2f5d0b8f2 100644 --- a/Server/Plugins/APIDump/Classes/World.lua +++ b/Server/Plugins/APIDump/Classes/World.lua @@ -3317,7 +3317,7 @@ function OnAllChunksAvailable() All return values from the callbacks are i { Name = "ShowBottom", Type = "boolean", - } + }, }, Returns = { diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg index 919d70e18..dc25ca379 100644 --- a/src/Bindings/AllToLua.pkg +++ b/src/Bindings/AllToLua.pkg @@ -74,6 +74,8 @@ $cfile "../UUID.h" // Entities: $cfile "../Entities/Entity.h" + +$cfile "../Entities/EnderCrystal.h" $cfile "../Entities/Boat.h" $cfile "../Entities/Pawn.h" $cfile "../Entities/ProjectileEntity.h" diff --git a/src/Bindings/CheckBindingsDependencies.lua b/src/Bindings/CheckBindingsDependencies.lua index 50e915311..8e5d68db8 100644 --- a/src/Bindings/CheckBindingsDependencies.lua +++ b/src/Bindings/CheckBindingsDependencies.lua @@ -99,7 +99,7 @@ local cmakeFiles = getCMakeListsFiles() local numMissingFiles = 0 for _, fnam in ipairs(pkgFiles) do if not(cmakeFiles[fnam]) then - io.stderr:write("Bindings dependency file ", fnam, " is not listed in src/Bindings/CMakeLists.txt\n") + io.stderr:write("Bindings dependency file ", fnam, " is not listed in CMake/GenerateBindings.cmake\n") numMissingFiles = numMissingFiles + 1 end end diff --git a/src/Entities/EnderCrystal.cpp b/src/Entities/EnderCrystal.cpp index 269714b58..4c21a794d 100644 --- a/src/Entities/EnderCrystal.cpp +++ b/src/Entities/EnderCrystal.cpp @@ -10,8 +10,19 @@ -cEnderCrystal::cEnderCrystal(Vector3d a_Pos, bool a_ShowBottom): +cEnderCrystal::cEnderCrystal(Vector3d a_Pos, bool a_ShowBottom) : + cEnderCrystal(a_Pos, {}, false, a_ShowBottom) +{ +} + + + + + +cEnderCrystal::cEnderCrystal(Vector3d a_Pos, Vector3i a_BeamTarget, bool a_DisplayBeam, bool a_ShowBottom) : Super(etEnderCrystal, a_Pos, 1.0, 1.0), + m_BeamTarget(a_BeamTarget), + m_DisplayBeam(a_DisplayBeam), m_ShowBottom(a_ShowBottom) { SetMaxHealth(5); @@ -21,9 +32,40 @@ cEnderCrystal::cEnderCrystal(Vector3d a_Pos, bool a_ShowBottom): +void cEnderCrystal::SetShowBottom(bool a_ShowBottom) +{ + m_ShowBottom = a_ShowBottom; + m_World->BroadcastEntityMetadata(*this); +} + + + + + +void cEnderCrystal::SetBeamTarget(Vector3i a_BeamTarget) +{ + m_BeamTarget = a_BeamTarget; + m_World->BroadcastEntityMetadata(*this); +} + + + + + +void cEnderCrystal::SetDisplayBeam(bool a_DisplayBeam) +{ + m_DisplayBeam = a_DisplayBeam; + m_World->BroadcastEntityMetadata(*this); +} + + + + + void cEnderCrystal::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnEntity(*this); + a_ClientHandle.SendEntityMetadata(*this); } @@ -33,10 +75,9 @@ void cEnderCrystal::SpawnOn(cClientHandle & a_ClientHandle) void cEnderCrystal::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); - // No further processing (physics e.t.c.) is needed - if (m_World->GetDimension() == dimEnd) + if ((m_World->GetDimension() == dimEnd) && (m_World->GetBlock(POS_TOINT) != E_BLOCK_FIRE)) { - m_World->SetBlock(POS_TOINT.addedY(1), E_BLOCK_FIRE, 0); + m_World->SetBlock(POS_TOINT, E_BLOCK_FIRE, 0); } } @@ -48,11 +89,11 @@ void cEnderCrystal::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); - m_World->DoExplosionAt(6.0, GetPosX(), GetPosY(), GetPosZ(), true, esEnderCrystal, this); + m_World->DoExplosionAt(6.0, GetPosX(), GetPosY() + (GetHeight() / 2.0), GetPosZ(), true, esEnderCrystal, this); Destroy(); - m_World->SetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT, E_BLOCK_FIRE, 0); + m_World->SetBlock(POS_TOINT, E_BLOCK_FIRE, 0); } diff --git a/src/Entities/EnderCrystal.h b/src/Entities/EnderCrystal.h index b2a28c517..7e783ffd2 100644 --- a/src/Entities/EnderCrystal.h +++ b/src/Entities/EnderCrystal.h @@ -19,26 +19,30 @@ public: CLASS_PROTODEF(cEnderCrystal) cEnderCrystal(Vector3d a_Pos, bool a_ShowBottom); + cEnderCrystal(Vector3d a_Pos, Vector3i a_BeamTarget, bool a_DisplayBeam, bool a_ShowBottom); - // Getters and Setters - bool ShowsBottom() const { return m_ShowBottom; } - void SetShowBottom(bool a_ShowBottom) { m_ShowBottom = a_ShowBottom; } + // tolua_begin Vector3i GetBeamTarget() const { return m_BeamTarget; } - void SetBeamTarget(Vector3i a_BeamTarget) { m_BeamTarget = a_BeamTarget; } + void SetBeamTarget(Vector3i a_BeamTarget); - /** If the EnderCrystal should send it's beam to the client and store to disk. */ + /** If the EnderCrystal should send it's beam to the client and save it. */ bool DisplaysBeam() const { return m_DisplayBeam; } - void SetDisplayBeam(bool a_DisplayBeam) { m_DisplayBeam = a_DisplayBeam; } + void SetDisplayBeam(bool a_DisplayBeam); + + bool ShowsBottom() const { return m_ShowBottom; } + void SetShowBottom(bool a_ShowBottom); + + // tolua_end private: - // If the bedrock base should be displayed - bool m_ShowBottom; - Vector3i m_BeamTarget; bool m_DisplayBeam; + // If the bedrock base should be displayed. + bool m_ShowBottom; + // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index 1887e32a6..c72cebaaf 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -167,7 +167,8 @@ public: !a_Entity.IsPlayer() || static_cast(a_Entity).IsGameModeSpectator() ) && - !a_Entity.IsBoat() + !a_Entity.IsBoat() && + !a_Entity.IsEnderCrystal() ) { // Not an entity that interacts with a projectile diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp index d1b48c11a..6a39589e3 100644 --- a/src/Protocol/Protocol_1_10.cpp +++ b/src/Protocol/Protocol_1_10.cpp @@ -543,14 +543,14 @@ void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); - a_Pkt.WriteBEUInt8(7); + a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_BEAM_TARGET); a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); if (EnderCrystal.DisplaysBeam()) { a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } - a_Pkt.WriteBEUInt8(8); + a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_SHOW_BOTTOM); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp index 9ea6332b8..d475bd005 100644 --- a/src/Protocol/Protocol_1_11.cpp +++ b/src/Protocol/Protocol_1_11.cpp @@ -809,14 +809,14 @@ void cProtocol_1_11_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); - a_Pkt.WriteBEUInt8(7); - a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); - a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); if (EnderCrystal.DisplaysBeam()) { + a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_BEAM_TARGET); + a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); + a_Pkt.WriteBool(true); // Dont do a second check if it should display the beam a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } - a_Pkt.WriteBEUInt8(8); + a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_SHOW_BOTTOM); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp index ee2016ae2..4e0d2b063 100644 --- a/src/Protocol/Protocol_1_12.cpp +++ b/src/Protocol/Protocol_1_12.cpp @@ -522,14 +522,14 @@ void cProtocol_1_12::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); - a_Pkt.WriteBEUInt8(7); - a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); - a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); if (EnderCrystal.DisplaysBeam()) { + a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_BEAM_TARGET); + a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); + a_Pkt.WriteBool(true); // Dont do a second check if it should display the beam a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } - a_Pkt.WriteBEUInt8(8); + a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_SHOW_BOTTOM); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp index efc1e9fc1..a61c094f4 100644 --- a/src/Protocol/Protocol_1_13.cpp +++ b/src/Protocol/Protocol_1_13.cpp @@ -891,10 +891,10 @@ void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); - WriteEntityMetadata(a_Pkt, EntityMetadata::EnderCrystalBeamTarget, EntityMetadataType::OptPosition); - a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); if (EnderCrystal.DisplaysBeam()) { + WriteEntityMetadata(a_Pkt, EntityMetadata::EnderCrystalBeamTarget, EntityMetadataType::OptPosition); + a_Pkt.WriteBool(true); // Dont do a second check if it should display the beam a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } WriteEntityMetadata(a_Pkt, EntityMetadata::EnderCrystalShowBottom, EntityMetadataType::Boolean); diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 778d4ca30..eff9c8530 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -1731,14 +1731,14 @@ void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); - a_Pkt.WriteBEUInt8(7); + a_Pkt.WriteBEUInt8(5); a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); if (EnderCrystal.DisplaysBeam()) { a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } - a_Pkt.WriteBEUInt8(8); + a_Pkt.WriteBEUInt8(6); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; diff --git a/src/World.h b/src/World.h index 7460dc624..490ab59b4 100644 --- a/src/World.h +++ b/src/World.h @@ -654,7 +654,7 @@ public: /** Spawns a new ender crystal at the specified block coords. Returns the UniqueID of the created entity, or cEntity::INVALID_ID on failure. */ - UInt32 SpawnEnderCrystal(Vector3d a_Pos, bool a_ShowBottom = false); + UInt32 SpawnEnderCrystal(Vector3d a_Pos, bool a_ShowBottom); // tolua_end diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index c7b4c7e1f..cfea33737 100755 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1718,19 +1718,14 @@ void cWSSAnvil::LoadBoatFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N void cWSSAnvil::LoadEnderCrystalFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { - auto EnderCrystal = std::make_unique(Vector3d(), false); - if (!LoadEntityBaseFromNBT(*EnderCrystal.get(), a_NBT, a_TagIdx)) - { - return; - } - + bool DisplayBeam = false, ShowBottom = false; + Vector3i BeamTarget; int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "BeamTarget"); if (CurrentLine > 0) { - EnderCrystal->SetDisplayBeam(true); + DisplayBeam = true; if (a_NBT.GetType(CurrentLine) == TAG_Compound) { - Vector3d BeamTarget = {0, 0, 0}; int CoordinateLine = a_NBT.FindChildByName(CurrentLine, "X"); if (CoordinateLine > 0) { @@ -1751,7 +1746,13 @@ void cWSSAnvil::LoadEnderCrystalFromNBT(cEntityList & a_Entities, const cParsedN CurrentLine = a_NBT.FindChildByName(a_TagIdx, "ShowBottom"); if (CurrentLine > 0) { - EnderCrystal->SetShowBottom(a_NBT.GetByte(CurrentLine) == 1); + ShowBottom = a_NBT.GetByte(CurrentLine) == 1; + } + + auto EnderCrystal = std::make_unique(Vector3d(), BeamTarget, DisplayBeam, ShowBottom); + if (!LoadEntityBaseFromNBT(*EnderCrystal.get(), a_NBT, a_TagIdx)) + { + return; } a_Entities.emplace_back(std::move(EnderCrystal));