From 7c4cb9a3852e33d8bcc5f8283485e833c6eab93e Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 1 Sep 2014 20:12:56 +0200 Subject: Added CustomName to cMonster. --- src/Entities/Pawn.cpp | 9 ++++++--- src/Mobs/Monster.cpp | 29 +++++++++++++++++++++++++++++ src/Mobs/Monster.h | 20 +++++++++++++++++++- src/Protocol/Protocol17x.cpp | 10 ++++++++++ 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp index fe6c24a7a..fc8ca3d47 100644 --- a/src/Entities/Pawn.cpp +++ b/src/Entities/Pawn.cpp @@ -9,9 +9,9 @@ -cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height): - super(a_EntityType, 0, 0, 0, a_Width, a_Height), - m_EntityEffects(tEffectMap()) +cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height) : + super(a_EntityType, 0, 0, 0, a_Width, a_Height) + , m_EntityEffects(tEffectMap()) { } @@ -111,3 +111,6 @@ void cPawn::ClearEntityEffects() RemoveEntityEffect(EffectType); } } + + + diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index f7ee0b0c0..6a477ca1c 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -75,6 +75,8 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString , m_IdleInterval(0) , m_DestroyTimer(0) , m_MobType(a_MobType) + , m_CustomName("") + , m_CustomNameAlwaysVisible(false) , m_SoundHurt(a_SoundHurt) , m_SoundDeath(a_SoundDeath) , m_AttackRate(3) @@ -679,6 +681,33 @@ void cMonster::InStateEscaping(float a_Dt) +void cMonster::SetCustomName(const AString & a_CustomName) +{ + m_CustomName = a_CustomName; + + // The maximal length is 64 + if (a_CustomName.length() > 64) + { + m_CustomName = a_CustomName.substr(0, 64); + } + + m_World->BroadcastEntityMetadata(*this); +} + + + + + +void cMonster::SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible) +{ + m_CustomNameAlwaysVisible = a_CustomNameAlwaysVisible; + m_World->BroadcastEntityMetadata(*this); +} + + + + + void cMonster::GetMonsterConfig(const AString & a_Name) { cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name); diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index cdbd26c09..ce4e36a46 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -144,7 +144,23 @@ public: virtual bool IsSitting (void) const { return false; } // tolua_begin - + + /** Returns true if the monster has a custom name. */ + bool HasCustomName(void) const { return !m_CustomName.empty(); } + + /** Gets the custom name of the monster. If no custom name is set, the function returns a empty string. */ + const AString & GetCustomName(void) const { return m_CustomName; } + + /** Sets the custom name of the monster. You see the name over the monster. */ + void SetCustomName(const AString & a_CustomName); + + /** Is the custom name of this monster always visible? If not, you only see the name when you sight the mob. */ + bool IsCustomNameAlwaysVisible(void) const { return m_CustomNameAlwaysVisible; } + + /** Sets the custom name visiblity of this monster. + If false, you only see the name when you sight the mob. If true, you always see the custom name. */ + void SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible); + /// Translates MobType enum to a string, empty string if unknown static AString MobTypeToString(eType a_MobType); @@ -228,6 +244,8 @@ protected: float m_DestroyTimer; eType m_MobType; + AString m_CustomName; + bool m_CustomNameAlwaysVisible; AString m_SoundHurt; AString m_SoundDeath; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 1091b877f..ed9812377 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1,3 +1,4 @@ + // Protocol17x.cpp /* @@ -3021,6 +3022,15 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) break; } } // switch (a_Mob.GetType()) + + // Custom name: + if (a_Mob.HasCustomName()) + { + WriteByte(0x8a); + WriteString(a_Mob.GetCustomName()); + WriteByte(0x0b); + WriteByte(a_Mob.IsCustomNameAlwaysVisible() ? 1 : 0); + } } -- cgit v1.2.3 From dfed6f94ca78f2e104ed316d83400b0ca74cb79a Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 1 Sep 2014 21:05:45 +0200 Subject: Added name tag --- src/Entities/Boat.cpp | 2 ++ src/Entities/Entity.h | 2 +- src/Entities/ItemFrame.cpp | 2 ++ src/Entities/Minecart.cpp | 5 +++-- src/Mobs/Monster.cpp | 19 +++++++++++++++++++ src/Mobs/Monster.h | 2 ++ src/Mobs/Sheep.cpp | 2 ++ 7 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp index 8ff8866a1..328a70846 100644 --- a/src/Entities/Boat.cpp +++ b/src/Entities/Boat.cpp @@ -62,6 +62,8 @@ bool cBoat::DoTakeDamage(TakeDamageInfo & TDI) void cBoat::OnRightClicked(cPlayer & a_Player) { + super::OnRightClicked(a_Player); + if (m_Attachee != NULL) { if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index b9c280b6b..774cdb062 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -447,7 +447,7 @@ public: // tolua_end /// Called when the specified player right-clicks this entity - virtual void OnRightClicked(cPlayer &) {} + virtual void OnRightClicked(cPlayer & a_Player) {} /// Returns the list of drops for this pawn when it is killed. May check a_Killer for special handling (sword of looting etc.). Called from KilledBy(). virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp index 0bc10ec60..3ccb95998 100644 --- a/src/Entities/ItemFrame.cpp +++ b/src/Entities/ItemFrame.cpp @@ -22,6 +22,8 @@ cItemFrame::cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_ void cItemFrame::OnRightClicked(cPlayer & a_Player) { + super::OnRightClicked(a_Player); + if (!m_Item.IsEmpty()) { // Item not empty, rotate, clipping values to zero to three inclusive diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 1501eea84..5fabbb542 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -1072,6 +1072,8 @@ cRideableMinecart::cRideableMinecart(double a_X, double a_Y, double a_Z, const c void cRideableMinecart::OnRightClicked(cPlayer & a_Player) { + super::OnRightClicked(a_Player); + if (m_Attachee != NULL) { if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) @@ -1124,8 +1126,7 @@ void cMinecartWithChest::SetSlot(size_t a_Idx, const cItem & a_Item) void cMinecartWithChest::OnRightClicked(cPlayer & a_Player) { - // Show the chest UI window to the player - // TODO + // TODO: Show the chest UI window to the player } diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 6a477ca1c..a89fa32a3 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -553,6 +553,25 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI) +void cMonster::OnRightClicked(cPlayer & a_Player) +{ + super::OnRightClicked(a_Player); + + const cItem & EquippedItem = a_Player.GetEquippedItem(); + if ((EquippedItem.m_ItemType == E_ITEM_NAME_TAG) && !EquippedItem.m_CustomName.empty()) + { + SetCustomName(EquippedItem.m_CustomName); + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + } +} + + + + + // Checks to see if EventSeePlayer should be fired // monster sez: Do I see the player void cMonster::CheckEventSeePlayer(void) diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index ce4e36a46..f14a4f100 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -92,6 +92,8 @@ public: virtual void KilledBy(TakeDamageInfo & a_TDI) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export virtual bool ReachedDestination(void); diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 9fb47201d..ee3236bba 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -47,6 +47,8 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cSheep::OnRightClicked(cPlayer & a_Player) { + super::OnRightClicked(a_Player); + const cItem & EquippedItem = a_Player.GetEquippedItem(); if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && !IsSheared() && !IsBaby()) { -- cgit v1.2.3 From 1bb4d7941267ee55cdf7f35fa6a0055521115960 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 2 Sep 2014 19:12:35 +0200 Subject: Added SetCustomName() to players. --- src/ClientHandle.cpp | 12 ++++------ src/ClientHandle.h | 2 +- src/Entities/Player.cpp | 47 ++++++++++++++++++++++++++++++++++++- src/Entities/Player.h | 15 ++++++++++++ src/Mobs/Monster.h | 3 ++- src/Protocol/Protocol.h | 2 +- src/Protocol/Protocol125.cpp | 23 +++++++++--------- src/Protocol/Protocol125.h | 2 +- src/Protocol/Protocol132.cpp | 9 ++++++- src/Protocol/Protocol17x.cpp | 26 +++++++++++++++----- src/Protocol/Protocol17x.h | 2 +- src/Protocol/ProtocolRecognizer.cpp | 4 ++-- src/Protocol/ProtocolRecognizer.h | 2 +- src/World.cpp | 14 +++++++---- src/World.h | 2 +- 15 files changed, 124 insertions(+), 41 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index f9c6a664c..e97c126a1 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -124,13 +124,11 @@ cClientHandle::~cClientHandle() if (m_Player != NULL) { cWorld * World = m_Player->GetWorld(); - if (!m_Username.empty() && (World != NULL)) - { - // Send the Offline PlayerList packet: - World->BroadcastPlayerListItem(*m_Player, false, this); - } if (World != NULL) { + // Send the Offline PlayerList packet: + World->BroadcastPlayerListItem(m_Player->GetTabListName(), false, 0, this); + World->RemovePlayer(m_Player, true); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again m_Player->Destroy(); } @@ -2371,9 +2369,9 @@ void cClientHandle::SendPlayerAbilities() -void cClientHandle::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cClientHandle::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping) { - m_Protocol->SendPlayerListItem(a_Player, a_IsOnline); + m_Protocol->SendPlayerListItem(a_PlayerName, a_IsOnline, a_Ping); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 7ae70a07f..529ee4555 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -156,7 +156,7 @@ public: 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_ParticleAmmount); void SendPlayerAbilities (void); - void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline); + void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0); void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+) void SendPlayerMoveLook (void); void SendPlayerPosition (void); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 756410989..a2934d036 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -81,7 +81,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) : m_Team(NULL), m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL), m_bIsTeleporting(false), - m_UUID((a_Client != NULL) ? a_Client->GetUUID() : "") + m_UUID((a_Client != NULL) ? a_Client->GetUUID() : ""), + m_CustomName("") { m_InventoryWindow = new cInventoryWindow(*this); m_CurrentWindow = m_InventoryWindow; @@ -813,6 +814,28 @@ void cPlayer::SetCanFly(bool a_CanFly) +void cPlayer::SetCustomName(const AString & a_CustomName) +{ + if (m_CustomName == a_CustomName) + { + return; + } + m_World->BroadcastPlayerListItem(GetTabListName(), false, 0); // Remove old tab-list entry + + m_CustomName = a_CustomName; + if (m_CustomName.length() > 16) + { + m_CustomName = m_CustomName.substr(0, 16); + } + + m_World->BroadcastSpawnEntity(*this, m_ClientHandle); + m_World->BroadcastPlayerListItem(GetTabListName(), true, GetClientHandle()->GetPing()); +} + + + + + void cPlayer::SetFlying(bool a_IsFlying) { if (a_IsFlying == m_IsFlying) @@ -1443,6 +1466,28 @@ AString cPlayer::GetColor(void) const +AString cPlayer::GetTabListName(void) const +{ + const AString & Color = GetColor(); + + if (HasCustomName()) + { + return m_CustomName; + } + else if ((GetName().length() <= 14) && !Color.empty()) + { + return Printf("%s%s", Color.c_str(), GetName().c_str()); + } + else + { + return GetName(); + } +} + + + + + void cPlayer::TossEquippedItem(char a_Amount) { cItems Drops; diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 9821cc6d9..da64bd64f 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -251,6 +251,9 @@ public: The returned value either is empty, or includes the cChatColor::Delimiter. */ AString GetColor(void) const; + /** Returns the name that is used in the tablist. */ + AString GetTabListName(void) const; + /** tosses the item in the selected hotbar slot */ void TossEquippedItem(char a_Amount = 1); @@ -398,6 +401,16 @@ public: /** If true the player can fly even when he's not in creative. */ void SetCanFly(bool a_CanFly); + /** Is a custom name for this player set? */ + bool HasCustomName(void) const { return !m_CustomName.empty(); } + + /** Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string. */ + const AString & GetCustomName(void) const { return m_CustomName; } + + /** Sets the custom name of this player. If you want to disable the custom name, simply set an empty string. + The custom name will be used in the tab-list, in the player nametag and in the tab-completion. */ + void SetCustomName(const AString & a_CustomName); + /** Gets the last position that the player slept in This is initialised to the world spawn point if the player has not slept in a bed as of yet */ @@ -562,6 +575,8 @@ protected: If no ClientHandle is given, the UUID is initialized to empty. */ AString m_UUID; + AString m_CustomName; + /** Sets the speed and sends it to the client, so that they are forced to move so. */ virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) override; diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index f14a4f100..a777978f6 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -153,7 +153,8 @@ public: /** Gets the custom name of the monster. If no custom name is set, the function returns a empty string. */ const AString & GetCustomName(void) const { return m_CustomName; } - /** Sets the custom name of the monster. You see the name over the monster. */ + /** Sets the custom name of the monster. You see the name over the monster. + If you want to disable the custom name, simply set an empty string. */ void SetCustomName(const AString & a_CustomName); /** Is the custom name of this monster always visible? If not, you only see the name when you sight the mob. */ diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 8e1842ec1..9b64faf79 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -93,7 +93,7 @@ public: virtual void SendPlayerAbilities (void) = 0; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0; virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) = 0; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) = 0; + virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) = 0; virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+) virtual void SendPlayerMoveLook (void) = 0; virtual void SendPlayerPosition (void) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index a66c64309..0b5e3de91 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -719,21 +719,13 @@ void cProtocol125::SendPaintingSpawn(const cPainting & a_Painting) -void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cProtocol125::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping) { cCSLock Lock(m_CSPacket); - AString PlayerName(a_Player.GetColor()); - PlayerName.append(a_Player.GetName()); - if (PlayerName.length() > 14) - { - PlayerName.erase(14); - } - PlayerName += cChatColor::White; - WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM); - WriteString(PlayerName); + WriteString(a_PlayerName); WriteBool (a_IsOnline); - WriteShort (a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); + WriteShort (a_Ping); Flush(); } @@ -792,7 +784,14 @@ void cProtocol125::SendPlayerSpawn(const cPlayer & a_Player) cCSLock Lock(m_CSPacket); WriteByte (PACKET_PLAYER_SPAWN); WriteInt (a_Player.GetUniqueID()); - WriteString(a_Player.GetName()); + if (a_Player.HasCustomName()) + { + WriteString(a_Player.GetCustomName()); + } + else + { + WriteString(a_Player.GetName()); + } WriteInt ((int)(a_Player.GetPosX() * 32)); WriteInt ((int)(a_Player.GetPosY() * 32)); WriteInt ((int)(a_Player.GetPosZ() * 32)); diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 1063777a2..9ab0adfcd 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -65,7 +65,7 @@ public: virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index 5c58ab0ba..af3bc68ee 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -260,7 +260,14 @@ void cProtocol132::SendPlayerSpawn(const cPlayer & a_Player) cCSLock Lock(m_CSPacket); WriteByte (PACKET_PLAYER_SPAWN); WriteInt (a_Player.GetUniqueID()); - WriteString(a_Player.GetName()); + if (a_Player.HasCustomName()) + { + WriteString(a_Player.GetCustomName()); + } + else + { + WriteString(a_Player.GetName()); + } WriteInt ((int)(a_Player.GetPosX() * 32)); WriteInt ((int)(a_Player.GetPosY() * 32)); WriteInt ((int)(a_Player.GetPosZ() * 32)); diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index ed9812377..2ac1d0d0f 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -865,14 +865,14 @@ void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_Sr -void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cProtocol172::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x38); // Playerlist Item packet - Pkt.WriteString(a_Player.GetName()); + Pkt.WriteString(a_PlayerName); Pkt.WriteBool(a_IsOnline); - Pkt.WriteShort(a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); + Pkt.WriteShort(a_Ping); } @@ -946,9 +946,16 @@ void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player) // Called to spawn another player for the client cPacketizer Pkt(*this, 0x0c); // Spawn Player packet - Pkt.WriteVarInt(a_Player.GetUniqueID()); + Pkt.WriteVarInt((UInt32) a_Player.GetUniqueID()); Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID())); - Pkt.WriteString(a_Player.GetName()); + if (a_Player.HasCustomName()) + { + Pkt.WriteString(a_Player.GetCustomName()); + } + else + { + Pkt.WriteString(a_Player.GetName()); + } Pkt.WriteFPInt(a_Player.GetPosX()); Pkt.WriteFPInt(a_Player.GetPosY()); Pkt.WriteFPInt(a_Player.GetPosZ()); @@ -3075,7 +3082,14 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player) cPacketizer Pkt(*this, 0x0c); // Spawn Player packet Pkt.WriteVarInt(a_Player.GetUniqueID()); Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID())); - Pkt.WriteString(a_Player.GetName()); + if (a_Player.HasCustomName()) + { + Pkt.WriteString(a_Player.GetCustomName()); + } + else + { + Pkt.WriteString(a_Player.GetName()); + } const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties(); Pkt.WriteVarInt(Properties.size()); diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index ccfa19eb6..eb64f6ad5 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -97,7 +97,7 @@ public: virtual void SendPlayerAbilities (void) override; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index c831da251..d9cfc140a 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -487,10 +487,10 @@ void cProtocolRecognizer::SendEntityAnimation(const cEntity & a_Entity, char a_A -void cProtocolRecognizer::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cProtocolRecognizer::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping) { ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerListItem(a_Player, a_IsOnline); + m_Protocol->SendPlayerListItem(a_PlayerName, a_IsOnline, a_Ping); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index a05aeda70..95fcae1d3 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -100,7 +100,7 @@ public: virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/World.cpp b/src/World.cpp index 99e09c658..469606012 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2147,7 +2147,7 @@ void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src -void cWorld::BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude) +void cWorld::BroadcastPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping, const cClientHandle * a_Exclude) { cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) @@ -2157,7 +2157,7 @@ void cWorld::BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, { continue; } - ch->SendPlayerListItem(a_Player, a_IsOnline); + ch->SendPlayerListItem(a_PlayerName, a_IsOnline, a_Ping); } } @@ -2669,7 +2669,7 @@ void cWorld::SendPlayerList(cPlayer * a_DestPlayer) cClientHandle * ch = (*itr)->GetClientHandle(); if ((ch != NULL) && !ch->IsDestroyed()) { - a_DestPlayer->GetClientHandle()->SendPlayerListItem(*(*itr), true); + a_DestPlayer->GetClientHandle()->SendPlayerListItem((*itr)->GetTabListName(), true, (*itr)->GetClientHandle()->GetPing()); } } } @@ -3209,13 +3209,17 @@ void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Resul for (cPlayerList::iterator itr = m_Players.begin(), end = m_Players.end(); itr != end; ++itr) { AString PlayerName ((*itr)->GetName()); + if ((*itr)->HasCustomName()) + { + PlayerName = (*itr)->GetCustomName(); + } + AString::size_type Found = PlayerName.find(LastWord); // Try to find last word in playername - if (Found == AString::npos) { continue; // No match } - + UsernamesByWeight.push_back(std::make_pair(Found, PlayerName)); // Match! Store it with the position of the match as a weight } Lock.Unlock(); diff --git a/src/World.h b/src/World.h index 578c9682b..5f4466603 100644 --- a/src/World.h +++ b/src/World.h @@ -237,7 +237,7 @@ public: void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override; // tolua_export void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export - void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL); + void BroadcastPlayerListItem (const AString & a_PlayerName, bool a_IsOnline, short a_Ping = 0, const cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); -- cgit v1.2.3 From c8953d165c037684b1373e090dea56daddc6e636 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 2 Sep 2014 19:13:36 +0200 Subject: Added a custom name test to the debuggers plugin. --- MCServer/Plugins/Debuggers/Debuggers.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index 179935c08..65ce0993a 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -38,6 +38,7 @@ function Initialize(Plugin) -- _X: Disabled so that the normal operation doesn't interfere with anything -- PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated); + PM:BindCommand("/cm", "debuggers", HandleCustomNameCmd, "- Gives you a custom name"); PM:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities"); PM:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities"); PM:BindCommand("/wool", "debuggers", HandleWoolCmd, "- Sets all your armor to blue wool"); @@ -768,6 +769,22 @@ end +function HandleCustomNameCmd(Split, Player) + if (Split[2] == nil) then + Player:SendMessage("Usage: /cm [CustomName]"); + return true; + end + + local NewName = Split[2] + Player:SetCustomName(NewName); + Player:SendMessageSuccess("Custom name setted to " .. Player:GetCustomName() .. "!") + return true +end + + + + + function HandleListEntitiesCmd(Split, Player) local NumEntities = 0; -- cgit v1.2.3 From 079634d18cf63abad05db0fda9a4510aa75c0522 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 2 Sep 2014 19:20:59 +0200 Subject: Added the new functions to APIDump. --- MCServer/Plugins/APIDump/APIDesc.lua | 9 +++++++++ src/Entities/Player.h | 2 +- src/Mobs/Monster.h | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index e7f9e9b18..f109638e9 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -1629,6 +1629,11 @@ a_Player:OpenWindow(Window); ]], Functions = { + HasCustomName = { Params = "", Return = "bool", Notes = "Returns true if the monster has a custom name." }, + GetCustomName = { Params = "", Return = "string", Notes = "Gets the custom name of the monster. If no custom name is set, the function returns an empty string." }, + SetCustomName = { Params = "string", Return = "", Notes = "Sets the custom name of the monster. You see the name over the monster. If you want to disable the custom name, simply set an empty string." }, + IsCustomNameAlwaysVisible = { Params = "", Return = "bool", Notes = "Is the custom name of this monster always visible? If not, you only see the name when you sight the mob." }, + SetCustomNameAlwaysVisible = { Params = "bool", Return = "", Notes = "Sets the custom name visiblity of this monster. If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name." }, FamilyFromType = { Params = "{{cMonster#MobType|MobType}}", Return = "{{cMonster#MobFamily|MobFamily}}", Notes = "(STATIC) Returns the mob family ({{cMonster#MobFamily|mfXXX}} constants) based on the mob type ({{cMonster#MobType|mtXXX}} constants)" }, GetMobFamily = { Params = "", Return = "{{cMonster#MobFamily|MobFamily}}", Notes = "Returns this mob's family ({{cMonster#MobFamily|mfXXX}} constant)" }, GetMobType = { Params = "", Return = "{{cMonster#MobType|MobType}}", Notes = "Returns the type of this mob ({{cMonster#MobType|mtXXX}} constant)" }, @@ -1752,6 +1757,7 @@ a_Player:OpenWindow(Window); ForceSetSpeed = { Params = "{{Vector3d|Direction}}", Notes = "Forces the player to move to the given direction." }, GetClientHandle = { Params = "", Return = "{{cClientHandle}}", Notes = "Returns the client handle representing the player's connection. May be nil (AI players)." }, GetColor = { Return = "string", Notes = "Returns the full color code to be used for this player's messages (based on their rank). Prefix player messages with this code." }, + GetTabListName = { Return = "string", Notes = "Returns the name that is used in the tablist." }, GetCurrentXp = { Params = "", Return = "number", Notes = "Returns the current amount of XP" }, GetEffectiveGameMode = { Params = "", Return = "{{Globals#GameMode|GameMode}}", Notes = "(OBSOLETE) Returns the current resolved game mode of the player. If the player is set to inherit the world's gamemode, returns that instead. See also GetGameMode() and IsGameModeXXX() functions. Note that this function is the same as GetGameMode(), use that function instead." }, GetEquippedItem = { Params = "", Return = "{{cItem}}", Notes = "Returns the item that the player is currently holding; empty item if holding nothing." }, @@ -1802,6 +1808,9 @@ a_Player:OpenWindow(Window); SendMessagePrivateMsg = { Params = "Message, SenderName", Return = "", Notes = "Prepends Light Blue [MSG: *SenderName*] / prepends SenderName and colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For private messaging." }, SendMessageSuccess = { Params = "Message", Return = "", Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Success notification." }, SendMessageWarning = { Params = "Message, Sender", Return = "", Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Denotes that something concerning, such as plugin reload, is about to happen." }, + HasCustomName = { Params = "", Return = "bool", Notes = "Returns true if the player has a custom name." }, + GetCustomName = { Params = "", Return = "string", Notes = "Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string." }, + SetCustomName = { Params = "string", Return = "", Notes = "Sets the custom name of this player. If you want to disable the custom name, simply set an empty string. The custom name will be used in the tab-list, in the player nametag and in the tab-completion." }, SetCanFly = { Params = "CanFly", Notes = "Sets if the player can fly or not." }, SetCrouch = { Params = "IsCrouched", Return = "", Notes = "Sets the crouch state, broadcasts the change to other players." }, SetCurrentExperience = { Params = "XPAmount", Return = "", Notes = "Sets the current amount of experience (and indirectly, the XP level)." }, diff --git a/src/Entities/Player.h b/src/Entities/Player.h index da64bd64f..49380c776 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -401,7 +401,7 @@ public: /** If true the player can fly even when he's not in creative. */ void SetCanFly(bool a_CanFly); - /** Is a custom name for this player set? */ + /** Returns true if the player has a custom name. */ bool HasCustomName(void) const { return !m_CustomName.empty(); } /** Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string. */ diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index a777978f6..1d66d50e5 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -150,7 +150,7 @@ public: /** Returns true if the monster has a custom name. */ bool HasCustomName(void) const { return !m_CustomName.empty(); } - /** Gets the custom name of the monster. If no custom name is set, the function returns a empty string. */ + /** Gets the custom name of the monster. If no custom name is set, the function returns an empty string. */ const AString & GetCustomName(void) const { return m_CustomName; } /** Sets the custom name of the monster. You see the name over the monster. @@ -161,7 +161,7 @@ public: bool IsCustomNameAlwaysVisible(void) const { return m_CustomNameAlwaysVisible; } /** Sets the custom name visiblity of this monster. - If false, you only see the name when you sight the mob. If true, you always see the custom name. */ + If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name. */ void SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible); /// Translates MobType enum to a string, empty string if unknown -- cgit v1.2.3 From 5c53608dd0e59d67a9aad5b03a58e1ff48d619b3 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 2 Sep 2014 19:34:58 +0200 Subject: Added CustomName saving. --- src/Mobs/Monster.cpp | 10 ++++++++-- src/WorldStorage/NBTChunkSerializer.cpp | 2 ++ src/WorldStorage/WSSAnvil.cpp | 13 +++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index a89fa32a3..b0b836dff 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -710,7 +710,10 @@ void cMonster::SetCustomName(const AString & a_CustomName) m_CustomName = a_CustomName.substr(0, 64); } - m_World->BroadcastEntityMetadata(*this); + if (m_World != NULL) + { + m_World->BroadcastEntityMetadata(*this); + } } @@ -720,7 +723,10 @@ void cMonster::SetCustomName(const AString & a_CustomName) void cMonster::SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible) { m_CustomNameAlwaysVisible = a_CustomNameAlwaysVisible; - m_World->BroadcastEntityMetadata(*this); + if (m_World != NULL) + { + m_World->BroadcastEntityMetadata(*this); + } } diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 68e541eba..1962d42ff 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -504,6 +504,8 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) m_Writer.AddFloat("", a_Monster->GetDropChanceBoots()); m_Writer.EndList(); m_Writer.AddByte("CanPickUpLoot", (char)a_Monster->CanPickUpLoot()); + m_Writer.AddString("CustomName", a_Monster->GetCustomName()); + m_Writer.AddByte("CustomNameVisible", (char)a_Monster->IsCustomNameAlwaysVisible()); switch (a_Monster->GetMobType()) { case cMonster::mtBat: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index e79cc291d..5c155aeef 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -2640,6 +2640,19 @@ bool cWSSAnvil::LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT & a_Monster.SetCanPickUpLoot(CanPickUpLoot); } + int CustomNameTag = a_NBT.FindChildByName(a_TagIdx, "CustomName"); + if ((CustomNameTag > 0) && (a_NBT.GetType(CustomNameTag) == TAG_String)) + { + a_Monster.SetCustomName(a_NBT.GetString(CustomNameTag)); + } + + int CustomNameVisibleTag = a_NBT.FindChildByName(a_TagIdx, "CustomNameVisible"); + if ((CustomNameVisibleTag > 0) && (a_NBT.GetType(CustomNameVisibleTag) == TAG_Byte)) + { + bool CustomNameVisible = (a_NBT.GetByte(CustomNameVisibleTag) == 1); + a_Monster.SetCustomNameAlwaysVisible(CustomNameVisible); + } + return true; } -- cgit v1.2.3 From 157f1c6688db8abe72c93a292f43d5a04040e0a4 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 4 Sep 2014 00:29:36 +0200 Subject: Started implementing of the 1.8 protocol. --- src/Protocol/CMakeLists.txt | 2 + src/Protocol/Protocol17x.cpp | 6 +- src/Protocol/Protocol17x.h | 14 +- src/Protocol/Protocol18x.cpp | 385 ++++++++++++++++++++++++++++++++++++ src/Protocol/Protocol18x.h | 76 +++++++ src/Protocol/ProtocolRecognizer.cpp | 25 ++- src/Protocol/ProtocolRecognizer.h | 1 + 7 files changed, 502 insertions(+), 7 deletions(-) create mode 100644 src/Protocol/Protocol18x.cpp create mode 100644 src/Protocol/Protocol18x.h diff --git a/src/Protocol/CMakeLists.txt b/src/Protocol/CMakeLists.txt index 1ba66ff1f..5426c58fa 100644 --- a/src/Protocol/CMakeLists.txt +++ b/src/Protocol/CMakeLists.txt @@ -14,6 +14,7 @@ SET (SRCS Protocol15x.cpp Protocol16x.cpp Protocol17x.cpp + Protocol18x.cpp ProtocolRecognizer.cpp) SET (HDRS @@ -27,6 +28,7 @@ SET (HDRS Protocol15x.h Protocol16x.h Protocol17x.h + Protocol18x.h ProtocolRecognizer.h) if(NOT MSVC) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 1091b877f..00b115c8f 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1,10 +1,12 @@ + // Protocol17x.cpp /* Implements the 1.7.x protocol classes: - cProtocol172 - release 1.7.2 protocol (#4) -(others may be added later in the future for the 1.7 release series) + - cProtocol176 + - release 1.7.6 protocol (#5) */ #include "Globals.h" @@ -1710,7 +1712,7 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) void cProtocol172::HandlePacketStatusPing(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Timestamp); - + cPacketizer Pkt(*this, 0x01); // Ping packet Pkt.WriteInt64(Timestamp); } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index ccfa19eb6..ec948e8a1 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -5,7 +5,8 @@ Declares the 1.7.x protocol classes: - cProtocol172 - release 1.7.2 protocol (#4) -(others may be added later in the future for the 1.7 release series) + - cProtocol176 + - release 1.7.6 protocol (#5) */ @@ -198,6 +199,11 @@ protected: { m_Out.WriteVarUTF8String(a_Value); } + + void WritePosition(const Vector3i a_Position) + { + WriteInt64(((Int64)a_Position.x & 0x3FFFFFF) << 38 | ((Int64)a_Position.y & 0xFFF) << 26 | ((Int64)a_Position.z & 0x3FFFFFF)); + } void WriteBuf(const char * a_Data, size_t a_Size) { @@ -258,12 +264,12 @@ protected: bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType); // Packet handlers while in the Status state (m_State == 1): - void HandlePacketStatusPing (cByteBuffer & a_ByteBuffer); + void HandlePacketStatusPing(cByteBuffer & a_ByteBuffer); virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer); // Packet handlers while in the Login state (m_State == 2): - void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer); - void HandlePacketLoginStart (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer); + virtual void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer); // Packet handlers while in the Game state (m_State == 3): void HandlePacketAnimation (cByteBuffer & a_ByteBuffer); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp new file mode 100644 index 000000000..0a455c70e --- /dev/null +++ b/src/Protocol/Protocol18x.cpp @@ -0,0 +1,385 @@ + +// Protocol18x.cpp + +/* +Implements the 1.8.x protocol classes: + - cProtocol180 + - release 1.8.0 protocol (#47) +(others may be added later in the future for the 1.8 release series) +*/ + +#include "Globals.h" +#include "Bindings/PluginManager.h" +#include "json/json.h" +#include "Protocol18x.h" + +#include "../ClientHandle.h" +#include "../CompositeChat.h" +#include "../Root.h" +#include "../Server.h" +#include "../World.h" + +#include "../Entities/Player.h" + +class cProtocol176; + + + + + +const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cProtocol180: + +cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : + super(a_Client, a_ServerAddress, a_ServerPort, a_State) +{ +} + + + + + +void cProtocol180::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x23); // Block Change packet + Pkt.WritePosition(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); + + UInt32 Block = ((UInt32)a_BlockType << 4) | ((UInt32)a_BlockMeta & 15); + Pkt.WriteVarInt(Block); +} + + + + + +void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x22); // Multi Block Change packet + Pkt.WriteInt(a_ChunkX); + Pkt.WriteInt(a_ChunkZ); + Pkt.WriteVarInt((UInt32)a_Changes.size()); + for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr) + { + short Coords = itr->y | (itr->z << 8) | (itr->x << 12); + Pkt.WriteShort(Coords); + + UInt32 Block = ((UInt32)itr->BlockType << 4) | ((UInt32)itr->BlockMeta & 15); + Pkt.WriteVarInt(Block); + } // for itr - a_Changes[] +} + + + + + +void cProtocol180::SendChat(const AString & a_Message) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x02); // Chat Message packet + Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str())); + Pkt.WriteChar(0); +} + + + + + +void cProtocol180::SendChat(const cCompositeChat & a_Message) +{ + ASSERT(m_State == 3); // In game mode? + + // Compose the complete Json string to send: + Json::Value msg; + cWorld * World = m_Client->GetPlayer()->GetWorld(); + msg["text"] = cClientHandle::FormatMessageType((World == NULL) ? false : World->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present + const cCompositeChat::cParts & Parts = a_Message.GetParts(); + for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) + { + Json::Value Part; + switch ((*itr)->m_PartType) + { + case cCompositeChat::ptText: + { + Part["text"] = (*itr)->m_Text; + AddChatPartStyle(Part, (*itr)->m_Style); + break; + } + + case cCompositeChat::ptClientTranslated: + { + const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr; + Part["translate"] = p.m_Text; + Json::Value With; + for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr) + { + With.append(*itrW); + } + if (!p.m_Parameters.empty()) + { + Part["with"] = With; + } + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptUrl: + { + const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Url; + Url["action"] = "open_url"; + Url["value"] = p.m_Url; + Part["clickEvent"] = Url; + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptSuggestCommand: + case cCompositeChat::ptRunCommand: + { + const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Cmd; + Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command"; + Cmd["value"] = p.m_Command; + Part["clickEvent"] = Cmd; + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptShowAchievement: + { + const cCompositeChat::cShowAchievementPart & p = (const cCompositeChat::cShowAchievementPart &)**itr; + Part["translate"] = "chat.type.achievement"; + + Json::Value Ach; + Ach["action"] = "show_achievement"; + Ach["value"] = p.m_Text; + + Json::Value AchColourAndName; + AchColourAndName["color"] = "green"; + AchColourAndName["translate"] = p.m_Text; + AchColourAndName["hoverEvent"] = Ach; + + Json::Value Extra; + Extra.append(AchColourAndName); + + Json::Value Name; + Name["text"] = p.m_PlayerName; + + Json::Value With; + With.append(Name); + With.append(Extra); + + Part["with"] = With; + AddChatPartStyle(Part, p.m_Style); + break; + } + } + msg["extra"].append(Part); + } // for itr - Parts[] + + // Send the message to the client: + cPacketizer Pkt(*this, 0x02); + Pkt.WriteString(msg.toStyledString()); + Pkt.WriteChar(0); +} + + + + + +void cProtocol180::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x04); // Entity Equipment packet + Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); + Pkt.WriteShort(a_SlotNum); + Pkt.WriteItem(a_Item); +} + + + + + +void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) +{ + // Send the Join Game packet: + { + cServer * Server = cRoot::Get()->GetServer(); + cPacketizer Pkt(*this, 0x01); // Join Game packet + Pkt.WriteInt(a_Player.GetUniqueID()); + Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 + Pkt.WriteChar((char)a_World.GetDimension()); + Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) + Pkt.WriteByte(std::min(Server->GetMaxPlayers(), 60)); + Pkt.WriteString("default"); // Level type - wtf? + Pkt.WriteBool(false); // Reduced Debug Info - wtf? + } + m_LastSentDimension = a_World.GetDimension(); + + // Send the spawn position: + { + cPacketizer Pkt(*this, 0x05); // Spawn Position packet + Vector3i Position(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); + Pkt.WritePosition(Position); + } + + // Send player abilities: + SendPlayerAbilities(); +} + + + + + +void cProtocol180::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) +{ + cServer * Server = cRoot::Get()->GetServer(); + AString ServerDescription = Server->GetDescription(); + int NumPlayers = Server->GetNumPlayers(); + int MaxPlayers = Server->GetMaxPlayers(); + AString Favicon = Server->GetFaviconData(); + cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon); + + // Version: + Json::Value Version; + Version["name"] = "1.8"; + Version["protocol"] = 47; + + // Players: + Json::Value Players; + Players["online"] = NumPlayers; + Players["max"] = MaxPlayers; + // TODO: Add "sample" + + // Description: + Json::Value Description; + Description["text"] = ServerDescription.c_str(); + + // Create the response: + Json::Value ResponseValue; + ResponseValue["version"] = Version; + ResponseValue["players"] = Players; + ResponseValue["description"] = Description; + if (!Favicon.empty()) + { + ResponseValue["favicon"] = Printf("data:image/png;base64,%s", Favicon.c_str()); + } + + Json::StyledWriter Writer; + AString Response = Writer.write(ResponseValue); + + cPacketizer Pkt(*this, 0x00); // Response packet + Pkt.WriteString(Response); +} + + + + + +void cProtocol180::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) +{ + AString Username; + if (!a_ByteBuffer.ReadVarUTF8String(Username)) + { + m_Client->Kick("Bad username"); + return; + } + + if (!m_Client->HandleHandshake(Username)) + { + // The client is not welcome here, they have been sent a Kick packet already + return; + } + + cServer * Server = cRoot::Get()->GetServer(); + // If auth is required, then send the encryption request: + if (Server->ShouldAuthenticate()) + { + cPacketizer Pkt(*this, 0x01); + Pkt.WriteString(Server->GetServerID()); + const AString & PubKeyDer = Server->GetPublicKeyDER(); + Pkt.WriteVarInt((short)PubKeyDer.size()); + Pkt.WriteBuf(PubKeyDer.data(), PubKeyDer.size()); + Pkt.WriteVarInt(4); + Pkt.WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :) + m_Client->SetUsername(Username); + return; + } + + m_Client->HandleLogin(4, Username); +} + + + + + +void cProtocol180::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) +{ + UInt32 EncKeyLength, EncNonceLength; + a_ByteBuffer.ReadVarInt(EncKeyLength); + AString EncKey; + if (!a_ByteBuffer.ReadString(EncKey, EncKeyLength)) + { + return; + } + a_ByteBuffer.ReadVarInt(EncNonceLength); + AString EncNonce; + if (!a_ByteBuffer.ReadString(EncNonce, EncNonceLength)) + { + return; + } + if ((EncKeyLength > MAX_ENC_LEN) || (EncNonceLength > MAX_ENC_LEN)) + { + LOGD("Too long encryption"); + m_Client->Kick("Hacked client"); + return; + } + + // Decrypt EncNonce using privkey + cRsaPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey(); + Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)]; + int res = rsaDecryptor.Decrypt((const Byte *)EncNonce.data(), EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce)); + if (res != 4) + { + LOGD("Bad nonce length: got %d, exp %d", res, 4); + m_Client->Kick("Hacked client"); + return; + } + if (ntohl(DecryptedNonce[0]) != (unsigned)(uintptr_t)this) + { + LOGD("Bad nonce value"); + m_Client->Kick("Hacked client"); + return; + } + + // Decrypt the symmetric encryption key using privkey: + Byte DecryptedKey[MAX_ENC_LEN]; + res = rsaDecryptor.Decrypt((const Byte *)EncKey.data(), EncKey.size(), DecryptedKey, sizeof(DecryptedKey)); + if (res != 16) + { + LOGD("Bad key length"); + m_Client->Kick("Hacked client"); + return; + } + + StartEncryption(DecryptedKey); + m_Client->HandleLogin(4, m_Client->GetUsername()); +} + + + + diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h new file mode 100644 index 000000000..11a376b17 --- /dev/null +++ b/src/Protocol/Protocol18x.h @@ -0,0 +1,76 @@ + +// Protocol18x.h + +/* +Declares the 1.8.x protocol classes: + - cProtocol180 + - release 1.8 protocol (#47) +(others may be added later in the future for the 1.8 release series) +*/ + + + + + +#pragma once + +#include "Protocol.h" +#include "Protocol17x.h" +#include "../ByteBuffer.h" + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4127) + #pragma warning(disable:4244) + #pragma warning(disable:4231) + #pragma warning(disable:4189) + #pragma warning(disable:4702) +#endif + +#ifdef _MSC_VER + #pragma warning(pop) +#endif + + + + + +// fwd: +namespace Json +{ + class Value; +} + + + + + +class cProtocol180 : + public cProtocol176 +{ + typedef cProtocol176 super; + +public: + + cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); + + virtual void SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; + virtual void SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; + virtual void SendChat(const AString & a_Message) override; + virtual void SendChat(const cCompositeChat & a_Message) override; + virtual void SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) override {} + virtual void SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; + virtual void SendLogin(const cPlayer & a_Player, const cWorld & a_World) override; + +protected: + + virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) override; + + // Packet handlers while in the Login state (m_State == 2): + virtual void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) override; +} ; + + + + diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 8b395230a..642e96880 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -13,6 +13,7 @@ #include "Protocol15x.h" #include "Protocol16x.h" #include "Protocol17x.h" +#include "Protocol18x.h" #include "../ClientHandle.h" #include "../Root.h" #include "../Server.h" @@ -51,7 +52,7 @@ AString cProtocolRecognizer::GetVersionTextFromInt(int a_ProtocolVersion) { case PROTO_VERSION_1_2_5: return "1.2.5"; case PROTO_VERSION_1_3_2: return "1.3.2"; - case PROTO_VERSION_1_4_2: return "1.4.2"; + // case PROTO_VERSION_1_4_2: return "1.4.2"; case PROTO_VERSION_1_4_4: return "1.4.4"; case PROTO_VERSION_1_4_6: return "1.4.6"; case PROTO_VERSION_1_5_0: return "1.5"; @@ -62,6 +63,7 @@ AString cProtocolRecognizer::GetVersionTextFromInt(int a_ProtocolVersion) case PROTO_VERSION_1_6_4: return "1.6.4"; case PROTO_VERSION_1_7_2: return "1.7.2"; case PROTO_VERSION_1_7_6: return "1.7.6"; + case PROTO_VERSION_1_8_0: return "1.8"; } ASSERT(!"Unknown protocol version"); return Printf("Unknown protocol (%d)", a_ProtocolVersion); @@ -1016,6 +1018,27 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema m_Protocol = new cProtocol176(m_Client, ServerAddress, (UInt16)ServerPort, NextState); return true; } + case PROTO_VERSION_1_8_0: + { + AString ServerAddress; + short ServerPort; + UInt32 NextState; + if (!m_Buffer.ReadVarUTF8String(ServerAddress)) + { + break; + } + if (!m_Buffer.ReadBEShort(ServerPort)) + { + break; + } + if (!m_Buffer.ReadVarInt(NextState)) + { + break; + } + m_Buffer.CommitRead(); + m_Protocol = new cProtocol180(m_Client, ServerAddress, (UInt16)ServerPort, NextState); + return true; + } } LOGINFO("Client \"%s\" uses an unsupported protocol (lengthed, version %u)", m_Client->GetIPString().c_str(), ProtocolVersion diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index a05aeda70..2e8976a9f 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -51,6 +51,7 @@ public: // These will be kept "under" the next / latest, because the next and latest are only needed for previous protocols PROTO_VERSION_1_7_2 = 4, PROTO_VERSION_1_7_6 = 5, + PROTO_VERSION_1_8_0 = 47, } ; cProtocolRecognizer(cClientHandle * a_Client); -- cgit v1.2.3 From 07fba5c98ec94f98b742e8aa76dcec5572bfcecb Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 4 Sep 2014 03:22:35 +0200 Subject: Added more 1.8 protocol things. --- src/Protocol/ChunkDataSerializer.cpp | 64 +++++ src/Protocol/ChunkDataSerializer.h | 4 +- src/Protocol/Protocol17x.cpp | 1 + src/Protocol/Protocol17x.h | 18 +- src/Protocol/Protocol18x.cpp | 523 ++++++++++++++++++++++++++++++++++- src/Protocol/Protocol18x.h | 36 +++ 6 files changed, 632 insertions(+), 14 deletions(-) diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index ebe61631b..9eadc4f0b 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -43,6 +43,7 @@ const AString & cChunkDataSerializer::Serialize(int a_Version) { case RELEASE_1_2_5: Serialize29(data); break; case RELEASE_1_3_2: Serialize39(data); break; + case RELEASE_1_8_0: Serialize80(data); break; // TODO: Other protocol versions may serialize the data differently; implement here default: @@ -174,3 +175,66 @@ void cChunkDataSerializer::Serialize39(AString & a_Data) + +void cChunkDataSerializer::Serialize80(AString & a_Data) +{ + // TODO: Do not copy data and then compress it; rather, compress partial blocks of data (zlib *can* stream) + + // Blocktypes converter (1.8 included the meta into the blocktype): + unsigned short Blocks[ARRAYCOUNT(m_BlockTypes)]; + for (int RelX = 0; RelX < cChunkDef::Width; RelX++) + { + for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++) + { + for (int RelY = 0; RelY < cChunkDef::Height; RelY++) + { + int Index = cChunkDef::MakeIndexNoCheck(RelX, RelY, RelZ); + BLOCKTYPE BlockType = m_BlockTypes[Index]; + NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; + + Blocks[Index] = ((unsigned short)BlockType << 4) | ((unsigned short)BlockMeta & 15); + } + } + } + + const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; + const int BlockLightOffset = sizeof(Blocks); + const int SkyLightOffset = BlockLightOffset + sizeof(m_BlockLight); + const int BiomeOffset = SkyLightOffset + sizeof(m_BlockSkyLight); + const int DataSize = BiomeOffset + BiomeDataSize; + + // Temporary buffer for the composed data: + char AllData [DataSize]; + memcpy(AllData, Blocks, sizeof(Blocks)); + memcpy(AllData + BlockLightOffset, m_BlockLight, sizeof(m_BlockLight)); + memcpy(AllData + SkyLightOffset, m_BlockSkyLight, sizeof(m_BlockSkyLight)); + memcpy(AllData + BiomeOffset, m_BiomeData, BiomeDataSize); + + // Put all those data into a_Data: + a_Data.push_back('\x01'); // "Ground-up continuous", or rather, "biome data present" flag + + // Two bitmaps; we're aways sending the full chunk with no additional data, so the bitmaps are 0xffff and 0, respectively + // Also, no endian flipping is needed because of the const values + unsigned short BitMap = 0xffff; + a_Data.append((const char *)&BitMap, sizeof(short)); + + // Write chunk size: + UInt32 ChunkSize = htonl((UInt32)DataSize); + + unsigned char b[5]; // // A 32-bit integer can be encoded by at most 5 bytes + size_t idx = 0; + UInt32 Value = ChunkSize; + do + { + b[idx] = (Value & 0x7f) | ((Value > 0x7f) ? 0x80 : 0x00); + Value = Value >> 7; + idx++; + } while (Value > 0); + a_Data.append((const char *)b, idx); + + a_Data.append(AllData, ChunkSize); // Chunk data +} + + + + diff --git a/src/Protocol/ChunkDataSerializer.h b/src/Protocol/ChunkDataSerializer.h index a42856356..4c33aede1 100644 --- a/src/Protocol/ChunkDataSerializer.h +++ b/src/Protocol/ChunkDataSerializer.h @@ -23,13 +23,15 @@ protected: Serializations m_Serializations; void Serialize29(AString & a_Data); // Release 1.2.4 and 1.2.5 - void Serialize39(AString & a_Data); // Release 1.3.1 and 1.3.2 + void Serialize39(AString & a_Data); // Release 1.3.1 to 1.7.10 + void Serialize80(AString & a_Data); // Release 1.8 public: enum { RELEASE_1_2_5 = 29, RELEASE_1_3_2 = 39, + RELEASE_1_8_0 = 47, } ; cChunkDataSerializer( diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 00b115c8f..88b4693c9 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2614,6 +2614,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) + void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEntity) { cFastNBTWriter Writer; diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index ec948e8a1..be94c0d61 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -146,6 +146,7 @@ protected: m_Lock(a_Protocol.m_CSPacket) { m_Out.WriteVarInt(a_PacketType); + LOG("Send packet %i", a_PacketType); } ~cPacketizer(); @@ -211,6 +212,7 @@ protected: } void WriteItem(const cItem & a_Item); + void WriteItem180(const cItem & a_Item); void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f @@ -277,21 +279,21 @@ protected: void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); void HandlePacketChatMessage (cByteBuffer & a_ByteBuffer); void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); - void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); - void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); - void HandlePacketKeepAlive (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketKeepAlive (cByteBuffer & a_ByteBuffer); void HandlePacketPlayer (cByteBuffer & a_ByteBuffer); void HandlePacketPlayerAbilities (cByteBuffer & a_ByteBuffer); void HandlePacketPlayerLook (cByteBuffer & a_ByteBuffer); - void HandlePacketPlayerPos (cByteBuffer & a_ByteBuffer); - void HandlePacketPlayerPosLook (cByteBuffer & a_ByteBuffer); - void HandlePacketPluginMessage (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketPlayerPos (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketPlayerPosLook (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketPluginMessage (cByteBuffer & a_ByteBuffer); void HandlePacketSlotSelect (cByteBuffer & a_ByteBuffer); - void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer); void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer); void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer); - void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer); void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer); void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 0a455c70e..4dbb2207c 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -11,6 +11,7 @@ Implements the 1.8.x protocol classes: #include "Globals.h" #include "Bindings/PluginManager.h" #include "json/json.h" +#include "ChunkDataSerializer.h" #include "Protocol18x.h" #include "../ClientHandle.h" @@ -20,14 +21,25 @@ Implements the 1.8.x protocol classes: #include "../World.h" #include "../Entities/Player.h" +#include "Entities/Painting.h" -class cProtocol176; + + + + +#define HANDLE_READ(ByteBuf, Proc, Type, Var) \ + Type Var; \ + if (!ByteBuf.Proc(Var))\ + {\ + return;\ + } const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... +class cProtocol176; @@ -45,6 +57,347 @@ cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAdd +void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +{ + ASSERT(m_State == 3); // In game mode? + + /*cPacketizer Pkt(*this, 0x2A); + Pkt.WriteString(a_ParticleName); + Pkt.WriteFloat(a_SrcX); + Pkt.WriteFloat(a_SrcY); + Pkt.WriteFloat(a_SrcZ); + Pkt.WriteFloat(a_OffsetX); + Pkt.WriteFloat(a_OffsetY); + Pkt.WriteFloat(a_OffsetZ); + Pkt.WriteFloat(a_ParticleData); + Pkt.WriteInt(a_ParticleAmmount);*/ +} + + + + + +void cProtocol180::SendPlayerMoveLook(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x08); // Player Position And Look packet + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteDouble(Player->GetPosX()); + + // The "+ 0.001" is there because otherwise the player falls through the block they were standing on. + Pkt.WriteDouble(Player->GetStance() + 0.001); + + Pkt.WriteDouble(Player->GetPosZ()); + Pkt.WriteFloat((float)Player->GetYaw()); + Pkt.WriteFloat((float)Player->GetPitch()); + Pkt.WriteByte(0); +} + + + + + +void cProtocol180::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x0a); + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WritePosition(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); +} + + + + + +void cProtocol180::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x0d); // Collect Item packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteVarInt(a_Player.GetUniqueID()); +} + + + + + +void cProtocol180::SendEntityVelocity(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x12); // Entity Velocity packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + // 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick + Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); + Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); + Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); +} + + + + + +void cProtocol180::SendDestroyEntity(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x13); // Destroy Entities packet + Pkt.WriteVarInt(1); + Pkt.WriteVarInt(a_Entity.GetUniqueID()); +} + + + + + +void cProtocol180::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_RelX); + Pkt.WriteByte(a_RelY); + Pkt.WriteByte(a_RelZ); + Pkt.WriteBool(true); // TODO: IsOnGround() on entities +} + + + + + +void cProtocol180::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_RelX); + Pkt.WriteByte(a_RelY); + Pkt.WriteByte(a_RelZ); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(true); // TODO: IsOnGround() on entities +} + + + + + +void cProtocol180::SendEntityLook(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x16); // Entity Look packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(true); // TODO: IsOnGround() on entities +} + + + + + +void cProtocol180::SendTeleportEntity(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x18); + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteFPInt(a_Entity.GetPosX()); + Pkt.WriteFPInt(a_Entity.GetPosY()); + Pkt.WriteFPInt(a_Entity.GetPosZ()); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(true); // TODO: IsOnGrond() on entities +} + + + + + +void cProtocol180::SendEntityHeadLook(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x19); // Entity Head Look packet + Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); + Pkt.WriteByteAngle(a_Entity.GetHeadYaw()); +} + + + + + +void cProtocol180::SendEntityMetadata(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteEntityMetadata(a_Entity); + Pkt.WriteByte(0x7f); // The termination byte +} + + + + + +void cProtocol180::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x1D); // Entity Effect packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_EffectID); + Pkt.WriteByte(a_Amplifier); + Pkt.WriteVarInt((UInt32)a_Duration); + Pkt.WriteBool(false); // Hide particles +} + + + + + +void cProtocol180::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x1e); + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_EffectID); +} + + + + + +void cProtocol180::SendEntityProperties(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x20); // Entity Properties packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteEntityProperties(a_Entity); +} + + + + + +void cProtocol180::SendKeepAlive(int a_PingID) +{ + // Drop the packet if the protocol is not in the Game state yet (caused a client crash): + if (m_State != 3) + { + LOGWARNING("Trying to send a KeepAlive packet to a player who's not yet fully logged in (%d). The protocol class prevented the packet.", m_State); + return; + } + + cPacketizer Pkt(*this, 0x00); // Keep Alive packet + Pkt.WriteVarInt(a_PingID); +} + + + + + +void cProtocol180::SendHealth(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x06); // Update Health packet + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteFloat((float)Player->GetHealth()); + Pkt.WriteVarInt((UInt32)Player->GetFoodLevel()); + Pkt.WriteFloat((float)Player->GetFoodSaturationLevel()); +} + + + + + +void cProtocol180::SendExperience(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x1f); // Experience Packet + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteFloat(Player->GetXpPercentage()); + Pkt.WriteVarInt((UInt32)Player->GetXpLevel()); + Pkt.WriteVarInt((UInt32)Player->GetCurrentXp()); +} + + + + + +void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x10); // Spawn Painting packet + Pkt.WriteVarInt(a_Painting.GetUniqueID()); + Pkt.WriteString(a_Painting.GetName().c_str()); + Pkt.WritePosition(Vector3i(a_Painting.GetPosX(), a_Painting.GetPosY(), a_Painting.GetPosZ())); + Pkt.WriteChar(a_Painting.GetDirection()); +} + + + + + +void cProtocol180::SendPluginMessage(const AString & a_Channel, const AString & a_Message) +{ + ASSERT(m_State == 3); // In game mode? + + /*cPacketizer Pkt(*this, 0x3f); + Pkt.WriteString(a_Channel); + Pkt.WriteBuf(a_Message.data(), a_Message.size());*/ +} + + + + + +void cProtocol180::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x21); // Chunk Data packet + Pkt.WriteInt(a_ChunkX); + Pkt.WriteInt(a_ChunkZ); + Pkt.WriteBool(true); + Pkt.WriteShort(0); // Primary bitmap + Pkt.WriteVarInt(0); // Data size +} + + + + + +void cProtocol180::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) +{ + ASSERT(m_State == 3); // In game mode? + + /*// Serialize first, before creating the Packetizer (the packetizer locks a CS) + // This contains the flags and bitmasks, too + const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_8_0); + + cPacketizer Pkt(*this, 0x21); // Chunk Data packet + Pkt.WriteInt(a_ChunkX); + Pkt.WriteInt(a_ChunkZ); + Pkt.WriteBuf(ChunkData.data(), ChunkData.size());*/ +} + + + + + void cProtocol180::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { ASSERT(m_State == 3); // In game mode? @@ -64,7 +417,7 @@ void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x22); // Multi Block Change packet + /*cPacketizer Pkt(*this, 0x22); // Multi Block Change packet Pkt.WriteInt(a_ChunkX); Pkt.WriteInt(a_ChunkZ); Pkt.WriteVarInt((UInt32)a_Changes.size()); @@ -75,7 +428,7 @@ void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV UInt32 Block = ((UInt32)itr->BlockType << 4) | ((UInt32)itr->BlockMeta & 15); Pkt.WriteVarInt(Block); - } // for itr - a_Changes[] + } // for itr - a_Changes[]*/ } @@ -204,10 +557,10 @@ void cProtocol180::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x04); // Entity Equipment packet + /*cPacketizer Pkt(*this, 0x04); // Entity Equipment packet Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); Pkt.WriteShort(a_SlotNum); - Pkt.WriteItem(a_Item); + Pkt.WriteItem(a_Item);*/ } @@ -245,6 +598,50 @@ void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) +void cProtocol180::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadChar, char, ActionID); + switch (ActionID) + { + case 0: + { + // Respawn + m_Client->HandleRespawn(); + break; + } + case 1: + { + // Request stats + const cStatManager & Manager = m_Client->GetPlayer()->GetStatManager(); + SendStatistics(Manager); + + break; + } + case 2: + { + // Open Inventory achievement + m_Client->GetPlayer()->AwardAchievement(achOpenInv); + break; + } + } +} + + + + + +void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); + AString Data; + a_ByteBuffer.ReadAll(Data); + m_Client->HandlePluginMessage(Channel, Data); +} + + + + + void cProtocol180::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) { cServer * Server = cRoot::Get()->GetServer(); @@ -383,3 +780,119 @@ void cProtocol180::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffe + +void cProtocol180::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Forward); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Sideways); + HANDLE_READ(a_ByteBuffer, ReadChar, char, Flags); + + if ((Flags & 0x2) != 0) + { + m_Client->HandleUnmount(); + } + else if ((Flags & 0x1) != 0) + { + m_Client->HandleSteerVehicle(Forward, Sideways); + } +} + + + + + +void cProtocol180::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, PlayerID); + HANDLE_READ(a_ByteBuffer, ReadChar, char, Action); + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, JumpBoost); + + switch (Action) + { + case 0: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch + case 1: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch + case 2: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed + case 3: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting + case 4: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting + } +} + + + + + +void cProtocol180::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, EntityID); + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Type); + + switch (Type) + { + case 0: + { + m_Client->HandleUseEntity((int)EntityID, false); + break; + } + case 1: + { + m_Client->HandleUseEntity((int)EntityID, true); + break; + } + case 2: + { + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetX); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetY); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetZ); + + // TODO: Do anything + break; + } + default: + { + ASSERT(!"Unhandled use entity type!"); + return; + } + } +} + + + + + +void cProtocol180::HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, KeepAliveID); + m_Client->HandleKeepAlive((int)KeepAliveID); +} + + + + + +void cProtocol180::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + m_Client->HandlePlayerPos(PosX, PosY, PosZ, PosY + 1.62, IsOnGround); +} + + + + + +void cProtocol180::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, PosY + 1.62, Yaw, Pitch, IsOnGround); +} + + + + diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 11a376b17..6604cbc3e 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -54,6 +54,32 @@ public: cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); + virtual void SendPickupSpawn (const cPickup & a_Pickup) override {} + virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override {} + virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override {} + virtual void SendWholeInventory (const cWindow & a_Window) override {} + virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; + virtual void SendEntityVelocity (const cEntity & a_Entity) override; + virtual void SendDestroyEntity (const cEntity & a_Entity) override; + virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityLook(const cEntity & a_Entity) override; + virtual void SendTeleportEntity(const cEntity & a_Entity) override; + virtual void SendEntityHeadLook(const cEntity & a_Entity) override; + virtual void SendEntityMetadata(const cEntity & a_Entity) override; + virtual void SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; + virtual void SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) override; + virtual void SendEntityProperties(const cEntity & a_Entity) override; + virtual void SendKeepAlive(int a_PingID) override; + virtual void SendHealth(void) override; + virtual void SendExperience(void) override; + virtual void SendPaintingSpawn(const cPainting & a_Painting) override; + virtual void SendPluginMessage(const AString & a_Channel, const AString & a_Message) override; + virtual void SendUnloadChunk(int a_ChunkX, int a_ChunkZ) override; + virtual void SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendChat(const AString & a_Message) override; @@ -69,6 +95,16 @@ protected: // Packet handlers while in the Login state (m_State == 2): virtual void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) override; + + // Packet handlers while in the Game state (m_State == 3): + virtual void HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) override; } ; -- cgit v1.2.3 From da28c70def4be849925709b2c4d4857b6db1abb8 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 4 Sep 2014 19:03:21 +0200 Subject: Fixed client errors. --- src/Protocol/ChunkDataSerializer.cpp | 32 +++---------- src/Protocol/Protocol17x.cpp | 2 +- src/Protocol/Protocol17x.h | 3 +- src/Protocol/Protocol18x.cpp | 90 ++++++++++++++++++++++++++---------- src/Protocol/Protocol18x.h | 4 ++ 5 files changed, 79 insertions(+), 52 deletions(-) diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index 9eadc4f0b..29e32ce32 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -182,19 +182,11 @@ void cChunkDataSerializer::Serialize80(AString & a_Data) // Blocktypes converter (1.8 included the meta into the blocktype): unsigned short Blocks[ARRAYCOUNT(m_BlockTypes)]; - for (int RelX = 0; RelX < cChunkDef::Width; RelX++) + for (size_t Index = 0; Index < cChunkDef::NumBlocks; Index++) { - for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++) - { - for (int RelY = 0; RelY < cChunkDef::Height; RelY++) - { - int Index = cChunkDef::MakeIndexNoCheck(RelX, RelY, RelZ); - BLOCKTYPE BlockType = m_BlockTypes[Index]; - NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; - - Blocks[Index] = ((unsigned short)BlockType << 4) | ((unsigned short)BlockMeta & 15); - } - } + BLOCKTYPE BlockType = m_BlockTypes[Index]; + NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; + Blocks[Index] = ((unsigned short)BlockType << 4) | ((unsigned short)BlockMeta); } const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; @@ -216,23 +208,13 @@ void cChunkDataSerializer::Serialize80(AString & a_Data) // Two bitmaps; we're aways sending the full chunk with no additional data, so the bitmaps are 0xffff and 0, respectively // Also, no endian flipping is needed because of the const values unsigned short BitMap = 0xffff; - a_Data.append((const char *)&BitMap, sizeof(short)); + a_Data.append((const char *)&BitMap, sizeof(unsigned short)); // Write chunk size: UInt32 ChunkSize = htonl((UInt32)DataSize); + a_Data.append((const char *)&ChunkSize, 4); - unsigned char b[5]; // // A 32-bit integer can be encoded by at most 5 bytes - size_t idx = 0; - UInt32 Value = ChunkSize; - do - { - b[idx] = (Value & 0x7f) | ((Value > 0x7f) ? 0x80 : 0x00); - Value = Value >> 7; - idx++; - } while (Value > 0); - a_Data.append((const char *)b, idx); - - a_Data.append(AllData, ChunkSize); // Chunk data + a_Data.append(AllData, DataSize); // Chunk data } diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 88b4693c9..b4f30b639 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1924,7 +1924,7 @@ void cProtocol172::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ShowCape); m_Client->SetLocale(Locale); - // TODO: handle in m_Client + // TODO: Do anything with the other values. } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index be94c0d61..d715e1cec 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -146,7 +146,6 @@ protected: m_Lock(a_Protocol.m_CSPacket) { m_Out.WriteVarInt(a_PacketType); - LOG("Send packet %i", a_PacketType); } ~cPacketizer(); @@ -278,7 +277,7 @@ protected: void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); void HandlePacketChatMessage (cByteBuffer & a_ByteBuffer); - void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); virtual void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); virtual void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 4dbb2207c..a3e72d4dd 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -57,6 +57,29 @@ cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAdd +void cProtocol180::SendLoginSuccess(void) +{ + ASSERT(m_State == 2); // State: login? + + // Disable compression: + { + cPacketizer Pkt(*this, 0x03); // Set compression packet + Pkt.WriteVarInt(-1); + } + + { + cPacketizer Pkt(*this, 0x02); // Login success packet + Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID())); + Pkt.WriteString(m_Client->GetUsername()); + } + + m_State = 3; // State = Game +} + + + + + void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) { ASSERT(m_State == 3); // In game mode? @@ -81,7 +104,7 @@ void cProtocol180::SendPlayerMoveLook(void) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x08); // Player Position And Look packet + /*cPacketizer Pkt(*this, 0x08); // Player Position And Look packet cPlayer * Player = m_Client->GetPlayer(); Pkt.WriteDouble(Player->GetPosX()); @@ -91,7 +114,7 @@ void cProtocol180::SendPlayerMoveLook(void) Pkt.WriteDouble(Player->GetPosZ()); Pkt.WriteFloat((float)Player->GetYaw()); Pkt.WriteFloat((float)Player->GetPitch()); - Pkt.WriteByte(0); + Pkt.WriteByte(0);*/ } @@ -128,12 +151,12 @@ void cProtocol180::SendEntityVelocity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x12); // Entity Velocity packet + /*cPacketizer Pkt(*this, 0x12); // Entity Velocity packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); // 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); + Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400));*/ } @@ -144,9 +167,9 @@ void cProtocol180::SendDestroyEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x13); // Destroy Entities packet + /*cPacketizer Pkt(*this, 0x13); // Destroy Entities packet Pkt.WriteVarInt(1); - Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteVarInt(a_Entity.GetUniqueID());*/ } @@ -157,12 +180,12 @@ void cProtocol180::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet + /*cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByte(a_RelX); Pkt.WriteByte(a_RelY); Pkt.WriteByte(a_RelZ); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities + Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ } @@ -173,14 +196,14 @@ void cProtocol180::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet + /*cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByte(a_RelX); Pkt.WriteByte(a_RelY); Pkt.WriteByte(a_RelZ); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities + Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ } @@ -191,11 +214,11 @@ void cProtocol180::SendEntityLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x16); // Entity Look packet + /*cPacketizer Pkt(*this, 0x16); // Entity Look packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities + Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ } @@ -206,14 +229,14 @@ void cProtocol180::SendTeleportEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x18); + /*cPacketizer Pkt(*this, 0x18); Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteFPInt(a_Entity.GetPosX()); Pkt.WriteFPInt(a_Entity.GetPosY()); Pkt.WriteFPInt(a_Entity.GetPosZ()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGrond() on entities + Pkt.WriteBool(true); // TODO: IsOnGrond() on entities*/ } @@ -224,9 +247,9 @@ void cProtocol180::SendEntityHeadLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x19); // Entity Head Look packet + /*cPacketizer Pkt(*this, 0x19); // Entity Head Look packet Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); - Pkt.WriteByteAngle(a_Entity.GetHeadYaw()); + Pkt.WriteByteAngle(a_Entity.GetHeadYaw());*/ } @@ -237,10 +260,10 @@ void cProtocol180::SendEntityMetadata(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet + /*cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteEntityMetadata(a_Entity); - Pkt.WriteByte(0x7f); // The termination byte + Pkt.WriteByte(0x7f); // The termination byte*/ } @@ -340,11 +363,11 @@ void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x10); // Spawn Painting packet + /*cPacketizer Pkt(*this, 0x10); // Spawn Painting packet Pkt.WriteVarInt(a_Painting.GetUniqueID()); Pkt.WriteString(a_Painting.GetName().c_str()); Pkt.WritePosition(Vector3i(a_Painting.GetPosX(), a_Painting.GetPosY(), a_Painting.GetPosZ())); - Pkt.WriteChar(a_Painting.GetDirection()); + Pkt.WriteChar(a_Painting.GetDirection());*/ } @@ -384,14 +407,14 @@ void cProtocol180::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize { ASSERT(m_State == 3); // In game mode? - /*// Serialize first, before creating the Packetizer (the packetizer locks a CS) + // Serialize first, before creating the Packetizer (the packetizer locks a CS) // This contains the flags and bitmasks, too const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_8_0); cPacketizer Pkt(*this, 0x21); // Chunk Data packet Pkt.WriteInt(a_ChunkX); Pkt.WriteInt(a_ChunkZ); - Pkt.WriteBuf(ChunkData.data(), ChunkData.size());*/ + Pkt.WriteBuf(ChunkData.data(), ChunkData.size()); } @@ -451,7 +474,7 @@ void cProtocol180::SendChat(const AString & a_Message) void cProtocol180::SendChat(const cCompositeChat & a_Message) { ASSERT(m_State == 3); // In game mode? - + // Compose the complete Json string to send: Json::Value msg; cWorld * World = m_Client->GetPlayer()->GetWorld(); @@ -634,7 +657,10 @@ void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); AString Data; - a_ByteBuffer.ReadAll(Data); + if (!a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1)) + { + return; + } m_Client->HandlePluginMessage(Channel, Data); } @@ -896,3 +922,19 @@ void cProtocol180::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) + +void cProtocol180::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Locale); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ViewDistance); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ChatFlags); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ChatColors); + HANDLE_READ(a_ByteBuffer, ReadChar, char, SkinFlags); + + m_Client->SetLocale(Locale); + // TODO: Handle other values +} + + + + diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 6604cbc3e..5c6111958 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -54,6 +54,9 @@ public: cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); + virtual void SendLoginSuccess (void) override; + virtual void SendPlayerAbilities (void) override {} + virtual void SendWindowClose (const cWindow & a_Window) override {} virtual void SendPickupSpawn (const cPickup & a_Pickup) override {} virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override {} virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override {} @@ -105,6 +108,7 @@ protected: virtual void HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) override; } ; -- cgit v1.2.3 From 09ff17b71ea5659dc628d9d6e3f1fd308d10037a Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 8 Sep 2014 00:36:30 +0200 Subject: Implemented packet compression. ChunkData packet needs this. --- src/Protocol/ChunkDataSerializer.cpp | 83 +++++++++++++++++++++++++++--------- src/Protocol/ChunkDataSerializer.h | 4 +- src/Protocol/Protocol125.cpp | 2 +- src/Protocol/Protocol132.cpp | 2 +- src/Protocol/Protocol17x.cpp | 26 ++++++++++- src/Protocol/Protocol18x.cpp | 34 ++++++++++----- src/Protocol/Protocol18x.h | 1 + 7 files changed, 117 insertions(+), 35 deletions(-) diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index 29e32ce32..a2e0c9ef9 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -8,6 +8,7 @@ #include "Globals.h" #include "ChunkDataSerializer.h" #include "zlib/zlib.h" +#include "ByteBuffer.h" @@ -30,7 +31,7 @@ cChunkDataSerializer::cChunkDataSerializer( -const AString & cChunkDataSerializer::Serialize(int a_Version) +const AString & cChunkDataSerializer::Serialize(int a_Version, int a_ChunkX, int a_ChunkZ) { Serializations::const_iterator itr = m_Serializations.find(a_Version); if (itr != m_Serializations.end()) @@ -43,7 +44,7 @@ const AString & cChunkDataSerializer::Serialize(int a_Version) { case RELEASE_1_2_5: Serialize29(data); break; case RELEASE_1_3_2: Serialize39(data); break; - case RELEASE_1_8_0: Serialize80(data); break; + case RELEASE_1_8_0: Serialize80(data, a_ChunkX, a_ChunkZ); break; // TODO: Other protocol versions may serialize the data differently; implement here default: @@ -176,45 +177,87 @@ void cChunkDataSerializer::Serialize39(AString & a_Data) -void cChunkDataSerializer::Serialize80(AString & a_Data) +void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_ChunkZ) { // TODO: Do not copy data and then compress it; rather, compress partial blocks of data (zlib *can* stream) // Blocktypes converter (1.8 included the meta into the blocktype): - unsigned short Blocks[ARRAYCOUNT(m_BlockTypes)]; + /*unsigned short Blocks[ARRAYCOUNT(m_BlockTypes)]; for (size_t Index = 0; Index < cChunkDef::NumBlocks; Index++) { BLOCKTYPE BlockType = m_BlockTypes[Index]; NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; Blocks[Index] = ((unsigned short)BlockType << 4) | ((unsigned short)BlockMeta); - } + }*/ const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; - const int BlockLightOffset = sizeof(Blocks); + const int MetadataOffset = sizeof(m_BlockTypes); + const int BlockLightOffset = MetadataOffset + sizeof(m_BlockMetas); const int SkyLightOffset = BlockLightOffset + sizeof(m_BlockLight); const int BiomeOffset = SkyLightOffset + sizeof(m_BlockSkyLight); const int DataSize = BiomeOffset + BiomeDataSize; // Temporary buffer for the composed data: char AllData [DataSize]; - memcpy(AllData, Blocks, sizeof(Blocks)); + memcpy(AllData, m_BlockTypes, sizeof(m_BlockTypes)); + memcpy(AllData + MetadataOffset, m_BlockMetas, sizeof(m_BlockMetas)); memcpy(AllData + BlockLightOffset, m_BlockLight, sizeof(m_BlockLight)); memcpy(AllData + SkyLightOffset, m_BlockSkyLight, sizeof(m_BlockSkyLight)); memcpy(AllData + BiomeOffset, m_BiomeData, BiomeDataSize); - // Put all those data into a_Data: - a_Data.push_back('\x01'); // "Ground-up continuous", or rather, "biome data present" flag - - // Two bitmaps; we're aways sending the full chunk with no additional data, so the bitmaps are 0xffff and 0, respectively - // Also, no endian flipping is needed because of the const values - unsigned short BitMap = 0xffff; - a_Data.append((const char *)&BitMap, sizeof(unsigned short)); - - // Write chunk size: - UInt32 ChunkSize = htonl((UInt32)DataSize); - a_Data.append((const char *)&ChunkSize, 4); - - a_Data.append(AllData, DataSize); // Chunk data + cByteBuffer Packet(512 KiB); + Packet.WriteVarInt(0x21); // Packet id (Chunk Data packet) + Packet.WriteBEInt(a_ChunkX); + Packet.WriteBEInt(a_ChunkZ); + Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag + Packet.WriteBEShort(0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff + Packet.WriteVarInt(DataSize); // Chunk size + Packet.WriteBuf(AllData, DataSize); // Chunk data + + AString PacketData; + Packet.ReadAll(PacketData); + Packet.CommitRead(); + + cByteBuffer NumberBuffer(20); + if (PacketData.size() >= 256) + { + AString PostData; + NumberBuffer.WriteVarInt(PacketData.size()); + NumberBuffer.ReadAll(PostData); + NumberBuffer.CommitRead(); + + // Compress the data: + const uLongf CompressedMaxSize = 200000; + char CompressedData[CompressedMaxSize]; + + uLongf CompressedSize = compressBound(PacketData.size()); + // Run-time check that our compile-time guess about CompressedMaxSize was enough: + ASSERT(CompressedSize <= CompressedMaxSize); + compress2((Bytef*)CompressedData, &CompressedSize, (const Bytef*)PacketData.data(), PacketData.size(), Z_DEFAULT_COMPRESSION); + + NumberBuffer.WriteVarInt(CompressedSize + PostData.size()); + NumberBuffer.WriteVarInt(PacketData.size()); + NumberBuffer.ReadAll(PostData); + NumberBuffer.CommitRead(); + + a_Data.clear(); + a_Data.resize(PostData.size() + CompressedSize); + a_Data.append(PostData.data(), PostData.size()); + a_Data.append(CompressedData, CompressedSize); + } + else + { + AString PostData; + NumberBuffer.WriteVarInt(Packet.GetUsedSpace() + 1); + NumberBuffer.WriteVarInt(0); + NumberBuffer.ReadAll(PostData); + NumberBuffer.CommitRead(); + + a_Data.clear(); + a_Data.resize(PostData.size() + PacketData.size()); + a_Data.append(PostData.data(), PostData.size()); + a_Data.append(PacketData.data(), PacketData.size()); + } } diff --git a/src/Protocol/ChunkDataSerializer.h b/src/Protocol/ChunkDataSerializer.h index 4c33aede1..3caa89d41 100644 --- a/src/Protocol/ChunkDataSerializer.h +++ b/src/Protocol/ChunkDataSerializer.h @@ -24,7 +24,7 @@ protected: void Serialize29(AString & a_Data); // Release 1.2.4 and 1.2.5 void Serialize39(AString & a_Data); // Release 1.3.1 to 1.7.10 - void Serialize80(AString & a_Data); // Release 1.8 + void Serialize80(AString & a_Data, int a_ChunkX, int a_ChunkZ); // Release 1.8 public: enum @@ -42,7 +42,7 @@ public: const unsigned char * a_BiomeData ); - const AString & Serialize(int a_Version); // Returns one of the internal m_Serializations[] + const AString & Serialize(int a_Version, int a_ChunkX, int a_ChunkZ); // Returns one of the internal m_Serializations[] } ; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index a66c64309..a74be28a5 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -262,7 +262,7 @@ void cProtocol125::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize SendPreChunk(a_ChunkX, a_ChunkZ, true); // Send the chunk data: - AString Serialized = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_2_5); + AString Serialized = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_2_5, a_ChunkX, a_ChunkZ); WriteByte(PACKET_MAP_CHUNK); WriteInt (a_ChunkX); WriteInt (a_ChunkZ); diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index 5c58ab0ba..5fd2655b8 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -176,7 +176,7 @@ void cProtocol132::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize // Pre-chunk not used in 1.3.2. Finally. // Send the chunk data: - AString Serialized = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2); + AString Serialized = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2, a_ChunkX, a_ChunkZ); WriteByte(PACKET_CHUNK_DATA); WriteInt (a_ChunkX); WriteInt (a_ChunkZ); diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index b4f30b639..0bee40028 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -346,7 +346,7 @@ void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize // Serialize first, before creating the Packetizer (the packetizer locks a CS) // This contains the flags and bitmasks, too - const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2); + const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2, a_ChunkX, a_ChunkZ); cPacketizer Pkt(*this, 0x21); // Chunk Data packet Pkt.WriteInt(a_ChunkX); @@ -1533,6 +1533,17 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) // Write one NUL extra, so that we can detect over-reads bb.Write("\0", 1); + // 1.8 - Compressed packets + if (m_State == 3) + { + UInt32 CompressedSize; + if (!bb.ReadVarInt(CompressedSize)) + { + // Not enough data + break; + } + } + UInt32 PacketType; if (!bb.ReadVarInt(PacketType)) { @@ -2511,10 +2522,23 @@ cProtocol172::cPacketizer::~cPacketizer() // Send the packet length UInt32 PacketLen = (UInt32)m_Out.GetUsedSpace(); + if (m_Protocol.m_State == 3) + { + PacketLen += 1; + } + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); m_Protocol.SendData(DataToSend.data(), DataToSend.size()); m_Protocol.m_OutPacketLenBuffer.CommitRead(); + + if (m_Protocol.m_State == 3) + { + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(0); + m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); + m_Protocol.SendData(DataToSend.data(), DataToSend.size()); + m_Protocol.m_OutPacketLenBuffer.CommitRead(); + } // Send the packet data: m_Out.ReadAll(DataToSend); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index a3e72d4dd..bcb5c2036 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -13,6 +13,7 @@ Implements the 1.8.x protocol classes: #include "json/json.h" #include "ChunkDataSerializer.h" #include "Protocol18x.h" +#include "zlib/zlib.h" #include "../ClientHandle.h" #include "../CompositeChat.h" @@ -21,7 +22,7 @@ Implements the 1.8.x protocol classes: #include "../World.h" #include "../Entities/Player.h" -#include "Entities/Painting.h" +#include "../Entities/Painting.h" @@ -57,23 +58,38 @@ cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAdd +void cProtocol180::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x28); // Effect packet + Pkt.WriteInt(a_EffectID); + Pkt.WritePosition(Vector3i(a_SrcX, a_SrcY, a_SrcZ)); + Pkt.WriteInt(a_Data); + Pkt.WriteBool(false); +} + + + + + void cProtocol180::SendLoginSuccess(void) { ASSERT(m_State == 2); // State: login? - // Disable compression: + // Enable compression: { cPacketizer Pkt(*this, 0x03); // Set compression packet - Pkt.WriteVarInt(-1); + Pkt.WriteVarInt(256); } + m_State = 3; // State = Game + { cPacketizer Pkt(*this, 0x02); // Login success packet Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID())); Pkt.WriteString(m_Client->GetUsername()); } - - m_State = 3; // State = Game } @@ -409,12 +425,10 @@ void cProtocol180::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize // Serialize first, before creating the Packetizer (the packetizer locks a CS) // This contains the flags and bitmasks, too - const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_8_0); + const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_8_0, a_ChunkX, a_ChunkZ); - cPacketizer Pkt(*this, 0x21); // Chunk Data packet - Pkt.WriteInt(a_ChunkX); - Pkt.WriteInt(a_ChunkZ); - Pkt.WriteBuf(ChunkData.data(), ChunkData.size()); + cCSLock Lock(m_CSPacket); + SendData(ChunkData.data(), ChunkData.size()); } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 5c6111958..d64742939 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -54,6 +54,7 @@ public: cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); + virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendLoginSuccess (void) override; virtual void SendPlayerAbilities (void) override {} virtual void SendWindowClose (const cWindow & a_Window) override {} -- cgit v1.2.3 From 10a30a03e38116fe084138662bd59147331dd883 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 8 Sep 2014 11:35:21 +0200 Subject: Added GetProtocolVersion() to cProtocol. --- src/Protocol/Protocol.h | 7 ++++++- src/Protocol/Protocol125.cpp | 3 ++- src/Protocol/Protocol132.cpp | 2 ++ src/Protocol/Protocol14x.cpp | 9 +++------ src/Protocol/Protocol17x.cpp | 26 ++++++++++++-------------- src/Protocol/Protocol17x.h | 1 - src/Protocol/Protocol18x.cpp | 3 ++- src/Protocol/ProtocolRecognizer.cpp | 4 ++-- 8 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 8e1842ec1..5811e5bff 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -46,7 +46,8 @@ typedef unsigned char Byte; class cProtocol { public: - cProtocol(cClientHandle * a_Client) : + cProtocol(cClientHandle * a_Client, int a_ProtocolVersion) : + m_ProtocolVersion(a_ProtocolVersion), m_Client(a_Client) { } @@ -130,7 +131,11 @@ public: /// Returns the ServerID used for authentication through session.minecraft.net virtual AString GetAuthServerID(void) = 0; + /** Returns the protocol version of this protocol. */ + int GetProtocolVersion(void) const { return m_ProtocolVersion; } + protected: + int m_ProtocolVersion; cClientHandle * m_Client; cCriticalSection m_CSPacket; // Each SendXYZ() function must acquire this CS in order to send the whole packet at once diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index a74be28a5..77939d933 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -16,6 +16,7 @@ Documentation: #include "../ClientHandle.h" #include "../World.h" #include "ChunkDataSerializer.h" +#include "ProtocolRecognizer.h" #include "../Entities/Entity.h" #include "../Entities/ExpOrb.h" #include "../Mobs/Monster.h" @@ -132,7 +133,7 @@ typedef unsigned char Byte; cProtocol125::cProtocol125(cClientHandle * a_Client) : - super(a_Client), + super(a_Client, cProtocolRecognizer::PROTO_VERSION_1_2_5), m_ReceivedData(32 KiB), m_LastSentDimension(dimNotSet) { diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index 5fd2655b8..6fbc3a264 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "ChunkDataSerializer.h" +#include "ProtocolRecognizer.h" #include "Protocol132.h" #include "../Root.h" #include "../Server.h" @@ -78,6 +79,7 @@ cProtocol132::cProtocol132(cClientHandle * a_Client) : super(a_Client), m_IsEncrypted(false) { + m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_3_2; } diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp index 3b6b6a42a..2d737acb4 100644 --- a/src/Protocol/Protocol14x.cpp +++ b/src/Protocol/Protocol14x.cpp @@ -23,6 +23,7 @@ Implements the 1.4.x protocol classes representing these protocols: #include "../UI/Window.h" #include "../Entities/Pickup.h" #include "../Entities/FallingBlock.h" +#include "ProtocolRecognizer.h" #ifdef _MSC_VER #pragma warning(push) @@ -72,6 +73,7 @@ enum cProtocol142::cProtocol142(cClientHandle * a_Client) : super(a_Client) { + m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_4_2; } @@ -132,12 +134,6 @@ void cProtocol142::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) { - if (!a_DoDaylightCycle) - { - // When writing a "-" before the number the client ignores it but it will stop the client-side time expiration. - a_TimeOfDay = std::min(-a_TimeOfDay, -1LL); - } - cCSLock Lock(m_CSPacket); WriteByte (PACKET_UPDATE_TIME); WriteInt64(a_WorldAge); @@ -156,6 +152,7 @@ void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_Do cProtocol146::cProtocol146(cClientHandle * a_Client) : super(a_Client) { + m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_4_6; } diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 0bee40028..e34a61818 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -12,6 +12,7 @@ Implements the 1.7.x protocol classes: #include "Globals.h" #include "json/json.h" #include "Protocol17x.h" +#include "ProtocolRecognizer.h" #include "ChunkDataSerializer.h" #include "PolarSSL++/Sha1Checksum.h" @@ -92,7 +93,7 @@ extern bool g_ShouldLogCommIn, g_ShouldLogCommOut; // cProtocol172: cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : - super(a_Client), + super(a_Client, cProtocolRecognizer::PROTO_VERSION_1_7_2), m_ServerAddress(a_ServerAddress), m_ServerPort(a_ServerPort), m_State(a_State), @@ -1534,7 +1535,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) bb.Write("\0", 1); // 1.8 - Compressed packets - if (m_State == 3) + if ((m_State == 3) && (GetProtocolVersion() == cProtocolRecognizer::PROTO_VERSION_1_8_0)) { UInt32 CompressedSize; if (!bb.ReadVarInt(CompressedSize)) @@ -2522,23 +2523,19 @@ cProtocol172::cPacketizer::~cPacketizer() // Send the packet length UInt32 PacketLen = (UInt32)m_Out.GetUsedSpace(); - if (m_Protocol.m_State == 3) + + if ((m_Protocol.m_State == 3) && (m_Protocol.GetProtocolVersion() == cProtocolRecognizer::PROTO_VERSION_1_8_0)) { - PacketLen += 1; + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen + 1); + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(0); + } + else + { + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); } - - m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); m_Protocol.SendData(DataToSend.data(), DataToSend.size()); m_Protocol.m_OutPacketLenBuffer.CommitRead(); - - if (m_Protocol.m_State == 3) - { - m_Protocol.m_OutPacketLenBuffer.WriteVarInt(0); - m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); - m_Protocol.SendData(DataToSend.data(), DataToSend.size()); - m_Protocol.m_OutPacketLenBuffer.CommitRead(); - } // Send the packet data: m_Out.ReadAll(DataToSend); @@ -3080,6 +3077,7 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity) cProtocol176::cProtocol176(cClientHandle * a_Client, const AString &a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : super(a_Client, a_ServerAddress, a_ServerPort, a_State) { + m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_7_6; } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index d715e1cec..289545bc7 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -211,7 +211,6 @@ protected: } void WriteItem(const cItem & a_Item); - void WriteItem180(const cItem & a_Item); void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index bcb5c2036..302fcc836 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -12,8 +12,8 @@ Implements the 1.8.x protocol classes: #include "Bindings/PluginManager.h" #include "json/json.h" #include "ChunkDataSerializer.h" +#include "ProtocolRecognizer.h" #include "Protocol18x.h" -#include "zlib/zlib.h" #include "../ClientHandle.h" #include "../CompositeChat.h" @@ -52,6 +52,7 @@ class cProtocol176; cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : super(a_Client, a_ServerAddress, a_ServerPort, a_State) { + m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_8_0; } diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 642e96880..c535390cc 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -26,7 +26,7 @@ cProtocolRecognizer::cProtocolRecognizer(cClientHandle * a_Client) : - super(a_Client), + super(a_Client, 0), m_Protocol(NULL), m_Buffer(512) { @@ -915,7 +915,7 @@ bool cProtocolRecognizer::TryRecognizeLengthlessProtocol(void) m_Protocol = new cProtocol132(m_Client); return true; } - case PROTO_VERSION_1_4_2: + //case PROTO_VERSION_1_4_2: case PROTO_VERSION_1_4_4: { m_Protocol = new cProtocol142(m_Client); -- cgit v1.2.3 From 38124bcce3c5e8ed8e4dba904dc4f15f89a82c14 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 8 Sep 2014 12:24:06 +0200 Subject: Updated chunk sending to 1.8 --- src/Protocol/ChunkDataSerializer.cpp | 17 +++++++++-------- src/Protocol/Protocol17x.cpp | 12 ++++++------ src/Protocol/Protocol18x.cpp | 17 +++++++---------- src/Protocol/Protocol18x.h | 2 -- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index a2e0c9ef9..d4574954e 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -182,25 +182,26 @@ void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_Chu // TODO: Do not copy data and then compress it; rather, compress partial blocks of data (zlib *can* stream) // Blocktypes converter (1.8 included the meta into the blocktype): - /*unsigned short Blocks[ARRAYCOUNT(m_BlockTypes)]; + unsigned char Blocks[cChunkDef::NumBlocks * 2]; + size_t LastOffset = 0; for (size_t Index = 0; Index < cChunkDef::NumBlocks; Index++) { - BLOCKTYPE BlockType = m_BlockTypes[Index]; + BLOCKTYPE BlockType = m_BlockTypes[Index] & 0xFF; NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; - Blocks[Index] = ((unsigned short)BlockType << 4) | ((unsigned short)BlockMeta); - }*/ + Blocks[LastOffset] = (BlockType << 4) | ((unsigned char)BlockMeta); + Blocks[LastOffset + 1] = (unsigned char)BlockType >> 4; + LastOffset += 2; + } const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; - const int MetadataOffset = sizeof(m_BlockTypes); - const int BlockLightOffset = MetadataOffset + sizeof(m_BlockMetas); + const int BlockLightOffset = sizeof(Blocks); const int SkyLightOffset = BlockLightOffset + sizeof(m_BlockLight); const int BiomeOffset = SkyLightOffset + sizeof(m_BlockSkyLight); const int DataSize = BiomeOffset + BiomeDataSize; // Temporary buffer for the composed data: char AllData [DataSize]; - memcpy(AllData, m_BlockTypes, sizeof(m_BlockTypes)); - memcpy(AllData + MetadataOffset, m_BlockMetas, sizeof(m_BlockMetas)); + memcpy(AllData, Blocks, sizeof(Blocks)); memcpy(AllData + BlockLightOffset, m_BlockLight, sizeof(m_BlockLight)); memcpy(AllData + SkyLightOffset, m_BlockSkyLight, sizeof(m_BlockSkyLight)); memcpy(AllData + BiomeOffset, m_BiomeData, BiomeDataSize); diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index e34a61818..34bfbc82b 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1503,14 +1503,14 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) ); m_CommLogFile.Flush(); } - + if (!m_ReceivedData.Write(a_Data, a_Size)) { // Too much data in the incoming queue, report to caller: m_Client->PacketBufferFull(); return; } - + // Handle all complete packets: for (;;) { @@ -1530,10 +1530,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) cByteBuffer bb(PacketLen + 1); VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); m_ReceivedData.CommitRead(); - - // Write one NUL extra, so that we can detect over-reads - bb.Write("\0", 1); - + // 1.8 - Compressed packets if ((m_State == 3) && (GetProtocolVersion() == cProtocolRecognizer::PROTO_VERSION_1_8_0)) { @@ -1544,6 +1541,9 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) break; } } + + // Write one NUL extra, so that we can detect over-reads + bb.Write("\0", 1); UInt32 PacketType; if (!bb.ReadVarInt(PacketType)) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 302fcc836..386e3dfb2 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -121,7 +121,7 @@ void cProtocol180::SendPlayerMoveLook(void) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x08); // Player Position And Look packet + cPacketizer Pkt(*this, 0x08); // Player Position And Look packet cPlayer * Player = m_Client->GetPlayer(); Pkt.WriteDouble(Player->GetPosX()); @@ -131,7 +131,7 @@ void cProtocol180::SendPlayerMoveLook(void) Pkt.WriteDouble(Player->GetPosZ()); Pkt.WriteFloat((float)Player->GetYaw()); Pkt.WriteFloat((float)Player->GetPitch()); - Pkt.WriteByte(0);*/ + Pkt.WriteByte(0); } @@ -168,12 +168,12 @@ void cProtocol180::SendEntityVelocity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x12); // Entity Velocity packet + cPacketizer Pkt(*this, 0x12); // Entity Velocity packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); // 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400));*/ + Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); } @@ -395,9 +395,9 @@ void cProtocol180::SendPluginMessage(const AString & a_Channel, const AString & { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x3f); + cPacketizer Pkt(*this, 0x3f); Pkt.WriteString(a_Channel); - Pkt.WriteBuf(a_Message.data(), a_Message.size());*/ + Pkt.WriteBuf(a_Message.data(), a_Message.size()); } @@ -672,10 +672,7 @@ void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); AString Data; - if (!a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1)) - { - return; - } + a_ByteBuffer.ReadAll(Data); m_Client->HandlePluginMessage(Channel, Data); } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index d64742939..d9fd5d573 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -56,8 +56,6 @@ public: virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendLoginSuccess (void) override; - virtual void SendPlayerAbilities (void) override {} - virtual void SendWindowClose (const cWindow & a_Window) override {} virtual void SendPickupSpawn (const cPickup & a_Pickup) override {} virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override {} virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override {} -- cgit v1.2.3 From 8f8693a71eb896ccc7c14c4033ae8d07dae27ac3 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 8 Sep 2014 17:02:54 +0200 Subject: Fixed more 1.8 packets. --- src/ByteBuffer.cpp | 44 ++++++++++ src/ByteBuffer.h | 5 ++ src/ClientHandle.cpp | 33 +++++--- src/Protocol/Protocol17x.cpp | 59 ++++++++----- src/Protocol/Protocol17x.h | 14 ++-- src/Protocol/Protocol18x.cpp | 196 +++++++++++++++++++++++++++++++++++++++++-- src/Protocol/Protocol18x.h | 9 +- 7 files changed, 313 insertions(+), 47 deletions(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index 96556bf61..94684afb8 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -489,6 +489,24 @@ bool cByteBuffer::ReadLEInt(int & a_Value) +bool cByteBuffer::ReadPosition(int & a_BlockX, int & a_BlockY, int & a_BlockZ) +{ + Int64 Value; + if (!ReadBEInt64(Value)) + { + return false; + } + + a_BlockX = Value >> 38; + a_BlockY = Value << 26 >> 52; + a_BlockZ = Value << 38 >> 38; + return true; +} + + + + + bool cByteBuffer::WriteChar(char a_Value) { CHECK_THREAD; @@ -661,6 +679,15 @@ bool cByteBuffer::WriteLEInt(int a_Value) +bool cByteBuffer::WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + return WriteBEInt64(((Int64)a_BlockX & 0x3FFFFFF) << 38 | ((Int64)a_BlockY & 0xFFF) << 26 | ((Int64)a_BlockZ & 0x3FFFFFF)); +} + + + + + bool cByteBuffer::ReadBuf(void * a_Buffer, size_t a_Count) { CHECK_THREAD; @@ -792,6 +819,23 @@ bool cByteBuffer::SkipRead(size_t a_Count) +bool cByteBuffer::ReverseRead(size_t a_Count) +{ + CHECK_THREAD; + CheckValid(); + if (m_ReadPos < a_Count) + { + return false; + } + + m_ReadPos -= a_Count; + return true; +} + + + + + void cByteBuffer::ReadAll(AString & a_Data) { CHECK_THREAD; diff --git a/src/ByteBuffer.h b/src/ByteBuffer.h index adaa00330..e200d2a7b 100644 --- a/src/ByteBuffer.h +++ b/src/ByteBuffer.h @@ -64,6 +64,7 @@ public: bool ReadVarInt (UInt32 & a_Value); bool ReadVarUTF8String (AString & a_Value); // string length as VarInt, then string as UTF-8 bool ReadLEInt (int & a_Value); + bool ReadPosition (int & a_BlockX, int & a_BlockY, int & a_BlockZ); /** Reads VarInt, assigns it to anything that can be assigned from an UInt32 (unsigned short, char, Byte, double, ...) */ template bool ReadVarInt(T & a_Value) @@ -90,6 +91,7 @@ public: bool WriteVarInt (UInt32 a_Value); bool WriteVarUTF8String (const AString & a_Value); // string length as VarInt, then string as UTF-8 bool WriteLEInt (int a_Value); + bool WritePosition (int a_BlockX, int a_BlockY, int a_BlockZ); /** Reads a_Count bytes into a_Buffer; returns true if successful */ bool ReadBuf(void * a_Buffer, size_t a_Count); @@ -105,6 +107,9 @@ public: /** Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer */ bool SkipRead(size_t a_Count); + + /** Reverse reading by a_Count bytes; returns false if not enough readed bytes in the ringbuffer */ + bool ReverseRead(size_t a_Count); /** Reads all available data into a_Data */ void ReadAll(AString & a_Data); diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 4a768771e..4c36dec4d 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1198,6 +1198,12 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e cWorld * World = m_Player->GetWorld(); + // 1.8 protocol fix + if ((int)a_BlockFace == 255) + { + a_BlockFace = BLOCK_FACE_NONE; + } + if ( (a_BlockFace != BLOCK_FACE_NONE) && // The client is interacting with a specific block ( @@ -1268,22 +1274,25 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e return; } - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta); - cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType); - - if (BlockHandler->IsUseable() && !m_Player->IsCrouched()) + if ((Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() <= 5) { - if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta); + cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType); + + if (BlockHandler->IsUseable() && !m_Player->IsCrouched()) { - // A plugin doesn't agree with using the block, abort + if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) + { + // A plugin doesn't agree with using the block, abort + return; + } + cChunkInterface ChunkInterface(World->GetChunkMap()); + BlockHandler->OnUse(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); + PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta); return; } - cChunkInterface ChunkInterface(World->GetChunkMap()); - BlockHandler->OnUse(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); - PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta); - return; } short EquippedDamage = Equipped.m_ItemDamage; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 34bfbc82b..9a7111a43 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1567,7 +1567,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) PacketType, PacketType, PacketLen, PacketLen, m_State, PacketDataHex.c_str() ); } - + if (!HandlePacket(bb, PacketType)) { // Unknown packet, already been reported, but without the length. Log the length here: @@ -1592,7 +1592,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) return; } - + if (bb.GetReadableSpace() != 1) { // Read more or less than packet length, report as error @@ -1613,7 +1613,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) m_Client->PacketError(PacketType); } } // for (ever) - + // Log any leftover bytes into the logfile: if (g_ShouldLogCommIn && (m_ReceivedData.GetReadableSpace() > 0)) { @@ -2332,25 +2332,32 @@ bool cProtocol172::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) -void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) +void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata, bool a_IsCompressed) { - // Uncompress the GZIPped data: - AString Uncompressed; - if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Uncompressed) != Z_OK) + AString Metadata; + if (a_IsCompressed) { - AString HexDump; - CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); - LOGWARNING("Cannot unGZIP item metadata (" SIZE_T_FMT " bytes):\n%s", a_Metadata.size(), HexDump.c_str()); - return; + // Uncompress the GZIPped data: + if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Metadata) != Z_OK) + { + AString HexDump; + CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); + LOGWARNING("Cannot unGZIP item metadata (" SIZE_T_FMT " bytes):\n%s", a_Metadata.size(), HexDump.c_str()); + return; + } + } + else + { + Metadata = a_Metadata; } // Parse into NBT: - cParsedNBT NBT(Uncompressed.data(), Uncompressed.size()); + cParsedNBT NBT(Metadata.data(), Metadata.size()); if (!NBT.IsValid()) { AString HexDump; - CreateHexDump(HexDump, Uncompressed.data(), Uncompressed.size(), 16); - LOGWARNING("Cannot parse NBT item metadata: (" SIZE_T_FMT " bytes)\n%s", Uncompressed.size(), HexDump.c_str()); + CreateHexDump(HexDump, Metadata.data(), Metadata.size(), 16); + LOGWARNING("Cannot parse NBT item metadata: (" SIZE_T_FMT " bytes)\n%s", Metadata.size(), HexDump.c_str()); return; } @@ -2580,7 +2587,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR)) { - WriteShort(-1); + WriteChar(0); return; } @@ -2626,10 +2633,24 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, (ENUM_ITEM_ID)a_Item.m_ItemType); } Writer.Finish(); - AString Compressed; - CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); - WriteShort((short)Compressed.size()); - WriteBuf(Compressed.data(), Compressed.size()); + + AString Result = Writer.GetResult(); + if (m_Protocol.GetProtocolVersion() == cProtocolRecognizer::PROTO_VERSION_1_8_0) + { + if (Result.size() == 0) + { + WriteChar(0); + return; + } + WriteBuf(Result.data(), Result.size()); + } + else + { + AString Compressed; + CompressStringGZIP(Result.data(), Result.size(), Compressed); + WriteShort((short)Compressed.size()); + WriteBuf(Compressed.data(), Compressed.size()); + } } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 289545bc7..1e716a761 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -200,9 +200,9 @@ protected: m_Out.WriteVarUTF8String(a_Value); } - void WritePosition(const Vector3i a_Position) + void WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ) { - WriteInt64(((Int64)a_Position.x & 0x3FFFFFF) << 38 | ((Int64)a_Position.y & 0xFFF) << 26 | ((Int64)a_Position.z & 0x3FFFFFF)); + m_Out.WritePosition(a_BlockX, a_BlockY, a_BlockZ); } void WriteBuf(const char * a_Data, size_t a_Size) @@ -273,12 +273,12 @@ protected: // Packet handlers while in the Game state (m_State == 3): void HandlePacketAnimation (cByteBuffer & a_ByteBuffer); - void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); - void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); void HandlePacketChatMessage (cByteBuffer & a_ByteBuffer); virtual void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); virtual void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); - void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); + virtual void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); virtual void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); virtual void HandlePacketKeepAlive (cByteBuffer & a_ByteBuffer); void HandlePacketPlayer (cByteBuffer & a_ByteBuffer); @@ -306,10 +306,10 @@ protected: void SendCompass(const cWorld & a_World); /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */ - bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item); + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item); /** Parses item metadata as read by ReadItem(), into the item enchantments. */ - void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); + void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata, bool a_IsCompressed = true); void StartEncryption(const Byte * a_Key); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 386e3dfb2..ffa8d5ecb 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -39,6 +39,21 @@ Implements the 1.8.x protocol classes: +#define HANDLE_PACKET_READ(ByteBuf, Proc, Type, Var) \ + Type Var; \ + { \ + if (!ByteBuf.Proc(Var)) \ + { \ + ByteBuf.CheckValid(); \ + return false; \ + } \ + ByteBuf.CheckValid(); \ + } + + + + + const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... class cProtocol176; @@ -59,13 +74,83 @@ cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAdd +void cProtocol180::SendPlayerSpawn(const cPlayer & a_Player) +{ + // Called to spawn another player for the client + cPacketizer Pkt(*this, 0x0c); // Spawn Player packet + Pkt.WriteVarInt(a_Player.GetUniqueID()); + + // Send UUID: + AString UUID = cMojangAPI::MakeUUIDShort(a_Player.GetClientHandle()->GetUUID()); + + Int64 MostSignificantBits = 0; + Int64 LeastSignificantBits = 0; + + for (size_t i = 0; i < UUID.length(); i++) + { + MostSignificantBits += (UUID[i] & 0xff) >> 7; + LeastSignificantBits += UUID[i] & 1; + } + Pkt.WriteInt64(4053239666997989821); + Pkt.WriteInt64(-5603022497796657139); + LOG("Bits: %i, %i", (int)MostSignificantBits, (int)LeastSignificantBits); + + // Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID())); + + Pkt.WriteFPInt(a_Player.GetPosX()); + Pkt.WriteFPInt(a_Player.GetPosY()); + Pkt.WriteFPInt(a_Player.GetPosZ()); + Pkt.WriteByteAngle(a_Player.GetYaw()); + Pkt.WriteByteAngle(a_Player.GetPitch()); + short ItemType = a_Player.GetEquippedItem().IsEmpty() ? 0 : a_Player.GetEquippedItem().m_ItemType; + Pkt.WriteShort(ItemType); + Pkt.WriteByte((3 << 5) | 6); // Metadata: float + index 6 + Pkt.WriteFloat((float)a_Player.GetHealth()); + Pkt.WriteByte((4 << 5 | (2 & 0x1F)) & 0xFF); + Pkt.WriteString(a_Player.GetName()); + Pkt.WriteByte(0x7f); // Metadata: end +} + + + + + +void cProtocol180::SendPlayerMaxSpeed(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x20); // Entity Properties + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteVarInt(Player->GetUniqueID()); + Pkt.WriteInt(1); // Count + Pkt.WriteString("generic.movementSpeed"); + // The default game speed is 0.1, multiply that value by the relative speed: + Pkt.WriteDouble(0.1 * Player->GetNormalMaxSpeed()); + if (Player->IsSprinting()) + { + Pkt.WriteVarInt(1); // Modifier count + Pkt.WriteInt64(0x662a6b8dda3e4c1c); + Pkt.WriteInt64(0x881396ea6097278d); // UUID of the modifier + Pkt.WriteDouble(Player->GetSprintingMaxSpeed() - Player->GetNormalMaxSpeed()); + Pkt.WriteByte(2); + } + else + { + Pkt.WriteVarInt(0); // Modifier count + } +} + + + + + void cProtocol180::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x28); // Effect packet Pkt.WriteInt(a_EffectID); - Pkt.WritePosition(Vector3i(a_SrcX, a_SrcY, a_SrcZ)); + Pkt.WritePosition(a_SrcX, a_SrcY, a_SrcZ); Pkt.WriteInt(a_Data); Pkt.WriteBool(false); } @@ -144,7 +229,7 @@ void cProtocol180::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bloc cPacketizer Pkt(*this, 0x0a); Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WritePosition(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); } @@ -441,7 +526,7 @@ void cProtocol180::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLO ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x23); // Block Change packet - Pkt.WritePosition(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); UInt32 Block = ((UInt32)a_BlockType << 4) | ((UInt32)a_BlockMeta & 15); Pkt.WriteVarInt(Block); @@ -624,8 +709,7 @@ void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) // Send the spawn position: { cPacketizer Pkt(*this, 0x05); // Spawn Position packet - Vector3i Position(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); - Pkt.WritePosition(Position); + Pkt.WritePosition(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); } // Send player abilities: @@ -636,6 +720,61 @@ void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) +bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) +{ + HANDLE_PACKET_READ(a_ByteBuffer, ReadBEShort, short, ItemType); + if (ItemType == -1) + { + // The item is empty, no more data follows + a_Item.Empty(); + return true; + } + a_Item.m_ItemType = ItemType; + + HANDLE_PACKET_READ(a_ByteBuffer, ReadChar, char, ItemCount); + HANDLE_PACKET_READ(a_ByteBuffer, ReadBEShort, short, ItemDamage); + a_Item.m_ItemCount = ItemCount; + a_Item.m_ItemDamage = ItemDamage; + if (ItemCount <= 0) + { + a_Item.Empty(); + } + + HANDLE_PACKET_READ(a_ByteBuffer, ReadChar, char, FirstChar); + if (FirstChar == 0) + { + // No metadata + return true; + } + a_ByteBuffer.ReverseRead(1); + + // Read the metadata + AString Metadata; + a_ByteBuffer.ReadAll(Metadata); + + ParseItemMetadata(a_Item, Metadata, false); + return true; +} + + + + + +void cProtocol180::HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEShort, short, SlotNum); + cItem Item; + if (!ReadItem(a_ByteBuffer, Item)) + { + return; + } + m_Client->HandleCreativeInventory(SlotNum, Item); +} + + + + + void cProtocol180::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadChar, char, ActionID); @@ -672,7 +811,10 @@ void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); AString Data; - a_ByteBuffer.ReadAll(Data); + if (!a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1)) + { + return; + } m_Client->HandlePluginMessage(Channel, Data); } @@ -940,7 +1082,7 @@ void cProtocol180::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Locale); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ViewDistance); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ChatFlags); - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ChatColors); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors); HANDLE_READ(a_ByteBuffer, ReadChar, char, SkinFlags); m_Client->SetLocale(Locale); @@ -950,3 +1092,43 @@ void cProtocol180::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) + +void cProtocol180::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) +{ + int BlockX, BlockY, BlockZ; + if (!a_ByteBuffer.ReadPosition(BlockX, BlockY, BlockZ)) + { + return; + } + + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Face); + cItem Item; + ReadItem(a_ByteBuffer, Item); + + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorX); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorY); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorZ); + m_Client->HandleRightClick(BlockX, BlockY, BlockZ, static_cast(Face), CursorX, CursorY, CursorZ, m_Client->GetPlayer()->GetEquippedItem()); +} + + + + + +void cProtocol180::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Status); + + int BlockX, BlockY, BlockZ; + if (!a_ByteBuffer.ReadPosition(BlockX, BlockY, BlockZ)) + { + return; + } + + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Face); + m_Client->HandleLeftClick(BlockX, BlockY, BlockZ, static_cast(Face), Status); +} + + + + diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index d9fd5d573..dc3739369 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -54,12 +54,12 @@ public: cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendPlayerMaxSpeed (void) override; virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendLoginSuccess (void) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override {} virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override {} - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override {} - virtual void SendWholeInventory (const cWindow & a_Window) override {} virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; virtual void SendPlayerMoveLook (void) override; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; @@ -92,6 +92,8 @@ public: protected: + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) override; + virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) override; // Packet handlers while in the Login state (m_State == 2): @@ -99,6 +101,7 @@ protected: virtual void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) override; // Packet handlers while in the Game state (m_State == 3): + virtual void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) override; @@ -108,6 +111,8 @@ protected: virtual void HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override; + virtual void HandlePacketBlockDig(cByteBuffer & a_ByteBuffer); } ; -- cgit v1.2.3 From fa2b69b3f36cdfa755f9c466abe49ece70303062 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 8 Sep 2014 17:08:28 +0200 Subject: 1.8: Fixed tab complete. --- src/Protocol/Protocol17x.h | 2 +- src/Protocol/Protocol18x.cpp | 17 +++++++++++++++++ src/Protocol/Protocol18x.h | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 1e716a761..f056f262a 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -289,7 +289,7 @@ protected: virtual void HandlePacketPluginMessage (cByteBuffer & a_ByteBuffer); void HandlePacketSlotSelect (cByteBuffer & a_ByteBuffer); virtual void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer); - void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer); + virtual void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer); void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer); virtual void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index ffa8d5ecb..eebac7a05 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1132,3 +1132,20 @@ void cProtocol180::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) + +void cProtocol180::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Text); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, HasPosition); + + if (HasPosition) + { + HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Position); + } + + m_Client->HandleTabCompletion(Text); +} + + + + diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index dc3739369..a3478e674 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -112,7 +112,8 @@ protected: virtual void HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketBlockDig(cByteBuffer & a_ByteBuffer); + virtual void HandlePacketBlockDig(cByteBuffer & a_ByteBuffer)override; + virtual void HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) override; } ; -- cgit v1.2.3 From e740739d0417c1c2e9693fba118b7a10e857a170 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 8 Sep 2014 19:24:33 +0200 Subject: Recoded cProtocol180 class. --- src/Protocol/Protocol17x.cpp | 72 +- src/Protocol/Protocol17x.h | 43 +- src/Protocol/Protocol18x.cpp | 3205 +++++++++++++++++++++++++++++++++--------- src/Protocol/Protocol18x.h | 307 +++- 4 files changed, 2864 insertions(+), 763 deletions(-) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 9a7111a43..0b94cb144 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1531,17 +1531,6 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); m_ReceivedData.CommitRead(); - // 1.8 - Compressed packets - if ((m_State == 3) && (GetProtocolVersion() == cProtocolRecognizer::PROTO_VERSION_1_8_0)) - { - UInt32 CompressedSize; - if (!bb.ReadVarInt(CompressedSize)) - { - // Not enough data - break; - } - } - // Write one NUL extra, so that we can detect over-reads bb.Write("\0", 1); @@ -2290,7 +2279,6 @@ void cProtocol172::SendData(const char * a_Data, size_t a_Size) - bool cProtocol172::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) { HANDLE_PACKET_READ(a_ByteBuffer, ReadBEShort, short, ItemType); @@ -2332,32 +2320,25 @@ bool cProtocol172::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) -void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata, bool a_IsCompressed) +void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) { - AString Metadata; - if (a_IsCompressed) + // Uncompress the GZIPped data: + AString Uncompressed; + if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Uncompressed) != Z_OK) { - // Uncompress the GZIPped data: - if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Metadata) != Z_OK) - { - AString HexDump; - CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); - LOGWARNING("Cannot unGZIP item metadata (" SIZE_T_FMT " bytes):\n%s", a_Metadata.size(), HexDump.c_str()); - return; - } - } - else - { - Metadata = a_Metadata; + AString HexDump; + CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); + LOGWARNING("Cannot unGZIP item metadata (" SIZE_T_FMT " bytes):\n%s", a_Metadata.size(), HexDump.c_str()); + return; } // Parse into NBT: - cParsedNBT NBT(Metadata.data(), Metadata.size()); + cParsedNBT NBT(Uncompressed.data(), Uncompressed.size()); if (!NBT.IsValid()) { AString HexDump; - CreateHexDump(HexDump, Metadata.data(), Metadata.size(), 16); - LOGWARNING("Cannot parse NBT item metadata: (" SIZE_T_FMT " bytes)\n%s", Metadata.size(), HexDump.c_str()); + CreateHexDump(HexDump, Uncompressed.data(), Uncompressed.size(), 16); + LOGWARNING("Cannot parse NBT item metadata: (" SIZE_T_FMT " bytes)\n%s", Uncompressed.size(), HexDump.c_str()); return; } @@ -2531,15 +2512,7 @@ cProtocol172::cPacketizer::~cPacketizer() // Send the packet length UInt32 PacketLen = (UInt32)m_Out.GetUsedSpace(); - if ((m_Protocol.m_State == 3) && (m_Protocol.GetProtocolVersion() == cProtocolRecognizer::PROTO_VERSION_1_8_0)) - { - m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen + 1); - m_Protocol.m_OutPacketLenBuffer.WriteVarInt(0); - } - else - { - m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); - } + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); m_Protocol.SendData(DataToSend.data(), DataToSend.size()); m_Protocol.m_OutPacketLenBuffer.CommitRead(); @@ -2634,23 +2607,10 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) } Writer.Finish(); - AString Result = Writer.GetResult(); - if (m_Protocol.GetProtocolVersion() == cProtocolRecognizer::PROTO_VERSION_1_8_0) - { - if (Result.size() == 0) - { - WriteChar(0); - return; - } - WriteBuf(Result.data(), Result.size()); - } - else - { - AString Compressed; - CompressStringGZIP(Result.data(), Result.size(), Compressed); - WriteShort((short)Compressed.size()); - WriteBuf(Compressed.data(), Compressed.size()); - } + AString Compressed; + CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); + WriteShort((short)Compressed.size()); + WriteBuf(Compressed.data(), Compressed.size()); } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index f056f262a..7955505f9 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -199,11 +199,6 @@ protected: { m_Out.WriteVarUTF8String(a_Value); } - - void WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ) - { - m_Out.WritePosition(a_BlockX, a_BlockY, a_BlockZ); - } void WriteBuf(const char * a_Data, size_t a_Size) { @@ -257,41 +252,41 @@ protected: /** Adds the received (unencrypted) data to m_ReceivedData, parses complete packets */ void AddReceivedData(const char * a_Data, size_t a_Size); - + /** Reads and handles the packet. The packet length and type have already been read. Returns true if the packet was understood, false if it was an unknown packet */ bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType); - + // Packet handlers while in the Status state (m_State == 1): void HandlePacketStatusPing(cByteBuffer & a_ByteBuffer); virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer); - + // Packet handlers while in the Login state (m_State == 2): - virtual void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer); - virtual void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer); + void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer); + void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer); // Packet handlers while in the Game state (m_State == 3): void HandlePacketAnimation (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); + void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); + void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); void HandlePacketChatMessage (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); - virtual void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketKeepAlive (cByteBuffer & a_ByteBuffer); + void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); + void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); + void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); + void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); + void HandlePacketKeepAlive (cByteBuffer & a_ByteBuffer); void HandlePacketPlayer (cByteBuffer & a_ByteBuffer); void HandlePacketPlayerAbilities (cByteBuffer & a_ByteBuffer); void HandlePacketPlayerLook (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketPlayerPos (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketPlayerPosLook (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketPluginMessage (cByteBuffer & a_ByteBuffer); + void HandlePacketPlayerPos (cByteBuffer & a_ByteBuffer); + void HandlePacketPlayerPosLook (cByteBuffer & a_ByteBuffer); + void HandlePacketPluginMessage (cByteBuffer & a_ByteBuffer); void HandlePacketSlotSelect (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer); + void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer); + void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer); void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer); - virtual void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); + void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer); void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer); void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer); @@ -309,7 +304,7 @@ protected: virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item); /** Parses item metadata as read by ReadItem(), into the item enchantments. */ - void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata, bool a_IsCompressed = true); + void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); void StartEncryption(const Byte * a_Key); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index eebac7a05..1793583a2 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -9,20 +9,41 @@ Implements the 1.8.x protocol classes: */ #include "Globals.h" -#include "Bindings/PluginManager.h" #include "json/json.h" -#include "ChunkDataSerializer.h" -#include "ProtocolRecognizer.h" #include "Protocol18x.h" +#include "ProtocolRecognizer.h" +#include "ChunkDataSerializer.h" +#include "PolarSSL++/Sha1Checksum.h" #include "../ClientHandle.h" -#include "../CompositeChat.h" #include "../Root.h" #include "../Server.h" #include "../World.h" +#include "../StringCompression.h" +#include "../CompositeChat.h" +#include "../Statistics.h" -#include "../Entities/Player.h" +#include "../WorldStorage/FastNBT.h" +#include "../WorldStorage/EnchantmentSerializer.h" + +#include "../Entities/ExpOrb.h" +#include "../Entities/Minecart.h" +#include "../Entities/FallingBlock.h" #include "../Entities/Painting.h" +#include "../Entities/Pickup.h" +#include "../Entities/Player.h" +#include "../Entities/ItemFrame.h" +#include "../Entities/ArrowEntity.h" +#include "../Entities/FireworkEntity.h" + +#include "../Mobs/IncludeAllMonsters.h" +#include "../UI/Window.h" + +#include "../BlockEntities/BeaconEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" +#include "../BlockEntities/MobHeadEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" +#include "Bindings/PluginManager.h" @@ -55,88 +76,63 @@ Implements the 1.8.x protocol classes: const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... -class cProtocol176; -//////////////////////////////////////////////////////////////////////////////// -// cProtocol180: +// fwd: main.cpp: +extern bool g_ShouldLogCommIn, g_ShouldLogCommOut; -cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : - super(a_Client, a_ServerAddress, a_ServerPort, a_State) -{ - m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_8_0; -} +//////////////////////////////////////////////////////////////////////////////// +// cProtocol180: -void cProtocol180::SendPlayerSpawn(const cPlayer & a_Player) +cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : + super(a_Client, cProtocolRecognizer::PROTO_VERSION_1_8_0), + m_ServerAddress(a_ServerAddress), + m_ServerPort(a_ServerPort), + m_State(a_State), + m_ReceivedData(32 KiB), + m_OutPacketBuffer(64 KiB), + m_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt + m_IsEncrypted(false), + m_LastSentDimension(dimNotSet) { - // Called to spawn another player for the client - cPacketizer Pkt(*this, 0x0c); // Spawn Player packet - Pkt.WriteVarInt(a_Player.GetUniqueID()); - - // Send UUID: - AString UUID = cMojangAPI::MakeUUIDShort(a_Player.GetClientHandle()->GetUUID()); - - Int64 MostSignificantBits = 0; - Int64 LeastSignificantBits = 0; - - for (size_t i = 0; i < UUID.length(); i++) + // Create the comm log file, if so requested: + if (g_ShouldLogCommIn || g_ShouldLogCommOut) { - MostSignificantBits += (UUID[i] & 0xff) >> 7; - LeastSignificantBits += UUID[i] & 1; + static int sCounter = 0; + cFile::CreateFolder("CommLogs"); + AString FileName = Printf("CommLogs/%x_%d__%s.log", (unsigned)time(NULL), sCounter++, a_Client->GetIPString().c_str()); + m_CommLogFile.Open(FileName, cFile::fmWrite); } - Pkt.WriteInt64(4053239666997989821); - Pkt.WriteInt64(-5603022497796657139); - LOG("Bits: %i, %i", (int)MostSignificantBits, (int)LeastSignificantBits); - - // Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID())); - - Pkt.WriteFPInt(a_Player.GetPosX()); - Pkt.WriteFPInt(a_Player.GetPosY()); - Pkt.WriteFPInt(a_Player.GetPosZ()); - Pkt.WriteByteAngle(a_Player.GetYaw()); - Pkt.WriteByteAngle(a_Player.GetPitch()); - short ItemType = a_Player.GetEquippedItem().IsEmpty() ? 0 : a_Player.GetEquippedItem().m_ItemType; - Pkt.WriteShort(ItemType); - Pkt.WriteByte((3 << 5) | 6); // Metadata: float + index 6 - Pkt.WriteFloat((float)a_Player.GetHealth()); - Pkt.WriteByte((4 << 5 | (2 & 0x1F)) & 0xFF); - Pkt.WriteString(a_Player.GetName()); - Pkt.WriteByte(0x7f); // Metadata: end } -void cProtocol180::SendPlayerMaxSpeed(void) +void cProtocol180::DataReceived(const char * a_Data, size_t a_Size) { - ASSERT(m_State == 3); // In game mode? - - cPacketizer Pkt(*this, 0x20); // Entity Properties - cPlayer * Player = m_Client->GetPlayer(); - Pkt.WriteVarInt(Player->GetUniqueID()); - Pkt.WriteInt(1); // Count - Pkt.WriteString("generic.movementSpeed"); - // The default game speed is 0.1, multiply that value by the relative speed: - Pkt.WriteDouble(0.1 * Player->GetNormalMaxSpeed()); - if (Player->IsSprinting()) + if (m_IsEncrypted) { - Pkt.WriteVarInt(1); // Modifier count - Pkt.WriteInt64(0x662a6b8dda3e4c1c); - Pkt.WriteInt64(0x881396ea6097278d); // UUID of the modifier - Pkt.WriteDouble(Player->GetSprintingMaxSpeed() - Player->GetNormalMaxSpeed()); - Pkt.WriteByte(2); + Byte Decrypted[512]; + while (a_Size > 0) + { + size_t NumBytes = (a_Size > sizeof(Decrypted)) ? sizeof(Decrypted) : a_Size; + m_Decryptor.ProcessData(Decrypted, (Byte *)a_Data, NumBytes); + AddReceivedData((const char *)Decrypted, NumBytes); + a_Size -= NumBytes; + a_Data += NumBytes; + } } else { - Pkt.WriteVarInt(0); // Modifier count + AddReceivedData(a_Data, a_Size); } } @@ -144,14 +140,13 @@ void cProtocol180::SendPlayerMaxSpeed(void) -void cProtocol180::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) +void cProtocol180::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x28); // Effect packet - Pkt.WriteInt(a_EffectID); - Pkt.WritePosition(a_SrcX, a_SrcY, a_SrcZ); - Pkt.WriteInt(a_Data); + cPacketizer Pkt(*this, 0x1b); // Attach Entity packet + Pkt.WriteInt(a_Entity.GetUniqueID()); + Pkt.WriteInt((a_Vehicle != NULL) ? a_Vehicle->GetUniqueID() : 0); Pkt.WriteBool(false); } @@ -159,242 +154,335 @@ void cProtocol180::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src -void cProtocol180::SendLoginSuccess(void) +void cProtocol180::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) { - ASSERT(m_State == 2); // State: login? - - // Enable compression: - { - cPacketizer Pkt(*this, 0x03); // Set compression packet - Pkt.WriteVarInt(256); - } - - m_State = 3; // State = Game - - { - cPacketizer Pkt(*this, 0x02); // Login success packet - Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID())); - Pkt.WriteString(m_Client->GetUsername()); - } + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x24); // Block Action packet + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); + Pkt.WriteByte(a_Byte1); + Pkt.WriteByte(a_Byte2); + Pkt.WriteVarInt(a_BlockType); } -void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +void cProtocol180::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x2A); - Pkt.WriteString(a_ParticleName); - Pkt.WriteFloat(a_SrcX); - Pkt.WriteFloat(a_SrcY); - Pkt.WriteFloat(a_SrcZ); - Pkt.WriteFloat(a_OffsetX); - Pkt.WriteFloat(a_OffsetY); - Pkt.WriteFloat(a_OffsetZ); - Pkt.WriteFloat(a_ParticleData); - Pkt.WriteInt(a_ParticleAmmount);*/ + cPacketizer Pkt(*this, 0x25); // Block Break Animation packet + Pkt.WriteVarInt(a_EntityID); + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); + Pkt.WriteChar(a_Stage); } -void cProtocol180::SendPlayerMoveLook(void) +void cProtocol180::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { ASSERT(m_State == 3); // In game mode? - - cPacketizer Pkt(*this, 0x08); // Player Position And Look packet - cPlayer * Player = m_Client->GetPlayer(); - Pkt.WriteDouble(Player->GetPosX()); - - // The "+ 0.001" is there because otherwise the player falls through the block they were standing on. - Pkt.WriteDouble(Player->GetStance() + 0.001); - - Pkt.WriteDouble(Player->GetPosZ()); - Pkt.WriteFloat((float)Player->GetYaw()); - Pkt.WriteFloat((float)Player->GetPitch()); - Pkt.WriteByte(0); + + cPacketizer Pkt(*this, 0x23); // Block Change packet + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); + Pkt.WriteVarInt(((UInt32)a_BlockType << 4) | ((UInt32)a_BlockMeta & 15)); } -void cProtocol180::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) +void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) { ASSERT(m_State == 3); // In game mode? - - cPacketizer Pkt(*this, 0x0a); - Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); + + /*cPacketizer Pkt(*this, 0x22); // Multi Block Change packet + Pkt.WriteInt(a_ChunkX); + Pkt.WriteInt(a_ChunkZ); + Pkt.WriteVarInt((UInt32)a_Changes.size()); + for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr) + { + short Coords = itr->y | (itr->z << 8) | (itr->x << 12); + Pkt.WriteShort(Coords); + + UInt32 Block = ((UInt32)itr->BlockType << 4) | ((UInt32)itr->BlockMeta & 15); + Pkt.WriteVarInt(Block); + } // for itr - a_Changes[]*/ } -void cProtocol180::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player) +void cProtocol180::SendChat(const AString & a_Message) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x0d); // Collect Item packet - Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteVarInt(a_Player.GetUniqueID()); + cPacketizer Pkt(*this, 0x02); // Chat Message packet + Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str())); + Pkt.WriteChar(0); } -void cProtocol180::SendEntityVelocity(const cEntity & a_Entity) +void cProtocol180::SendChat(const cCompositeChat & a_Message) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x12); // Entity Velocity packet - Pkt.WriteVarInt(a_Entity.GetUniqueID()); - // 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick - Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); - Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); -} + // Compose the complete Json string to send: + Json::Value msg; + cWorld * World = m_Client->GetPlayer()->GetWorld(); + msg["text"] = cClientHandle::FormatMessageType((World == NULL) ? false : World->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present + const cCompositeChat::cParts & Parts = a_Message.GetParts(); + for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) + { + Json::Value Part; + switch ((*itr)->m_PartType) + { + case cCompositeChat::ptText: + { + Part["text"] = (*itr)->m_Text; + AddChatPartStyle(Part, (*itr)->m_Style); + break; + } + + case cCompositeChat::ptClientTranslated: + { + const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr; + Part["translate"] = p.m_Text; + Json::Value With; + for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr) + { + With.append(*itrW); + } + if (!p.m_Parameters.empty()) + { + Part["with"] = With; + } + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptUrl: + { + const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Url; + Url["action"] = "open_url"; + Url["value"] = p.m_Url; + Part["clickEvent"] = Url; + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptSuggestCommand: + case cCompositeChat::ptRunCommand: + { + const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Cmd; + Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command"; + Cmd["value"] = p.m_Command; + Part["clickEvent"] = Cmd; + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptShowAchievement: + { + const cCompositeChat::cShowAchievementPart & p = (const cCompositeChat::cShowAchievementPart &)**itr; + Part["translate"] = "chat.type.achievement"; + Json::Value Ach; + Ach["action"] = "show_achievement"; + Ach["value"] = p.m_Text; + + Json::Value AchColourAndName; + AchColourAndName["color"] = "green"; + AchColourAndName["translate"] = p.m_Text; + AchColourAndName["hoverEvent"] = Ach; + Json::Value Extra; + Extra.append(AchColourAndName); + Json::Value Name; + Name["text"] = p.m_PlayerName; + Json::Value With; + With.append(Name); + With.append(Extra); -void cProtocol180::SendDestroyEntity(const cEntity & a_Entity) -{ - ASSERT(m_State == 3); // In game mode? + Part["with"] = With; + AddChatPartStyle(Part, p.m_Style); + break; + } + } + msg["extra"].append(Part); + } // for itr - Parts[] - /*cPacketizer Pkt(*this, 0x13); // Destroy Entities packet - Pkt.WriteVarInt(1); - Pkt.WriteVarInt(a_Entity.GetUniqueID());*/ + // Send the message to the client: + cPacketizer Pkt(*this, 0x02); + Pkt.WriteString(msg.toStyledString()); + Pkt.WriteChar(0); } -void cProtocol180::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) +void cProtocol180::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { ASSERT(m_State == 3); // In game mode? - - /*cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet - Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteByte(a_RelX); - Pkt.WriteByte(a_RelY); - Pkt.WriteByte(a_RelZ); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ + + // Serialize first, before creating the Packetizer (the packetizer locks a CS) + // This contains the flags and bitmasks, too + const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_8_0, a_ChunkX, a_ChunkZ); + + cCSLock Lock(m_CSPacket); + SendData(ChunkData.data(), ChunkData.size()); } -void cProtocol180::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) +void cProtocol180::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet + cPacketizer Pkt(*this, 0x0d); // Collect Item packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteByte(a_RelX); - Pkt.WriteByte(a_RelY); - Pkt.WriteByte(a_RelZ); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ + Pkt.WriteVarInt(a_Player.GetUniqueID()); } -void cProtocol180::SendEntityLook(const cEntity & a_Entity) +void cProtocol180::SendDestroyEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x16); // Entity Look packet - Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ + /*cPacketizer Pkt(*this, 0x13); // Destroy Entities packet + Pkt.WriteVarInt(1); + Pkt.WriteVarInt(a_Entity.GetUniqueID());*/ } -void cProtocol180::SendTeleportEntity(const cEntity & a_Entity) +void cProtocol180::SendDisconnect(const AString & a_Reason) +{ + switch (m_State) + { + case 2: + { + // During login: + cPacketizer Pkt(*this, 0); + Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Reason).c_str())); + break; + } + case 3: + { + // In-game: + cPacketizer Pkt(*this, 0x40); + Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Reason).c_str())); + break; + } + } +} + + + + + +void cProtocol180::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x18); + cPacketizer Pkt(*this, 0x36); // Sign Editor Open packet + Pkt.WriteInt(a_BlockX); + Pkt.WriteInt(a_BlockY); + Pkt.WriteInt(a_BlockZ); +} + + + + + +void cProtocol180::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x1D); // Entity Effect packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteFPInt(a_Entity.GetPosX()); - Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteFPInt(a_Entity.GetPosZ()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); - Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGrond() on entities*/ + Pkt.WriteByte(a_EffectID); + Pkt.WriteByte(a_Amplifier); + Pkt.WriteVarInt((UInt32)a_Duration); + Pkt.WriteBool(false); // Hide particles } -void cProtocol180::SendEntityHeadLook(const cEntity & a_Entity) +void cProtocol180::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x19); // Entity Head Look packet + /*cPacketizer Pkt(*this, 0x04); // Entity Equipment packet Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); - Pkt.WriteByteAngle(a_Entity.GetHeadYaw());*/ + Pkt.WriteShort(a_SlotNum); + Pkt.WriteItem(a_Item);*/ } -void cProtocol180::SendEntityMetadata(const cEntity & a_Entity) +void cProtocol180::SendEntityHeadLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet - Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteEntityMetadata(a_Entity); - Pkt.WriteByte(0x7f); // The termination byte*/ + /*cPacketizer Pkt(*this, 0x19); // Entity Head Look packet + Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); + Pkt.WriteByteAngle(a_Entity.GetHeadYaw());*/ } -void cProtocol180::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) +void cProtocol180::SendEntityLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x1D); // Entity Effect packet + /*cPacketizer Pkt(*this, 0x16); // Entity Look packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteByte(a_EffectID); - Pkt.WriteByte(a_Amplifier); - Pkt.WriteVarInt((UInt32)a_Duration); - Pkt.WriteBool(false); // Hide particles + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ } -void cProtocol180::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) +void cProtocol180::SendEntityMetadata(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x1e); + /*cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); - Pkt.WriteByte(a_EffectID); + Pkt.WriteEntityMetadata(a_Entity); + Pkt.WriteByte(0x7f); // The termination byte*/ } @@ -414,306 +502,1823 @@ void cProtocol180::SendEntityProperties(const cEntity & a_Entity) -void cProtocol180::SendKeepAlive(int a_PingID) +void cProtocol180::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) { - // Drop the packet if the protocol is not in the Game state yet (caused a client crash): - if (m_State != 3) - { - LOGWARNING("Trying to send a KeepAlive packet to a player who's not yet fully logged in (%d). The protocol class prevented the packet.", m_State); - return; - } + ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x00); // Keep Alive packet - Pkt.WriteVarInt(a_PingID); + /*cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_RelX); + Pkt.WriteByte(a_RelY); + Pkt.WriteByte(a_RelZ); + Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ } -void cProtocol180::SendHealth(void) +void cProtocol180::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) { ASSERT(m_State == 3); // In game mode? - - cPacketizer Pkt(*this, 0x06); // Update Health packet - cPlayer * Player = m_Client->GetPlayer(); - Pkt.WriteFloat((float)Player->GetHealth()); - Pkt.WriteVarInt((UInt32)Player->GetFoodLevel()); - Pkt.WriteFloat((float)Player->GetFoodSaturationLevel()); + + /*cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_RelX); + Pkt.WriteByte(a_RelY); + Pkt.WriteByte(a_RelZ); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ } -void cProtocol180::SendExperience(void) +void cProtocol180::SendEntityStatus(const cEntity & a_Entity, char a_Status) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x1f); // Experience Packet - cPlayer * Player = m_Client->GetPlayer(); - Pkt.WriteFloat(Player->GetXpPercentage()); - Pkt.WriteVarInt((UInt32)Player->GetXpLevel()); - Pkt.WriteVarInt((UInt32)Player->GetCurrentXp()); + cPacketizer Pkt(*this, 0x1a); // Entity Status packet + Pkt.WriteInt(a_Entity.GetUniqueID()); + Pkt.WriteChar(a_Status); } -void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) +void cProtocol180::SendEntityVelocity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x10); // Spawn Painting packet - Pkt.WriteVarInt(a_Painting.GetUniqueID()); - Pkt.WriteString(a_Painting.GetName().c_str()); - Pkt.WritePosition(Vector3i(a_Painting.GetPosX(), a_Painting.GetPosY(), a_Painting.GetPosZ())); - Pkt.WriteChar(a_Painting.GetDirection());*/ + cPacketizer Pkt(*this, 0x12); // Entity Velocity packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + // 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick + Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); + Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); + Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); } -void cProtocol180::SendPluginMessage(const AString & a_Channel, const AString & a_Message) +void cProtocol180::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x3f); - Pkt.WriteString(a_Channel); - Pkt.WriteBuf(a_Message.data(), a_Message.size()); + cPacketizer Pkt(*this, 0x27); // Explosion packet + Pkt.WriteFloat((float)a_BlockX); + Pkt.WriteFloat((float)a_BlockY); + Pkt.WriteFloat((float)a_BlockZ); + Pkt.WriteFloat((float)a_Radius); + Pkt.WriteInt((int)a_BlocksAffected.size()); + for (cVector3iArray::const_iterator itr = a_BlocksAffected.begin(), end = a_BlocksAffected.end(); itr != end; ++itr) + { + Pkt.WriteChar((char)itr->x); + Pkt.WriteChar((char)itr->y); + Pkt.WriteChar((char)itr->z); + } // for itr - a_BlockAffected[] + Pkt.WriteFloat((float)a_PlayerMotion.x); + Pkt.WriteFloat((float)a_PlayerMotion.y); + Pkt.WriteFloat((float)a_PlayerMotion.z); } -void cProtocol180::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) +void cProtocol180::SendGameMode(eGameMode a_GameMode) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x21); // Chunk Data packet - Pkt.WriteInt(a_ChunkX); - Pkt.WriteInt(a_ChunkZ); - Pkt.WriteBool(true); - Pkt.WriteShort(0); // Primary bitmap - Pkt.WriteVarInt(0); // Data size + cPacketizer Pkt(*this, 0x2b); // Change Game State packet + Pkt.WriteByte(3); // Reason: Change game mode + Pkt.WriteFloat((float)a_GameMode); } -void cProtocol180::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) +void cProtocol180::SendHealth(void) { ASSERT(m_State == 3); // In game mode? - // Serialize first, before creating the Packetizer (the packetizer locks a CS) - // This contains the flags and bitmasks, too - const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_8_0, a_ChunkX, a_ChunkZ); - - cCSLock Lock(m_CSPacket); - SendData(ChunkData.data(), ChunkData.size()); + cPacketizer Pkt(*this, 0x06); // Update Health packet + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteFloat((float)Player->GetHealth()); + Pkt.WriteVarInt((UInt32)Player->GetFoodLevel()); + Pkt.WriteFloat((float)Player->GetFoodSaturationLevel()); } -void cProtocol180::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) +void cProtocol180::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) { ASSERT(m_State == 3); // In game mode? - cPacketizer Pkt(*this, 0x23); // Block Change packet - Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); - - UInt32 Block = ((UInt32)a_BlockType << 4) | ((UInt32)a_BlockMeta & 15); - Pkt.WriteVarInt(Block); + cPacketizer Pkt(*this, 0x2f); // Set Slot packet + Pkt.WriteChar(a_WindowID); + Pkt.WriteShort(a_SlotNum); + Pkt.WriteItem(a_Item); } -void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) +void cProtocol180::SendKeepAlive(int a_PingID) { - ASSERT(m_State == 3); // In game mode? - - /*cPacketizer Pkt(*this, 0x22); // Multi Block Change packet - Pkt.WriteInt(a_ChunkX); - Pkt.WriteInt(a_ChunkZ); - Pkt.WriteVarInt((UInt32)a_Changes.size()); - for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr) + // Drop the packet if the protocol is not in the Game state yet (caused a client crash): + if (m_State != 3) { - short Coords = itr->y | (itr->z << 8) | (itr->x << 12); - Pkt.WriteShort(Coords); - - UInt32 Block = ((UInt32)itr->BlockType << 4) | ((UInt32)itr->BlockMeta & 15); - Pkt.WriteVarInt(Block); - } // for itr - a_Changes[]*/ + LOGWARNING("Trying to send a KeepAlive packet to a player who's not yet fully logged in (%d). The protocol class prevented the packet.", m_State); + return; + } + + cPacketizer Pkt(*this, 0x00); // Keep Alive packet + Pkt.WriteVarInt(a_PingID); } -void cProtocol180::SendChat(const AString & a_Message) +void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) { - ASSERT(m_State == 3); // In game mode? + // Send the Join Game packet: + { + cServer * Server = cRoot::Get()->GetServer(); + cPacketizer Pkt(*this, 0x01); // Join Game packet + Pkt.WriteInt(a_Player.GetUniqueID()); + Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 + Pkt.WriteChar((char)a_World.GetDimension()); + Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) + Pkt.WriteByte(std::min(Server->GetMaxPlayers(), 60)); + Pkt.WriteString("default"); // Level type - wtf? + Pkt.WriteBool(false); // Reduced Debug Info - wtf? + } + m_LastSentDimension = a_World.GetDimension(); - cPacketizer Pkt(*this, 0x02); // Chat Message packet - Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str())); - Pkt.WriteChar(0); + // Send the spawn position: + { + cPacketizer Pkt(*this, 0x05); // Spawn Position packet + Pkt.WritePosition(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); + } + + // Send player abilities: + SendPlayerAbilities(); } - -void cProtocol180::SendChat(const cCompositeChat & a_Message) +void cProtocol180::SendLoginSuccess(void) { - ASSERT(m_State == 3); // In game mode? + ASSERT(m_State == 2); // State: login? - // Compose the complete Json string to send: - Json::Value msg; - cWorld * World = m_Client->GetPlayer()->GetWorld(); - msg["text"] = cClientHandle::FormatMessageType((World == NULL) ? false : World->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present - const cCompositeChat::cParts & Parts = a_Message.GetParts(); - for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) + // Enable compression: { - Json::Value Part; - switch ((*itr)->m_PartType) - { - case cCompositeChat::ptText: - { - Part["text"] = (*itr)->m_Text; - AddChatPartStyle(Part, (*itr)->m_Style); - break; - } - - case cCompositeChat::ptClientTranslated: + cPacketizer Pkt(*this, 0x03); // Set compression packet + Pkt.WriteVarInt(256); + } + + m_State = 3; // State = Game + + { + cPacketizer Pkt(*this, 0x02); // Login success packet + Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID())); + Pkt.WriteString(m_Client->GetUsername()); + } +} + + + + + +void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) +{ + ASSERT(m_State == 3); // In game mode? + + /*cPacketizer Pkt(*this, 0x10); // Spawn Painting packet + Pkt.WriteVarInt(a_Painting.GetUniqueID()); + Pkt.WriteString(a_Painting.GetName().c_str()); + Pkt.WritePosition(Vector3i(a_Painting.GetPosX(), a_Painting.GetPosY(), a_Painting.GetPosZ())); + Pkt.WriteChar(a_Painting.GetDirection());*/ +} + + + + + +void cProtocol180::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x34); + Pkt.WriteVarInt(a_ID); + Pkt.WriteShort (3 + a_Length); + + Pkt.WriteByte(0); + Pkt.WriteByte(a_X); + Pkt.WriteByte(a_Y); + + for (unsigned int i = 0; i < a_Length; ++i) + { + Pkt.WriteByte(a_Colors[i]); + } +} + + + + + +void cProtocol180::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x34); + Pkt.WriteVarInt(a_ID); + Pkt.WriteShort ((short)(1 + (3 * a_Decorators.size()))); + + Pkt.WriteByte(1); + + for (cMapDecoratorList::const_iterator it = a_Decorators.begin(); it != a_Decorators.end(); ++it) + { + Pkt.WriteByte((it->GetType() << 4) | (it->GetRot() & 0xf)); + Pkt.WriteByte(it->GetPixelX()); + Pkt.WriteByte(it->GetPixelZ()); + } +} + + + + + +void cProtocol180::SendMapInfo(int a_ID, unsigned int a_Scale) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x34); + Pkt.WriteVarInt(a_ID); + Pkt.WriteShort (2); + + Pkt.WriteByte(2); + Pkt.WriteByte(a_Scale); +} + + + + + + +void cProtocol180::SendPickupSpawn(const cPickup & a_Pickup) +{ + ASSERT(m_State == 3); // In game mode? + + /*{ + cPacketizer Pkt(*this, 0x0e); // Spawn Object packet + Pkt.WriteVarInt(a_Pickup.GetUniqueID()); + Pkt.WriteByte(2); // Type = Pickup + Pkt.WriteFPInt(a_Pickup.GetPosX()); + Pkt.WriteFPInt(a_Pickup.GetPosY()); + Pkt.WriteFPInt(a_Pickup.GetPosZ()); + Pkt.WriteByteAngle(a_Pickup.GetYaw()); + Pkt.WriteByteAngle(a_Pickup.GetPitch()); + Pkt.WriteInt(0); // No object data + } + + { + cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet + Pkt.WriteVarInt(a_Pickup.GetUniqueID()); + Pkt.WriteByte((0x05 << 5) | 10); // Slot type + index 10 + Pkt.WriteItem(a_Pickup.GetItem()); + Pkt.WriteByte(0x7f); // End of metadata + }*/ +} + + + + + +void cProtocol180::SendPlayerAbilities(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x39); // Player Abilities packet + Byte Flags = 0; + cPlayer * Player = m_Client->GetPlayer(); + if (Player->IsGameModeCreative()) + { + Flags |= 0x01; + Flags |= 0x08; // Godmode, used for creative + } + if (Player->IsFlying()) + { + Flags |= 0x02; + } + if (Player->CanFly()) + { + Flags |= 0x04; + } + Pkt.WriteByte(Flags); + Pkt.WriteFloat((float)(0.05 * Player->GetFlyingMaxSpeed())); + Pkt.WriteFloat((float)(0.1 * Player->GetNormalMaxSpeed())); +} + + + + + +void cProtocol180::SendEntityAnimation(const cEntity & a_Entity, char a_Animation) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x0b); // Animation packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteChar(a_Animation); +} + + + + + +void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +{ + ASSERT(m_State == 3); // In game mode? + + /*cPacketizer Pkt(*this, 0x2A); + Pkt.WriteString(a_ParticleName); + Pkt.WriteFloat(a_SrcX); + Pkt.WriteFloat(a_SrcY); + Pkt.WriteFloat(a_SrcZ); + Pkt.WriteFloat(a_OffsetX); + Pkt.WriteFloat(a_OffsetY); + Pkt.WriteFloat(a_OffsetZ); + Pkt.WriteFloat(a_ParticleData); + Pkt.WriteInt(a_ParticleAmmount);*/ +} + + + + + +void cProtocol180::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +{ + ASSERT(m_State == 3); // In game mode? + + /*cPacketizer Pkt(*this, 0x38); // Playerlist Item packet + Pkt.WriteString(a_Player.GetName()); + Pkt.WriteBool(a_IsOnline); + Pkt.WriteShort(a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0);*/ +} + + + + + +void cProtocol180::SendPlayerMaxSpeed(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x20); // Entity Properties + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteVarInt(Player->GetUniqueID()); + Pkt.WriteInt(1); // Count + Pkt.WriteString("generic.movementSpeed"); + // The default game speed is 0.1, multiply that value by the relative speed: + Pkt.WriteDouble(0.1 * Player->GetNormalMaxSpeed()); + if (Player->IsSprinting()) + { + Pkt.WriteVarInt(1); // Modifier count + Pkt.WriteInt64(0x662a6b8dda3e4c1c); + Pkt.WriteInt64(0x881396ea6097278d); // UUID of the modifier + Pkt.WriteDouble(Player->GetSprintingMaxSpeed() - Player->GetNormalMaxSpeed()); + Pkt.WriteByte(2); + } + else + { + Pkt.WriteVarInt(0); // Modifier count + } +} + + + + + +void cProtocol180::SendPlayerMoveLook(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x08); // Player Position And Look packet + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteDouble(Player->GetPosX()); + + // The "+ 0.001" is there because otherwise the player falls through the block they were standing on. + Pkt.WriteDouble(Player->GetStance() + 0.001); + + Pkt.WriteDouble(Player->GetPosZ()); + Pkt.WriteFloat((float)Player->GetYaw()); + Pkt.WriteFloat((float)Player->GetPitch()); + Pkt.WriteByte(0); +} + + + + + +void cProtocol180::SendPlayerPosition(void) +{ + // There is no dedicated packet for this, send the whole thing: + SendPlayerMoveLook(); +} + + + + + +void cProtocol180::SendPlayerSpawn(const cPlayer & a_Player) +{ + // Called to spawn another player for the client + cPacketizer Pkt(*this, 0x0c); // Spawn Player packet + Pkt.WriteVarInt(a_Player.GetUniqueID()); + + // Fake UUID + Pkt.WriteInt64(4053239666997989821); + Pkt.WriteInt64(-5603022497796657139); + + Pkt.WriteFPInt(a_Player.GetPosX()); + Pkt.WriteFPInt(a_Player.GetPosY()); + Pkt.WriteFPInt(a_Player.GetPosZ()); + Pkt.WriteByteAngle(a_Player.GetYaw()); + Pkt.WriteByteAngle(a_Player.GetPitch()); + short ItemType = a_Player.GetEquippedItem().IsEmpty() ? 0 : a_Player.GetEquippedItem().m_ItemType; + Pkt.WriteShort(ItemType); + Pkt.WriteByte((3 << 5) | 6); // Metadata: float + index 6 + Pkt.WriteFloat((float)a_Player.GetHealth()); + Pkt.WriteByte((4 << 5 | (2 & 0x1F)) & 0xFF); + Pkt.WriteString(a_Player.GetName()); + Pkt.WriteByte(0x7f); // Metadata: end +} + + + + + +void cProtocol180::SendPluginMessage(const AString & a_Channel, const AString & a_Message) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x3f); + Pkt.WriteString(a_Channel); + Pkt.WriteBuf(a_Message.data(), a_Message.size()); +} + + + + + +void cProtocol180::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x1e); + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_EffectID); +} + + + + + +void cProtocol180::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) +{ + if ((m_LastSentDimension == a_Dimension) && !a_ShouldIgnoreDimensionChecks) + { + // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death) + return; + } + + cPacketizer Pkt(*this, 0x07); // Respawn packet + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteInt((int)a_Dimension); + Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) + Pkt.WriteByte((Byte)Player->GetEffectiveGameMode()); + Pkt.WriteString("default"); + m_LastSentDimension = a_Dimension; +} + + + + + +void cProtocol180::SendExperience(void) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x1f); // Experience Packet + cPlayer * Player = m_Client->GetPlayer(); + Pkt.WriteFloat(Player->GetXpPercentage()); + Pkt.WriteVarInt((UInt32)Player->GetXpLevel()); + Pkt.WriteVarInt((UInt32)Player->GetCurrentXp()); +} + + + + + +void cProtocol180::SendExperienceOrb(const cExpOrb & a_ExpOrb) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x11); + Pkt.WriteVarInt(a_ExpOrb.GetUniqueID()); + Pkt.WriteFPInt(a_ExpOrb.GetPosX()); + Pkt.WriteFPInt(a_ExpOrb.GetPosY()); + Pkt.WriteFPInt(a_ExpOrb.GetPosZ()); + Pkt.WriteShort(a_ExpOrb.GetReward()); +} + + + + + +void cProtocol180::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x3b); + Pkt.WriteString(a_Name); + Pkt.WriteString(a_DisplayName); + Pkt.WriteByte(a_Mode); +} + + + + + +void cProtocol180::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x3c); + Pkt.WriteString(a_Player); + Pkt.WriteByte(a_Mode); + + if (a_Mode != 1) + { + Pkt.WriteString(a_Objective); + Pkt.WriteInt((int) a_Score); + } +} + + + + + +void cProtocol180::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x3d); + Pkt.WriteByte((int) a_Display); + Pkt.WriteString(a_Objective); +} + + + + + +void cProtocol180::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x29); // Sound Effect packet + Pkt.WriteString(a_SoundName); + Pkt.WriteInt((int)(a_X * 8.0)); + Pkt.WriteInt((int)(a_Y * 8.0)); + Pkt.WriteInt((int)(a_Z * 8.0)); + Pkt.WriteFloat(a_Volume); + Pkt.WriteByte((Byte)(a_Pitch * 63)); +} + + + + + +void cProtocol180::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x28); // Effect packet + Pkt.WriteInt(a_EffectID); + Pkt.WritePosition(a_SrcX, a_SrcY, a_SrcZ); + Pkt.WriteInt(a_Data); + Pkt.WriteBool(false); +} + + + + + +void cProtocol180::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x0e); // Spawn Object packet + Pkt.WriteVarInt(a_FallingBlock.GetUniqueID()); + Pkt.WriteByte(70); // Falling block + Pkt.WriteFPInt(a_FallingBlock.GetPosX()); + Pkt.WriteFPInt(a_FallingBlock.GetPosY()); + Pkt.WriteFPInt(a_FallingBlock.GetPosZ()); + Pkt.WriteByteAngle(a_FallingBlock.GetYaw()); + Pkt.WriteByteAngle(a_FallingBlock.GetPitch()); + Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10 + Pkt.WriteShort((short)(a_FallingBlock.GetSpeedX() * 400)); + Pkt.WriteShort((short)(a_FallingBlock.GetSpeedY() * 400)); + Pkt.WriteShort((short)(a_FallingBlock.GetSpeedZ() * 400)); +} + + + + + +void cProtocol180::SendSpawnMob(const cMonster & a_Mob) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x0f); // Spawn Mob packet + Pkt.WriteVarInt(a_Mob.GetUniqueID()); + Pkt.WriteByte((Byte)a_Mob.GetMobType()); + Pkt.WriteFPInt(a_Mob.GetPosX()); + Pkt.WriteFPInt(a_Mob.GetPosY()); + Pkt.WriteFPInt(a_Mob.GetPosZ()); + Pkt.WriteByteAngle(a_Mob.GetPitch()); + Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); + Pkt.WriteByteAngle(a_Mob.GetYaw()); + Pkt.WriteShort((short)(a_Mob.GetSpeedX() * 400)); + Pkt.WriteShort((short)(a_Mob.GetSpeedY() * 400)); + Pkt.WriteShort((short)(a_Mob.GetSpeedZ() * 400)); + Pkt.WriteEntityMetadata(a_Mob); + Pkt.WriteByte(0x7f); // Metadata terminator +} + + + + + +void cProtocol180::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) +{ + ASSERT(m_State == 3); // In game mode? + + /*cPacketizer Pkt(*this, 0xe); // Spawn Object packet + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteByte(a_ObjectType); + Pkt.WriteFPInt(a_Entity.GetPosX()); + Pkt.WriteFPInt(a_Entity.GetPosY()); + Pkt.WriteFPInt(a_Entity.GetPosZ()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteInt(a_ObjectData); + if (a_ObjectData != 0) + { + Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); + Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); + Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); + }*/ +} + + + + + +void cProtocol180::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0xe); // Spawn Object packet + Pkt.WriteVarInt(a_Vehicle.GetUniqueID()); + Pkt.WriteByte(a_VehicleType); + Pkt.WriteFPInt(a_Vehicle.GetPosX()); + Pkt.WriteFPInt(a_Vehicle.GetPosY()); + Pkt.WriteFPInt(a_Vehicle.GetPosZ()); + Pkt.WriteByteAngle(a_Vehicle.GetPitch()); + Pkt.WriteByteAngle(a_Vehicle.GetYaw()); + Pkt.WriteInt(a_VehicleSubType); + if (a_VehicleSubType != 0) + { + Pkt.WriteShort((short)(a_Vehicle.GetSpeedX() * 400)); + Pkt.WriteShort((short)(a_Vehicle.GetSpeedY() * 400)); + Pkt.WriteShort((short)(a_Vehicle.GetSpeedZ() * 400)); + } +} + + + + + +void cProtocol180::SendStatistics(const cStatManager & a_Manager) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x37); + Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only + + for (size_t i = 0; i < (size_t)statCount; ++i) + { + StatValue Value = a_Manager.GetValue((eStatistic) i); + const AString & StatName = cStatInfo::GetName((eStatistic) i); + + Pkt.WriteString(StatName); + Pkt.WriteVarInt(Value); + } +} + + + + + +void cProtocol180::SendTabCompletionResults(const AStringVector & a_Results) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x3a); // Tab-Complete packet + Pkt.WriteVarInt((int)a_Results.size()); + + for (AStringVector::const_iterator itr = a_Results.begin(), end = a_Results.end(); itr != end; ++itr) + { + Pkt.WriteString(*itr); + } +} + + + + + +void cProtocol180::SendTeleportEntity(const cEntity & a_Entity) +{ + ASSERT(m_State == 3); // In game mode? + + /*cPacketizer Pkt(*this, 0x18); + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WriteFPInt(a_Entity.GetPosX()); + Pkt.WriteFPInt(a_Entity.GetPosY()); + Pkt.WriteFPInt(a_Entity.GetPosZ()); + Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(a_Entity.GetPitch()); + Pkt.WriteBool(true); // TODO: IsOnGrond() on entities*/ +} + + + + + +void cProtocol180::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x2c); // Spawn Global Entity packet + Pkt.WriteVarInt(0); // EntityID = 0, always + Pkt.WriteByte(1); // Type = Thunderbolt + Pkt.WriteFPInt(a_BlockX); + Pkt.WriteFPInt(a_BlockY); + Pkt.WriteFPInt(a_BlockZ); +} + + + + + +void cProtocol180::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) +{ + ASSERT(m_State == 3); // In game mode? + if (!a_DoDaylightCycle) + { + // When writing a "-" before the number the client ignores it but it will stop the client-side time expiration. + a_TimeOfDay = std::min(-a_TimeOfDay, -1LL); + } + + cPacketizer Pkt(*this, 0x03); + Pkt.WriteInt64(a_WorldAge); + Pkt.WriteInt64(a_TimeOfDay); +} + + + + + +void cProtocol180::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x21); // Chunk Data packet + Pkt.WriteInt(a_ChunkX); + Pkt.WriteInt(a_ChunkZ); + Pkt.WriteBool(true); + Pkt.WriteShort(0); // Primary bitmap + Pkt.WriteVarInt(0); // Data size +} + + + + +void cProtocol180::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x35); // Update tile entity packet + Pkt.WriteInt(a_BlockEntity.GetPosX()); + Pkt.WriteShort(a_BlockEntity.GetPosY()); + Pkt.WriteInt(a_BlockEntity.GetPosZ()); + + Byte Action = 0; + switch (a_BlockEntity.GetBlockType()) + { + 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; + } + Pkt.WriteByte(Action); + + Pkt.WriteBlockEntity(a_BlockEntity); +} + + + + + +void cProtocol180::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x33); + Pkt.WriteInt(a_BlockX); + Pkt.WriteShort((short)a_BlockY); + Pkt.WriteInt(a_BlockZ); + // Need to send only up to 15 chars, otherwise the client crashes (#598) + Pkt.WriteString(a_Line1.substr(0, 15)); + Pkt.WriteString(a_Line2.substr(0, 15)); + Pkt.WriteString(a_Line3.substr(0, 15)); + Pkt.WriteString(a_Line4.substr(0, 15)); +} + + + + + +void cProtocol180::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x0a); + Pkt.WriteVarInt(a_Entity.GetUniqueID()); + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); +} + + + + + +void cProtocol180::SendWeather(eWeather a_Weather) +{ + ASSERT(m_State == 3); // In game mode? + + { + cPacketizer Pkt(*this, 0x2b); // Change Game State packet + Pkt.WriteByte((a_Weather == wSunny) ? 1 : 2); // End rain / begin rain + Pkt.WriteFloat(0); // Unused for weather + } + + // TODO: Fade effect, somehow +} + + + + + +void cProtocol180::SendWholeInventory(const cWindow & a_Window) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x30); // Window Items packet + Pkt.WriteChar(a_Window.GetWindowID()); + Pkt.WriteShort(a_Window.GetNumSlots()); + cItems Slots; + a_Window.GetSlots(*(m_Client->GetPlayer()), Slots); + for (cItems::const_iterator itr = Slots.begin(), end = Slots.end(); itr != end; ++itr) + { + Pkt.WriteItem(*itr); + } // for itr - Slots[] +} + + + + + +void cProtocol180::SendWindowClose(const cWindow & a_Window) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x2e); + Pkt.WriteChar(a_Window.GetWindowID()); +} + + + + + +void cProtocol180::SendWindowOpen(const cWindow & a_Window) +{ + ASSERT(m_State == 3); // In game mode? + + if (a_Window.GetWindowType() < 0) + { + // Do not send this packet for player inventory windows + return; + } + + cPacketizer Pkt(*this, 0x2d); + Pkt.WriteChar(a_Window.GetWindowID()); + Pkt.WriteChar(a_Window.GetWindowType()); + Pkt.WriteString(a_Window.GetWindowTitle()); + Pkt.WriteChar(a_Window.GetNumNonInventorySlots()); + Pkt.WriteBool(true); + if (a_Window.GetWindowType() == cWindow::wtAnimalChest) + { + Pkt.WriteInt(0); // TODO: The animal's EntityID + } +} + + + + + +void cProtocol180::SendWindowProperty(const cWindow & a_Window, int a_Property, int a_Value) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x31); // Window Property packet + Pkt.WriteChar(a_Window.GetWindowID()); + Pkt.WriteShort(a_Property); + Pkt.WriteShort(a_Value); +} + + + + + +void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) +{ + // Write the incoming data into the comm log file: + if (g_ShouldLogCommIn) + { + if (m_ReceivedData.GetReadableSpace() > 0) + { + AString AllData; + size_t OldReadableSpace = m_ReceivedData.GetReadableSpace(); + m_ReceivedData.ReadAll(AllData); + m_ReceivedData.ResetRead(); + m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace); + ASSERT(m_ReceivedData.GetReadableSpace() == OldReadableSpace); + AString Hex; + CreateHexDump(Hex, AllData.data(), AllData.size(), 16); + m_CommLogFile.Printf("Incoming data, " SIZE_T_FMT " (0x" SIZE_T_FMT_HEX ") unparsed bytes already present in buffer:\n%s\n", + AllData.size(), AllData.size(), Hex.c_str() + ); + } + AString Hex; + CreateHexDump(Hex, a_Data, a_Size, 16); + m_CommLogFile.Printf("Incoming data: %d (0x%x) bytes: \n%s\n", + (unsigned)a_Size, (unsigned)a_Size, Hex.c_str() + ); + m_CommLogFile.Flush(); + } + + if (!m_ReceivedData.Write(a_Data, a_Size)) + { + // Too much data in the incoming queue, report to caller: + m_Client->PacketBufferFull(); + return; + } + + // Handle all complete packets: + for (;;) + { + UInt32 PacketLen; + if (!m_ReceivedData.ReadVarInt(PacketLen)) + { + // Not enough data + m_ReceivedData.ResetRead(); + break; + } + if (!m_ReceivedData.CanReadBytes(PacketLen)) + { + // The full packet hasn't been received yet + m_ReceivedData.ResetRead(); + break; + } + cByteBuffer bb(PacketLen + 1); + VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); + m_ReceivedData.CommitRead(); + + // Compressed packets + if (m_State == 3) + { + UInt32 CompressedSize; + if (!bb.ReadVarInt(CompressedSize)) { - const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr; - Part["translate"] = p.m_Text; - Json::Value With; - for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr) - { - With.append(*itrW); - } - if (!p.m_Parameters.empty()) - { - Part["with"] = With; - } - AddChatPartStyle(Part, p.m_Style); + // Not enough data break; } + } + + // Write one NUL extra, so that we can detect over-reads + bb.Write("\0", 1); + + UInt32 PacketType; + if (!bb.ReadVarInt(PacketType)) + { + // Not enough data + break; + } + + // Log the packet info into the comm log file: + if (g_ShouldLogCommIn) + { + AString PacketData; + bb.ReadAll(PacketData); + bb.ResetRead(); + bb.ReadVarInt(PacketType); + ASSERT(PacketData.size() > 0); + PacketData.resize(PacketData.size() - 1); + AString PacketDataHex; + CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16); + m_CommLogFile.Printf("Next incoming packet is type %u (0x%x), length %u (0x%x) at state %d. Payload:\n%s\n", + PacketType, PacketType, PacketLen, PacketLen, m_State, PacketDataHex.c_str() + ); + } + + if (!HandlePacket(bb, PacketType)) + { + // Unknown packet, already been reported, but without the length. Log the length here: + LOGWARNING("Unhandled packet: type 0x%x, state %d, length %u", PacketType, m_State, PacketLen); - case cCompositeChat::ptUrl: + #ifdef _DEBUG + // Dump the packet contents into the log: + bb.ResetRead(); + AString Packet; + bb.ReadAll(Packet); + Packet.resize(Packet.size() - 1); // Drop the final NUL pushed there for over-read detection + AString Out; + CreateHexDump(Out, Packet.data(), (int)Packet.size(), 24); + LOGD("Packet contents:\n%s", Out.c_str()); + #endif // _DEBUG + + // Put a message in the comm log: + if (g_ShouldLogCommIn) { - const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr; - Part["text"] = p.m_Text; - Json::Value Url; - Url["action"] = "open_url"; - Url["value"] = p.m_Url; - Part["clickEvent"] = Url; - AddChatPartStyle(Part, p.m_Style); - break; + m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n"); } - case cCompositeChat::ptSuggestCommand: - case cCompositeChat::ptRunCommand: + return; + } + + if (bb.GetReadableSpace() != 1) + { + // Read more or less than packet length, report as error + LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x, state %d. Read " SIZE_T_FMT " bytes, packet contained %u bytes", + PacketType, m_State, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen + ); + + // Put a message in the comm log: + if (g_ShouldLogCommIn) { - const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr; - Part["text"] = p.m_Text; - Json::Value Cmd; - Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command"; - Cmd["value"] = p.m_Command; - Part["clickEvent"] = Cmd; - AddChatPartStyle(Part, p.m_Style); - break; + m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got " SIZE_T_FMT " left) ^^^^^^\n\n\n", + 1, bb.GetReadableSpace() + ); + m_CommLogFile.Flush(); + } + + ASSERT(!"Read wrong number of bytes!"); + m_Client->PacketError(PacketType); + } + } // for (ever) + + // Log any leftover bytes into the logfile: + if (g_ShouldLogCommIn && (m_ReceivedData.GetReadableSpace() > 0)) + { + AString AllData; + size_t OldReadableSpace = m_ReceivedData.GetReadableSpace(); + m_ReceivedData.ReadAll(AllData); + m_ReceivedData.ResetRead(); + m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace); + ASSERT(m_ReceivedData.GetReadableSpace() == OldReadableSpace); + AString Hex; + CreateHexDump(Hex, AllData.data(), AllData.size(), 16); + m_CommLogFile.Printf("There are " SIZE_T_FMT " (0x" SIZE_T_FMT_HEX ") bytes of non-parse-able data left in the buffer:\n%s", + m_ReceivedData.GetReadableSpace(), m_ReceivedData.GetReadableSpace(), Hex.c_str() + ); + m_CommLogFile.Flush(); + } +} + + + + +bool cProtocol180::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) +{ + switch (m_State) + { + case 1: + { + // Status + switch (a_PacketType) + { + case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true; + case 0x01: HandlePacketStatusPing (a_ByteBuffer); return true; + } + break; + } + + case 2: + { + // Login + switch (a_PacketType) + { + case 0x00: HandlePacketLoginStart (a_ByteBuffer); return true; + case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true; + } + break; + } + + case 3: + { + // Game + switch (a_PacketType) + { + case 0x00: HandlePacketKeepAlive (a_ByteBuffer); return true; + case 0x01: HandlePacketChatMessage (a_ByteBuffer); return true; + case 0x02: HandlePacketUseEntity (a_ByteBuffer); return true; + case 0x03: HandlePacketPlayer (a_ByteBuffer); return true; + case 0x04: HandlePacketPlayerPos (a_ByteBuffer); return true; + case 0x05: HandlePacketPlayerLook (a_ByteBuffer); return true; + case 0x06: HandlePacketPlayerPosLook (a_ByteBuffer); return true; + case 0x07: HandlePacketBlockDig (a_ByteBuffer); return true; + case 0x08: HandlePacketBlockPlace (a_ByteBuffer); return true; + case 0x09: HandlePacketSlotSelect (a_ByteBuffer); return true; + case 0x0a: HandlePacketAnimation (a_ByteBuffer); return true; + case 0x0b: HandlePacketEntityAction (a_ByteBuffer); return true; + case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return true; + case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return true; + case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true; + case 0x0f: // Confirm transaction - not used in MCS + case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; + case 0x11: HandlePacketEnchantItem (a_ByteBuffer); return true; + case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true; + case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return true; + case 0x14: HandlePacketTabComplete (a_ByteBuffer); return true; + case 0x15: HandlePacketClientSettings (a_ByteBuffer); return true; + case 0x16: HandlePacketClientStatus (a_ByteBuffer); return true; + case 0x17: HandlePacketPluginMessage (a_ByteBuffer); return true; } + break; + } + default: + { + // Received a packet in an unknown state, report: + LOGWARNING("Received a packet in an unknown protocol state %d. Ignoring further packets.", m_State); + + // Cannot kick the client - we don't know this state and thus the packet number for the kick packet + + // Switch to a state when all further packets are silently ignored: + m_State = 255; + return false; + } + case 255: + { + // This is the state used for "not processing packets anymore" when we receive a bad packet from a client. + // Do not output anything (the caller will do that for us), just return failure + return false; + } + } // switch (m_State) + + // Unknown packet type, report to the ClientHandle: + m_Client->PacketUnknown(a_PacketType); + return false; +} + + + + + +void cProtocol180::HandlePacketStatusPing(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Timestamp); + + cPacketizer Pkt(*this, 0x01); // Ping packet + Pkt.WriteInt64(Timestamp); +} + + + + + +void cProtocol180::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) +{ + cServer * Server = cRoot::Get()->GetServer(); + AString ServerDescription = Server->GetDescription(); + int NumPlayers = Server->GetNumPlayers(); + int MaxPlayers = Server->GetMaxPlayers(); + AString Favicon = Server->GetFaviconData(); + cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon); + + // Version: + Json::Value Version; + Version["name"] = "1.8"; + Version["protocol"] = 47; + + // Players: + Json::Value Players; + Players["online"] = NumPlayers; + Players["max"] = MaxPlayers; + // TODO: Add "sample" + + // Description: + Json::Value Description; + Description["text"] = ServerDescription.c_str(); + + // Create the response: + Json::Value ResponseValue; + ResponseValue["version"] = Version; + ResponseValue["players"] = Players; + ResponseValue["description"] = Description; + if (!Favicon.empty()) + { + ResponseValue["favicon"] = Printf("data:image/png;base64,%s", Favicon.c_str()); + } + + Json::StyledWriter Writer; + AString Response = Writer.write(ResponseValue); + + cPacketizer Pkt(*this, 0x00); // Response packet + Pkt.WriteString(Response); +} + + + + + +void cProtocol180::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) +{ + UInt32 EncKeyLength, EncNonceLength; + a_ByteBuffer.ReadVarInt(EncKeyLength); + AString EncKey; + if (!a_ByteBuffer.ReadString(EncKey, EncKeyLength)) + { + return; + } + a_ByteBuffer.ReadVarInt(EncNonceLength); + AString EncNonce; + if (!a_ByteBuffer.ReadString(EncNonce, EncNonceLength)) + { + return; + } + if ((EncKeyLength > MAX_ENC_LEN) || (EncNonceLength > MAX_ENC_LEN)) + { + LOGD("Too long encryption"); + m_Client->Kick("Hacked client"); + return; + } + + // Decrypt EncNonce using privkey + cRsaPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey(); + Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)]; + int res = rsaDecryptor.Decrypt((const Byte *)EncNonce.data(), EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce)); + if (res != 4) + { + LOGD("Bad nonce length: got %d, exp %d", res, 4); + m_Client->Kick("Hacked client"); + return; + } + if (ntohl(DecryptedNonce[0]) != (unsigned)(uintptr_t)this) + { + LOGD("Bad nonce value"); + m_Client->Kick("Hacked client"); + return; + } + + // Decrypt the symmetric encryption key using privkey: + Byte DecryptedKey[MAX_ENC_LEN]; + res = rsaDecryptor.Decrypt((const Byte *)EncKey.data(), EncKey.size(), DecryptedKey, sizeof(DecryptedKey)); + if (res != 16) + { + LOGD("Bad key length"); + m_Client->Kick("Hacked client"); + return; + } + + StartEncryption(DecryptedKey); + m_Client->HandleLogin(4, m_Client->GetUsername()); +} + + + + + +void cProtocol180::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) +{ + AString Username; + if (!a_ByteBuffer.ReadVarUTF8String(Username)) + { + m_Client->Kick("Bad username"); + return; + } + + if (!m_Client->HandleHandshake(Username)) + { + // The client is not welcome here, they have been sent a Kick packet already + return; + } + + cServer * Server = cRoot::Get()->GetServer(); + // If auth is required, then send the encryption request: + if (Server->ShouldAuthenticate()) + { + cPacketizer Pkt(*this, 0x01); + Pkt.WriteString(Server->GetServerID()); + const AString & PubKeyDer = Server->GetPublicKeyDER(); + Pkt.WriteVarInt((short)PubKeyDer.size()); + Pkt.WriteBuf(PubKeyDer.data(), PubKeyDer.size()); + Pkt.WriteVarInt(4); + Pkt.WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :) + m_Client->SetUsername(Username); + return; + } + + m_Client->HandleLogin(4, Username); +} + + + + + +void cProtocol180::HandlePacketAnimation(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEInt, int, EntityID); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Animation); + m_Client->HandleAnimation(Animation); +} + + + + + +void cProtocol180::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Status); + + int BlockX, BlockY, BlockZ; + if (!a_ByteBuffer.ReadPosition(BlockX, BlockY, BlockZ)) + { + return; + } + + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Face); + m_Client->HandleLeftClick(BlockX, BlockY, BlockZ, static_cast(Face), Status); +} + + + + + +void cProtocol180::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) +{ + int BlockX, BlockY, BlockZ; + if (!a_ByteBuffer.ReadPosition(BlockX, BlockY, BlockZ)) + { + return; + } + + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Face); + cItem Item; + ReadItem(a_ByteBuffer, Item); + + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorX); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorY); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorZ); + m_Client->HandleRightClick(BlockX, BlockY, BlockZ, static_cast(Face), CursorX, CursorY, CursorZ, m_Client->GetPlayer()->GetEquippedItem()); +} + + + + + +void cProtocol180::HandlePacketChatMessage(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Message); + m_Client->HandleChat(Message); +} + + + + + +void cProtocol180::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Locale); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ViewDistance); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ChatFlags); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors); + HANDLE_READ(a_ByteBuffer, ReadChar, char, SkinFlags); + + m_Client->SetLocale(Locale); + // TODO: Handle other values +} + + + + + +void cProtocol180::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadChar, char, ActionID); + switch (ActionID) + { + case 0: + { + // Respawn + m_Client->HandleRespawn(); + break; + } + case 1: + { + // Request stats + const cStatManager & Manager = m_Client->GetPlayer()->GetStatManager(); + SendStatistics(Manager); - case cCompositeChat::ptShowAchievement: - { - const cCompositeChat::cShowAchievementPart & p = (const cCompositeChat::cShowAchievementPart &)**itr; - Part["translate"] = "chat.type.achievement"; + break; + } + case 2: + { + // Open Inventory achievement + m_Client->GetPlayer()->AwardAchievement(achOpenInv); + break; + } + } +} - Json::Value Ach; - Ach["action"] = "show_achievement"; - Ach["value"] = p.m_Text; - - Json::Value AchColourAndName; - AchColourAndName["color"] = "green"; - AchColourAndName["translate"] = p.m_Text; - AchColourAndName["hoverEvent"] = Ach; - Json::Value Extra; - Extra.append(AchColourAndName); - Json::Value Name; - Name["text"] = p.m_PlayerName; - Json::Value With; - With.append(Name); - With.append(Extra); - Part["with"] = With; - AddChatPartStyle(Part, p.m_Style); - break; - } - } - msg["extra"].append(Part); - } // for itr - Parts[] - - // Send the message to the client: - cPacketizer Pkt(*this, 0x02); - Pkt.WriteString(msg.toStyledString()); - Pkt.WriteChar(0); +void cProtocol180::HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEShort, short, SlotNum); + cItem Item; + if (!ReadItem(a_ByteBuffer, Item)) + { + return; + } + m_Client->HandleCreativeInventory(SlotNum, Item); +} + + + + + +void cProtocol180::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, PlayerID); + HANDLE_READ(a_ByteBuffer, ReadChar, char, Action); + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, JumpBoost); + + switch (Action) + { + case 0: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch + case 1: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch + case 2: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed + case 3: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting + case 4: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting + } +} + + + + + +void cProtocol180::HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, KeepAliveID); + m_Client->HandleKeepAlive((int)KeepAliveID); +} + + + + + +void cProtocol180::HandlePacketPlayer(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + // TODO: m_Client->HandlePlayerOnGround(IsOnGround); +} + + + + + +void cProtocol180::HandlePacketPlayerAbilities(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Flags); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, FlyingSpeed); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, WalkingSpeed); + + bool IsFlying = false, CanFly = false; + if ((Flags & 2) != 0) + { + IsFlying = true; + } + if ((Flags & 4) != 0) + { + CanFly = true; + } + + m_Client->HandlePlayerAbilities(CanFly, IsFlying, FlyingSpeed, WalkingSpeed); +} + + + + + +void cProtocol180::HandlePacketPlayerLook(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + m_Client->HandlePlayerLook(Yaw, Pitch, IsOnGround); +} + + + + + +void cProtocol180::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + m_Client->HandlePlayerPos(PosX, PosY, PosZ, PosY + 1.62, IsOnGround); +} + + + + + +void cProtocol180::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); + m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, PosY + 1.62, Yaw, Pitch, IsOnGround); +} + + + + + +void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); + AString Data; + if (!a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1)) + { + return; + } + m_Client->HandlePluginMessage(Channel, Data); +} + + + + + +void cProtocol180::HandlePacketSlotSelect(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEShort, short, SlotNum); + m_Client->HandleSlotSelected(SlotNum); +} + + + + + +void cProtocol180::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Forward); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Sideways); + HANDLE_READ(a_ByteBuffer, ReadChar, char, Flags); + + if ((Flags & 0x2) != 0) + { + m_Client->HandleUnmount(); + } + else if ((Flags & 0x1) != 0) + { + m_Client->HandleSteerVehicle(Forward, Sideways); + } +} + + + + + +void cProtocol180::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Text); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, HasPosition); + + if (HasPosition) + { + HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Position); + } + + m_Client->HandleTabCompletion(Text); +} + + + + + +void cProtocol180::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockX); + HANDLE_READ(a_ByteBuffer, ReadBEShort, short, BlockY); + HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockZ); + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line1); + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line2); + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line3); + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line4); + m_Client->HandleUpdateSign(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); +} + + + + + +void cProtocol180::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, EntityID); + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Type); + + switch (Type) + { + case 0: + { + m_Client->HandleUseEntity((int)EntityID, false); + break; + } + case 1: + { + m_Client->HandleUseEntity((int)EntityID, true); + break; + } + case 2: + { + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetX); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetY); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetZ); + + // TODO: Do anything + break; + } + default: + { + ASSERT(!"Unhandled use entity type!"); + return; + } + } +} + + + + + +void cProtocol180::HandlePacketEnchantItem(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, WindowID); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Enchantment); + + m_Client->HandleEnchantItem(WindowID, Enchantment); +} + + + + + +void cProtocol180::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadChar, char, WindowID); + HANDLE_READ(a_ByteBuffer, ReadBEShort, short, SlotNum); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Button); + HANDLE_READ(a_ByteBuffer, ReadBEShort, short, TransactionID); + HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Mode); + cItem Item; + ReadItem(a_ByteBuffer, Item); + + // Convert Button, Mode, SlotNum and HeldItem into eClickAction: + eClickAction Action; + switch ((Mode << 8) | Button) + { + case 0x0000: Action = (SlotNum != -999) ? caLeftClick : caLeftClickOutside; break; + case 0x0001: Action = (SlotNum != -999) ? caRightClick : caRightClickOutside; break; + case 0x0100: Action = caShiftLeftClick; break; + case 0x0101: Action = caShiftRightClick; break; + case 0x0200: Action = caNumber1; break; + case 0x0201: Action = caNumber2; break; + case 0x0202: Action = caNumber3; break; + case 0x0203: Action = caNumber4; break; + case 0x0204: Action = caNumber5; break; + case 0x0205: Action = caNumber6; break; + case 0x0206: Action = caNumber7; break; + case 0x0207: Action = caNumber8; break; + case 0x0208: Action = caNumber9; break; + case 0x0300: Action = caMiddleClick; break; + case 0x0400: Action = (SlotNum == -999) ? caLeftClickOutsideHoldNothing : caDropKey; break; + case 0x0401: Action = (SlotNum == -999) ? caRightClickOutsideHoldNothing : caCtrlDropKey; break; + case 0x0500: Action = (SlotNum == -999) ? caLeftPaintBegin : caUnknown; break; + case 0x0501: Action = (SlotNum != -999) ? caLeftPaintProgress : caUnknown; break; + case 0x0502: Action = (SlotNum == -999) ? caLeftPaintEnd : caUnknown; break; + case 0x0504: Action = (SlotNum == -999) ? caRightPaintBegin : caUnknown; break; + case 0x0505: Action = (SlotNum != -999) ? caRightPaintProgress : caUnknown; break; + case 0x0506: Action = (SlotNum == -999) ? caRightPaintEnd : caUnknown; break; + case 0x0600: Action = caDblClick; break; + default: + { + LOGWARNING("Unhandled window click mode / button combination: %d (0x%x)", (Mode << 8) | Button, (Mode << 8) | Button); + Action = caUnknown; + break; + } + } + + m_Client->HandleWindowClick(WindowID, SlotNum, Action, Item); +} + + + + + +void cProtocol180::HandlePacketWindowClose(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadChar, char, WindowID); + m_Client->HandleWindowClose(WindowID); } -void cProtocol180::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) +void cProtocol180::WritePacket(cByteBuffer & a_Packet) { - ASSERT(m_State == 3); // In game mode? - - /*cPacketizer Pkt(*this, 0x04); // Entity Equipment packet - Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); - Pkt.WriteShort(a_SlotNum); - Pkt.WriteItem(a_Item);*/ + cCSLock Lock(m_CSPacket); + AString Pkt; + a_Packet.ReadAll(Pkt); + WriteVarInt((UInt32)Pkt.size()); + SendData(Pkt.data(), Pkt.size()); + Flush(); } -void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) +void cProtocol180::SendData(const char * a_Data, size_t a_Size) { - // Send the Join Game packet: + if (m_IsEncrypted) { - cServer * Server = cRoot::Get()->GetServer(); - cPacketizer Pkt(*this, 0x01); // Join Game packet - Pkt.WriteInt(a_Player.GetUniqueID()); - Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 - Pkt.WriteChar((char)a_World.GetDimension()); - Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) - Pkt.WriteByte(std::min(Server->GetMaxPlayers(), 60)); - Pkt.WriteString("default"); // Level type - wtf? - Pkt.WriteBool(false); // Reduced Debug Info - wtf? + Byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks) + while (a_Size > 0) + { + size_t NumBytes = (a_Size > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Size; + m_Encryptor.ProcessData(Encrypted, (Byte *)a_Data, NumBytes); + m_Client->SendData((const char *)Encrypted, NumBytes); + a_Size -= NumBytes; + a_Data += NumBytes; + } } - m_LastSentDimension = a_World.GetDimension(); - - // Send the spawn position: + else { - cPacketizer Pkt(*this, 0x05); // Spawn Position packet - Pkt.WritePosition(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); + m_Client->SendData(a_Data, a_Size); } - - // Send player abilities: - SendPlayerAbilities(); } @@ -752,7 +2357,7 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) AString Metadata; a_ByteBuffer.ReadAll(Metadata); - ParseItemMetadata(a_Item, Metadata, false); + ParseItemMetadata(a_Item, Metadata); return true; } @@ -760,45 +2365,69 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) -void cProtocol180::HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer) +void cProtocol180::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) { - HANDLE_READ(a_ByteBuffer, ReadBEShort, short, SlotNum); - cItem Item; - if (!ReadItem(a_ByteBuffer, Item)) + // Parse into NBT: + cParsedNBT NBT(a_Metadata.data(), a_Metadata.size()); + if (!NBT.IsValid()) { + AString HexDump; + CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16); + LOGWARNING("Cannot parse NBT item metadata: (" SIZE_T_FMT " bytes)\n%s", a_Metadata.size(), HexDump.c_str()); return; } - m_Client->HandleCreativeInventory(SlotNum, Item); -} - - - - - -void cProtocol180::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) -{ - HANDLE_READ(a_ByteBuffer, ReadChar, char, ActionID); - switch (ActionID) + + // Load enchantments and custom display names from the NBT data: + for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag)) { - case 0: + AString TagName = NBT.GetName(tag); + switch (NBT.GetType(tag)) { - // Respawn - m_Client->HandleRespawn(); - break; - } - case 1: - { - // Request stats - const cStatManager & Manager = m_Client->GetPlayer()->GetStatManager(); - SendStatistics(Manager); - - break; - } - case 2: - { - // Open Inventory achievement - m_Client->GetPlayer()->AwardAchievement(achOpenInv); - break; + case TAG_List: + { + if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags + { + EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); + } + break; + } + case TAG_Compound: + { + if (TagName == "display") // Custom name and lore tag + { + for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag)) + { + if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag + { + a_Item.m_CustomName = NBT.GetString(displaytag); + } + else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag + { + AString Lore; + + for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings + { + AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a grave accent/backtick, used internally by MCS to display a new line in the client; don't forget to c_str ;) + } + + a_Item.m_Lore = Lore; + } + } + } + else if ((TagName == "Fireworks") || (TagName == "Explosion")) + { + cFireworkItem::ParseFromNBT(a_Item.m_FireworkItem, NBT, tag, (ENUM_ITEM_ID)a_Item.m_ItemType); + } + break; + } + case TAG_Int: + { + if (TagName == "RepairCost") + { + a_Item.m_RepairCost = NBT.GetInt(tag); + } + } + default: LOGD("Unimplemented NBT data when parsing!"); break; } } } @@ -807,173 +2436,144 @@ void cProtocol180::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) -void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) -{ - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); - AString Data; - if (!a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1)) - { - return; - } - m_Client->HandlePluginMessage(Channel, Data); -} - - - - - -void cProtocol180::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) -{ - cServer * Server = cRoot::Get()->GetServer(); - AString ServerDescription = Server->GetDescription(); - int NumPlayers = Server->GetNumPlayers(); - int MaxPlayers = Server->GetMaxPlayers(); - AString Favicon = Server->GetFaviconData(); - cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon); - - // Version: - Json::Value Version; - Version["name"] = "1.8"; - Version["protocol"] = 47; - - // Players: - Json::Value Players; - Players["online"] = NumPlayers; - Players["max"] = MaxPlayers; - // TODO: Add "sample" - - // Description: - Json::Value Description; - Description["text"] = ServerDescription.c_str(); - - // Create the response: - Json::Value ResponseValue; - ResponseValue["version"] = Version; - ResponseValue["players"] = Players; - ResponseValue["description"] = Description; - if (!Favicon.empty()) - { - ResponseValue["favicon"] = Printf("data:image/png;base64,%s", Favicon.c_str()); - } - - Json::StyledWriter Writer; - AString Response = Writer.write(ResponseValue); - - cPacketizer Pkt(*this, 0x00); // Response packet - Pkt.WriteString(Response); -} - - - - - -void cProtocol180::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) +void cProtocol180::StartEncryption(const Byte * a_Key) { - AString Username; - if (!a_ByteBuffer.ReadVarUTF8String(Username)) - { - m_Client->Kick("Bad username"); - return; - } - - if (!m_Client->HandleHandshake(Username)) - { - // The client is not welcome here, they have been sent a Kick packet already - return; - } + m_Encryptor.Init(a_Key, a_Key); + m_Decryptor.Init(a_Key, a_Key); + m_IsEncrypted = true; + // Prepare the m_AuthServerID: + cSha1Checksum Checksum; cServer * Server = cRoot::Get()->GetServer(); - // If auth is required, then send the encryption request: - if (Server->ShouldAuthenticate()) - { - cPacketizer Pkt(*this, 0x01); - Pkt.WriteString(Server->GetServerID()); - const AString & PubKeyDer = Server->GetPublicKeyDER(); - Pkt.WriteVarInt((short)PubKeyDer.size()); - Pkt.WriteBuf(PubKeyDer.data(), PubKeyDer.size()); - Pkt.WriteVarInt(4); - Pkt.WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :) - m_Client->SetUsername(Username); - return; - } - - m_Client->HandleLogin(4, Username); + const AString & ServerID = Server->GetServerID(); + Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length()); + Checksum.Update(a_Key, 16); + Checksum.Update((const Byte *)Server->GetPublicKeyDER().data(), Server->GetPublicKeyDER().size()); + Byte Digest[20]; + Checksum.Finalize(Digest); + cSha1Checksum::DigestToJava(Digest, m_AuthServerID); } -void cProtocol180::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) +void cProtocol180::AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) { - UInt32 EncKeyLength, EncNonceLength; - a_ByteBuffer.ReadVarInt(EncKeyLength); - AString EncKey; - if (!a_ByteBuffer.ReadString(EncKey, EncKeyLength)) - { - return; - } - a_ByteBuffer.ReadVarInt(EncNonceLength); - AString EncNonce; - if (!a_ByteBuffer.ReadString(EncNonce, EncNonceLength)) - { - return; - } - if ((EncKeyLength > MAX_ENC_LEN) || (EncNonceLength > MAX_ENC_LEN)) - { - LOGD("Too long encryption"); - m_Client->Kick("Hacked client"); - return; - } - - // Decrypt EncNonce using privkey - cRsaPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey(); - Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)]; - int res = rsaDecryptor.Decrypt((const Byte *)EncNonce.data(), EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce)); - if (res != 4) - { - LOGD("Bad nonce length: got %d, exp %d", res, 4); - m_Client->Kick("Hacked client"); - return; - } - if (ntohl(DecryptedNonce[0]) != (unsigned)(uintptr_t)this) - { - LOGD("Bad nonce value"); - m_Client->Kick("Hacked client"); - return; - } - - // Decrypt the symmetric encryption key using privkey: - Byte DecryptedKey[MAX_ENC_LEN]; - res = rsaDecryptor.Decrypt((const Byte *)EncKey.data(), EncKey.size(), DecryptedKey, sizeof(DecryptedKey)); - if (res != 16) + size_t len = a_PartStyle.length(); + for (size_t i = 0; i < len; i++) { - LOGD("Bad key length"); - m_Client->Kick("Hacked client"); - return; - } - - StartEncryption(DecryptedKey); - m_Client->HandleLogin(4, m_Client->GetUsername()); + switch (a_PartStyle[i]) + { + case 'b': + { + // bold + a_Value["bold"] = Json::Value(true); + break; + } + + case 'i': + { + // italic + a_Value["italic"] = Json::Value(true); + break; + } + + case 'u': + { + // Underlined + a_Value["underlined"] = Json::Value(true); + break; + } + + case 's': + { + // strikethrough + a_Value["strikethrough"] = Json::Value(true); + break; + } + + case 'o': + { + // obfuscated + a_Value["obfuscated"] = Json::Value(true); + break; + } + + case '@': + { + // Color, specified by the next char: + i++; + if (i >= len) + { + // String too short, didn't contain a color + break; + } + switch (a_PartStyle[i]) + { + case '0': a_Value["color"] = Json::Value("black"); break; + case '1': a_Value["color"] = Json::Value("dark_blue"); break; + case '2': a_Value["color"] = Json::Value("dark_green"); break; + case '3': a_Value["color"] = Json::Value("dark_aqua"); break; + case '4': a_Value["color"] = Json::Value("dark_red"); break; + case '5': a_Value["color"] = Json::Value("dark_purple"); break; + case '6': a_Value["color"] = Json::Value("gold"); break; + case '7': a_Value["color"] = Json::Value("gray"); break; + case '8': a_Value["color"] = Json::Value("dark_gray"); break; + case '9': a_Value["color"] = Json::Value("blue"); break; + case 'a': a_Value["color"] = Json::Value("green"); break; + case 'b': a_Value["color"] = Json::Value("aqua"); break; + case 'c': a_Value["color"] = Json::Value("red"); break; + case 'd': a_Value["color"] = Json::Value("light_purple"); break; + case 'e': a_Value["color"] = Json::Value("yellow"); break; + case 'f': a_Value["color"] = Json::Value("white"); break; + } // switch (color) + } // case '@' + } // switch (Style[i]) + } // for i - a_PartStyle[] } -void cProtocol180::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) +//////////////////////////////////////////////////////////////////////////////// +// cProtocol180::cPacketizer: + +cProtocol180::cPacketizer::~cPacketizer() { - HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Forward); - HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Sideways); - HANDLE_READ(a_ByteBuffer, ReadChar, char, Flags); + AString DataToSend; - if ((Flags & 0x2) != 0) + // Send the packet length + UInt32 PacketLen = (UInt32)m_Out.GetUsedSpace(); + + if (m_Protocol.m_State == 3) { - m_Client->HandleUnmount(); + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen + 1); + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(0); } - else if ((Flags & 0x1) != 0) + else { - m_Client->HandleSteerVehicle(Forward, Sideways); + m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); + } + m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); + m_Protocol.SendData(DataToSend.data(), DataToSend.size()); + m_Protocol.m_OutPacketLenBuffer.CommitRead(); + + // Send the packet data: + m_Out.ReadAll(DataToSend); + m_Protocol.SendData(DataToSend.data(), DataToSend.size()); + m_Out.CommitRead(); + + // Log the comm into logfile: + if (g_ShouldLogCommOut) + { + AString Hex; + ASSERT(DataToSend.size() > 0); + CreateHexDump(Hex, DataToSend.data() + 1, DataToSend.size() - 1, 16); + m_Protocol.m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload:\n%s\n", + DataToSend[0], DataToSend[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str() + ); } } @@ -981,171 +2581,518 @@ void cProtocol180::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) -void cProtocol180::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) +void cProtocol180::cPacketizer::WriteItem(const cItem & a_Item) { - HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, PlayerID); - HANDLE_READ(a_ByteBuffer, ReadChar, char, Action); - HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, JumpBoost); + short ItemType = a_Item.m_ItemType; + ASSERT(ItemType >= -1); // Check validity of packets in debug runtime + if (ItemType <= 0) + { + // Fix, to make sure no invalid values are sent. + ItemType = -1; + } + + if (a_Item.IsEmpty()) + { + WriteShort(-1); + return; + } + + WriteShort(ItemType); + WriteByte (a_Item.m_ItemCount); + WriteShort(a_Item.m_ItemDamage); + + if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR)) + { + WriteChar(0); + return; + } - switch (Action) + // Send the enchantments and custom names: + cFastNBTWriter Writer; + if (a_Item.m_RepairCost != 0) { - case 0: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch - case 1: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch - case 2: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed - case 3: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting - case 4: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting + Writer.AddInt("RepairCost", a_Item.m_RepairCost); + } + if (!a_Item.m_Enchantments.IsEmpty()) + { + const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; + EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); + } + if (!a_Item.IsBothNameAndLoreEmpty()) + { + Writer.BeginCompound("display"); + if (!a_Item.IsCustomNameEmpty()) + { + Writer.AddString("Name", a_Item.m_CustomName.c_str()); + } + if (!a_Item.IsLoreEmpty()) + { + Writer.BeginList("Lore", TAG_String); + + AStringVector Decls = StringSplit(a_Item.m_Lore, "`"); + for (AStringVector::const_iterator itr = Decls.begin(), end = Decls.end(); itr != end; ++itr) + { + if (itr->empty()) + { + // The decl is empty (two `s), ignore + continue; + } + Writer.AddString("", itr->c_str()); + } + + Writer.EndList(); + } + Writer.EndCompound(); + } + if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) + { + cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, (ENUM_ITEM_ID)a_Item.m_ItemType); } + Writer.Finish(); + + AString Result = Writer.GetResult(); + if (Result.size() == 0) + { + WriteChar(0); + return; + } + WriteBuf(Result.data(), Result.size()); } -void cProtocol180::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) +void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEntity) { - HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, EntityID); - HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Type); + cFastNBTWriter Writer; - switch (Type) + switch (a_BlockEntity.GetBlockType()) { - case 0: + case E_BLOCK_BEACON: { - m_Client->HandleUseEntity((int)EntityID, false); + 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 1: + case E_BLOCK_COMMAND_BLOCK: { - m_Client->HandleUseEntity((int)EntityID, true); + cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity; + + Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this + Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult()); + Writer.AddInt("x", CommandBlockEntity.GetPosX()); + Writer.AddInt("y", CommandBlockEntity.GetPosY()); + Writer.AddInt("z", CommandBlockEntity.GetPosZ()); + Writer.AddString("Command", CommandBlockEntity.GetCommand().c_str()); + // You can set custom names for windows in Vanilla + // For a command block, this would be the 'name' prepended to anything it outputs into global chat + // MCS doesn't have this, so just leave it @ '@'. (geddit?) + Writer.AddString("CustomName", "@"); + Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + + if (!CommandBlockEntity.GetLastOutput().empty()) + { + AString Output; + Printf(Output, "{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str()); + + Writer.AddString("LastOutput", Output.c_str()); + } break; } - case 2: + case E_BLOCK_HEAD: { - HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetX); - HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetY); - HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetZ); - - // TODO: Do anything + cMobHeadEntity & MobHeadEntity = (cMobHeadEntity &)a_BlockEntity; + + Writer.AddInt("x", MobHeadEntity.GetPosX()); + Writer.AddInt("y", MobHeadEntity.GetPosY()); + Writer.AddInt("z", MobHeadEntity.GetPosZ()); + Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF); + Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF); + Writer.AddString("ExtraType", MobHeadEntity.GetOwner().c_str()); + Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though break; } - default: + case E_BLOCK_FLOWER_POT: { - ASSERT(!"Unhandled use entity type!"); - return; + cFlowerPotEntity & FlowerPotEntity = (cFlowerPotEntity &)a_BlockEntity; + + Writer.AddInt("x", FlowerPotEntity.GetPosX()); + Writer.AddInt("y", FlowerPotEntity.GetPosY()); + Writer.AddInt("z", FlowerPotEntity.GetPosZ()); + Writer.AddInt("Item", (Int32) FlowerPotEntity.GetItem().m_ItemType); + Writer.AddInt("Data", (Int32) FlowerPotEntity.GetItem().m_ItemDamage); + Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + break; } + default: break; } -} - - + Writer.Finish(); - -void cProtocol180::HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) -{ - HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, KeepAliveID); - m_Client->HandleKeepAlive((int)KeepAliveID); + AString Compressed; + CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); + WriteShort((short)Compressed.size()); + WriteBuf(Compressed.data(), Compressed.size()); } -void cProtocol180::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) +void cProtocol180::cPacketizer::WriteByteAngle(double a_Angle) { - HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); - HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); - HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); - HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); - m_Client->HandlePlayerPos(PosX, PosY, PosZ, PosY + 1.62, IsOnGround); + WriteByte((char)(255 * a_Angle / 360)); } -void cProtocol180::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) +void cProtocol180::cPacketizer::WriteFPInt(double a_Value) { - HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); - HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); - HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); - HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); - HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); - HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); - m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, PosY + 1.62, Yaw, Pitch, IsOnGround); + int Value = (int)(a_Value * 32); + WriteInt(Value); } -void cProtocol180::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) +void cProtocol180::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) { - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Locale); - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ViewDistance); - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ChatFlags); - HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors); - HANDLE_READ(a_ByteBuffer, ReadChar, char, SkinFlags); + // Common metadata: + Byte Flags = 0; + if (a_Entity.IsOnFire()) + { + Flags |= 0x01; + } + if (a_Entity.IsCrouched()) + { + Flags |= 0x02; + } + if (a_Entity.IsSprinting()) + { + Flags |= 0x08; + } + if (a_Entity.IsRclking()) + { + Flags |= 0x10; + } + if (a_Entity.IsInvisible()) + { + Flags |= 0x20; + } + WriteByte(0); // Byte(0) + index 0 + WriteByte(Flags); - m_Client->SetLocale(Locale); - // TODO: Handle other values -} - - - - - -void cProtocol180::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) -{ - int BlockX, BlockY, BlockZ; - if (!a_ByteBuffer.ReadPosition(BlockX, BlockY, BlockZ)) + switch (a_Entity.GetEntityType()) { - return; + case cEntity::etPlayer: break; // TODO? + case cEntity::etPickup: + { + WriteByte((5 << 5) | 10); // Slot(5) + index 10 + WriteItem(((const cPickup &)a_Entity).GetItem()); + break; + } + case cEntity::etMinecart: + { + WriteByte(0x51); + + // The following expression makes Minecarts shake more with less health or higher damage taken + // It gets half the maximum health, and takes it away from the current health minus the half health: + /* + Health: 5 | 3 - (5 - 3) = 1 (shake power) + Health: 3 | 3 - (3 - 3) = 3 + Health: 1 | 3 - (1 - 3) = 5 + */ + WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4); + WriteByte(0x52); + WriteInt(1); // Shaking direction, doesn't seem to affect anything + WriteByte(0x73); + WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer + + if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpNone) + { + cRideableMinecart & RideableMinecart = ((cRideableMinecart &)a_Entity); + const cItem & MinecartContent = RideableMinecart.GetContent(); + if (!MinecartContent.IsEmpty()) + { + WriteByte(0x54); + int Content = MinecartContent.m_ItemType; + Content |= MinecartContent.m_ItemDamage << 8; + WriteInt(Content); + WriteByte(0x55); + WriteInt(RideableMinecart.GetBlockHeight()); + WriteByte(0x56); + WriteByte(1); + } + } + else if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace) + { + WriteByte(0x10); + WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); + } + break; + } + case cEntity::etProjectile: + { + cProjectileEntity & Projectile = (cProjectileEntity &)a_Entity; + switch (Projectile.GetProjectileKind()) + { + case cProjectileEntity::pkArrow: + { + WriteByte(0x10); + WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); + break; + } + case cProjectileEntity::pkFirework: + { + WriteByte(0xA8); + WriteItem(((const cFireworkEntity &)a_Entity).GetItem()); + break; + } + default: break; + } + break; + } + case cEntity::etMonster: + { + WriteMobMetadata((const cMonster &)a_Entity); + break; + } + case cEntity::etItemFrame: + { + cItemFrame & Frame = (cItemFrame &)a_Entity; + WriteByte(0xA2); + WriteItem(Frame.GetItem()); + WriteByte(0x3); + WriteByte(Frame.GetRotation()); + break; + } + default: break; } - - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Face); - cItem Item; - ReadItem(a_ByteBuffer, Item); - - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorX); - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorY); - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorZ); - m_Client->HandleRightClick(BlockX, BlockY, BlockZ, static_cast(Face), CursorX, CursorY, CursorZ, m_Client->GetPlayer()->GetEquippedItem()); } -void cProtocol180::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) +void cProtocol180::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) { - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Status); - - int BlockX, BlockY, BlockZ; - if (!a_ByteBuffer.ReadPosition(BlockX, BlockY, BlockZ)) + switch (a_Mob.GetMobType()) { - return; - } + case cMonster::mtCreeper: + { + WriteByte(0x10); + WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); + WriteByte(0x11); + WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); + break; + } + + case cMonster::mtBat: + { + WriteByte(0x10); + WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); + break; + } + + case cMonster::mtPig: + { + WriteByte(0x10); + WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); + break; + } + + case cMonster::mtVillager: + { + WriteByte(0x50); + WriteInt(((const cVillager &)a_Mob).GetVilType()); + break; + } + + case cMonster::mtZombie: + { + WriteByte(0x0c); + WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); + WriteByte(0x0d); + WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); + WriteByte(0x0e); + WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); + break; + } + + case cMonster::mtGhast: + { + WriteByte(0x10); + WriteByte(((const cGhast &)a_Mob).IsCharging()); + break; + } + + case cMonster::mtWolf: + { + const cWolf & Wolf = (const cWolf &)a_Mob; + Byte WolfStatus = 0; + if (Wolf.IsSitting()) + { + WolfStatus |= 0x1; + } + if (Wolf.IsAngry()) + { + WolfStatus |= 0x2; + } + if (Wolf.IsTame()) + { + WolfStatus |= 0x4; + } + WriteByte(0x10); + WriteByte(WolfStatus); + + WriteByte(0x72); + WriteFloat((float)(a_Mob.GetHealth())); + WriteByte(0x13); + WriteByte(Wolf.IsBegging() ? 1 : 0); + WriteByte(0x14); + WriteByte(Wolf.GetCollarColor()); + break; + } + + case cMonster::mtSheep: + { + WriteByte(0x10); + Byte SheepMetadata = 0; + SheepMetadata = ((const cSheep &)a_Mob).GetFurColor(); + if (((const cSheep &)a_Mob).IsSheared()) + { + SheepMetadata |= 0x10; + } + WriteByte(SheepMetadata); + break; + } + + case cMonster::mtEnderman: + { + WriteByte(0x10); + WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); + WriteByte(0x11); + WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); + WriteByte(0x12); + WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); + break; + } + + case cMonster::mtSkeleton: + { + WriteByte(0x0d); + WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); + break; + } + + case cMonster::mtWitch: + { + WriteByte(0x15); + WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); + break; + } - HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Face); - m_Client->HandleLeftClick(BlockX, BlockY, BlockZ, static_cast(Face), Status); + case cMonster::mtWither: + { + WriteByte(0x54); // Int at index 20 + WriteInt(((const cWither &)a_Mob).GetWitherInvulnerableTicks()); + WriteByte(0x66); // Float at index 6 + WriteFloat((float)(a_Mob.GetHealth())); + break; + } + + case cMonster::mtSlime: + { + WriteByte(0x10); + WriteByte(((const cSlime &)a_Mob).GetSize()); + break; + } + + case cMonster::mtMagmaCube: + { + WriteByte(0x10); + WriteByte(((const cMagmaCube &)a_Mob).GetSize()); + break; + } + + case cMonster::mtHorse: + { + const cHorse & Horse = (const cHorse &)a_Mob; + int Flags = 0; + if (Horse.IsTame()) + { + Flags |= 0x02; + } + if (Horse.IsSaddled()) + { + Flags |= 0x04; + } + if (Horse.IsChested()) + { + Flags |= 0x08; + } + if (Horse.IsBaby()) + { + Flags |= 0x10; + } + if (Horse.IsEating()) + { + Flags |= 0x20; + } + if (Horse.IsRearing()) + { + Flags |= 0x40; + } + if (Horse.IsMthOpen()) + { + Flags |= 0x80; + } + WriteByte(0x50); // Int at index 16 + WriteInt(Flags); + WriteByte(0x13); // Byte at index 19 + WriteByte(Horse.GetHorseType()); + WriteByte(0x54); // Int at index 20 + int Appearance = 0; + Appearance = Horse.GetHorseColor(); + Appearance |= Horse.GetHorseStyle() << 8; + WriteInt(Appearance); + WriteByte(0x56); // Int at index 22 + WriteInt(Horse.GetHorseArmour()); + break; + } + } // switch (a_Mob.GetType()) } -void cProtocol180::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) +void cProtocol180::cPacketizer::WriteEntityProperties(const cEntity & a_Entity) { - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Text); - HANDLE_READ(a_ByteBuffer, ReadBool, bool, HasPosition); - - if (HasPosition) + if (!a_Entity.IsMob()) { - HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Position); + // No properties for anything else than mobs + WriteInt(0); + return; } - m_Client->HandleTabCompletion(Text); -} + // const cMonster & Mob = (const cMonster &)a_Entity; + // TODO: Send properties and modifiers based on the mob type + + WriteInt(0); // NumProperties +} diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index a3478e674..f9d5a24dd 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -4,7 +4,7 @@ /* Declares the 1.8.x protocol classes: - cProtocol180 - - release 1.8 protocol (#47) + - release 1.8.0 protocol (#47) (others may be added later in the future for the 1.8 release series) */ @@ -15,7 +15,6 @@ Declares the 1.8.x protocol classes: #pragma once #include "Protocol.h" -#include "Protocol17x.h" #include "../ByteBuffer.h" #ifdef _MSC_VER @@ -31,6 +30,9 @@ Declares the 1.8.x protocol classes: #pragma warning(pop) #endif +#include "PolarSSL++/AesCfb128Decryptor.h" +#include "PolarSSL++/AesCfb128Encryptor.h" + @@ -46,76 +48,273 @@ namespace Json class cProtocol180 : - public cProtocol176 + public cProtocol { - typedef cProtocol176 super; + typedef cProtocol super; public: cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State); + + /** Called when client sends some data: */ + virtual void DataReceived(const char * a_Data, size_t a_Size) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendLoginSuccess (void) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override {} - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override {} - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + /** Sending stuff to clients (alphabetically sorted): */ + virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; + virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; + virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; + virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; + virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; + virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; + virtual void SendDisconnect (const AString & a_Reason) override; + virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) + virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; + virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; + virtual void SendEntityHeadLook (const cEntity & a_Entity) override; + virtual void SendEntityLook (const cEntity & a_Entity) override; + virtual void SendEntityMetadata (const cEntity & a_Entity) override; + virtual void SendEntityProperties (const cEntity & a_Entity) override; virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityLook(const cEntity & a_Entity) override; - virtual void SendTeleportEntity(const cEntity & a_Entity) override; - virtual void SendEntityHeadLook(const cEntity & a_Entity) override; - virtual void SendEntityMetadata(const cEntity & a_Entity) override; - virtual void SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; - virtual void SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) override; - virtual void SendEntityProperties(const cEntity & a_Entity) override; - virtual void SendKeepAlive(int a_PingID) override; - virtual void SendHealth(void) override; - virtual void SendExperience(void) override; - virtual void SendPaintingSpawn(const cPainting & a_Painting) override; - virtual void SendPluginMessage(const AString & a_Channel, const AString & a_Message) override; - virtual void SendUnloadChunk(int a_ChunkX, int a_ChunkZ) override; - virtual void SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat(const AString & a_Message) override; - virtual void SendChat(const cCompositeChat & a_Message) override; - virtual void SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) override {} - virtual void SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendLogin(const cPlayer & a_Player, const cWorld & a_World) override; + virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; + virtual void SendEntityVelocity (const cEntity & a_Entity) override; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; + virtual void SendGameMode (eGameMode a_GameMode) override; + virtual void SendHealth (void) override; + virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; + virtual void SendKeepAlive (int a_PingID) override; + virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; + virtual void SendLoginSuccess (void) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; + virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendPickupSpawn (const cPickup & a_Pickup) override; + virtual void SendPlayerAbilities (void) override; + virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; + virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerMaxSpeed (void) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerPosition (void) override; + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; + virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; + virtual void SendExperience (void) override; + virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; + virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; + virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; + virtual void SendSpawnMob (const cMonster & a_Mob) override; + virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; + virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; + virtual void SendStatistics (const cStatManager & a_Manager) override; + virtual void SendTabCompletionResults(const AStringVector & a_Results) override; + virtual void SendTeleportEntity (const cEntity & a_Entity) override; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; + virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; + virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendWeather (eWeather a_Weather) override; + virtual void SendWholeInventory (const cWindow & a_Window) override; + virtual void SendWindowClose (const cWindow & a_Window) override; + virtual void SendWindowOpen (const cWindow & a_Window) override; + virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; + + virtual AString GetAuthServerID(void) override { return m_AuthServerID; } protected: - virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) override; + /** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */ + class cPacketizer + { + public: + cPacketizer(cProtocol180 & a_Protocol, UInt32 a_PacketType) : + m_Protocol(a_Protocol), + m_Out(a_Protocol.m_OutPacketBuffer), + m_Lock(a_Protocol.m_CSPacket) + { + m_Out.WriteVarInt(a_PacketType); + } + + ~cPacketizer(); - virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) override; + void WriteBool(bool a_Value) + { + m_Out.WriteBool(a_Value); + } + + void WriteByte(Byte a_Value) + { + m_Out.WriteByte(a_Value); + } + + void WriteChar(char a_Value) + { + m_Out.WriteChar(a_Value); + } + + void WriteShort(short a_Value) + { + m_Out.WriteBEShort(a_Value); + } + + void WriteInt(int a_Value) + { + m_Out.WriteBEInt(a_Value); + } + + void WriteInt64(Int64 a_Value) + { + m_Out.WriteBEInt64(a_Value); + } + + void WriteFloat(float a_Value) + { + m_Out.WriteBEFloat(a_Value); + } + + void WriteDouble(double a_Value) + { + m_Out.WriteBEDouble(a_Value); + } + + void WriteVarInt(UInt32 a_Value) + { + m_Out.WriteVarInt(a_Value); + } + + void WriteString(const AString & a_Value) + { + m_Out.WriteVarUTF8String(a_Value); + } - // Packet handlers while in the Login state (m_State == 2): - virtual void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) override; + void WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ) + { + m_Out.WritePosition(a_BlockX, a_BlockY, a_BlockZ); + } + + void WriteBuf(const char * a_Data, size_t a_Size) + { + m_Out.Write(a_Data, a_Size); + } + + void WriteItem(const cItem & a_Item); + void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte + void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer + void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f + void WriteMobMetadata(const cMonster & a_Mob); // Writes the mob-specific metadata for the specified mob + void WriteEntityProperties(const cEntity & a_Entity); // Writes the entity properties for the specified entity, including the Count field + void WriteBlockEntity(const cBlockEntity & a_BlockEntity); + + protected: + cProtocol180 & m_Protocol; + cByteBuffer & m_Out; + cCSLock m_Lock; + } ; + + AString m_ServerAddress; + + UInt16 m_ServerPort; + + AString m_AuthServerID; + + /** State of the protocol. 1 = status, 2 = login, 3 = game */ + UInt32 m_State; + + /** Buffer for the received data */ + cByteBuffer m_ReceivedData; + + /** Buffer for composing the outgoing packets, through cPacketizer */ + cByteBuffer m_OutPacketBuffer; + + /** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */ + cByteBuffer m_OutPacketLenBuffer; + + bool m_IsEncrypted; + + cAesCfb128Decryptor m_Decryptor; + cAesCfb128Encryptor m_Encryptor; + + /** The logfile where the comm is logged, when g_ShouldLogComm is true */ + cFile m_CommLogFile; + + /** The dimension that was last sent to a player in a Respawn or Login packet. + Used to avoid Respawning into the same dimension, which confuses the client. */ + eDimension m_LastSentDimension; + + + /** Adds the received (unencrypted) data to m_ReceivedData, parses complete packets */ + void AddReceivedData(const char * a_Data, size_t a_Size); + + /** Reads and handles the packet. The packet length and type have already been read. + Returns true if the packet was understood, false if it was an unknown packet + */ + bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType); + + // Packet handlers while in the Status state (m_State == 1): + void HandlePacketStatusPing(cByteBuffer & a_ByteBuffer); + void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer); + // Packet handlers while in the Login state (m_State == 2): + void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer); + void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer); + // Packet handlers while in the Game state (m_State == 3): - virtual void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override; - virtual void HandlePacketBlockDig(cByteBuffer & a_ByteBuffer)override; - virtual void HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) override; -} ; + void HandlePacketAnimation (cByteBuffer & a_ByteBuffer); + void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); + void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); + void HandlePacketChatMessage (cByteBuffer & a_ByteBuffer); + void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); + void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); + void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); + void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); + void HandlePacketKeepAlive (cByteBuffer & a_ByteBuffer); + void HandlePacketPlayer (cByteBuffer & a_ByteBuffer); + void HandlePacketPlayerAbilities (cByteBuffer & a_ByteBuffer); + void HandlePacketPlayerLook (cByteBuffer & a_ByteBuffer); + void HandlePacketPlayerPos (cByteBuffer & a_ByteBuffer); + void HandlePacketPlayerPosLook (cByteBuffer & a_ByteBuffer); + void HandlePacketPluginMessage (cByteBuffer & a_ByteBuffer); + void HandlePacketSlotSelect (cByteBuffer & a_ByteBuffer); + void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer); + void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer); + void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer); + void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); + void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer); + void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer); + void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer); + + + /** Writes an entire packet into the output stream. a_Packet is expected to start with the packet type; data length is prepended here. */ + void WritePacket(cByteBuffer & a_Packet); + + /** Sends the data to the client, encrypting them if needed. */ + virtual void SendData(const char * a_Data, size_t a_Size) override; + void SendCompass(const cWorld & a_World); + + /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */ + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item); + + /** Parses item metadata as read by ReadItem(), into the item enchantments. */ + void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); + + void StartEncryption(const Byte * a_Key); + + /** Adds the chat part's style (represented by the part's stylestring) into the Json object. */ + void AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle); +} ; -- cgit v1.2.3 From 76fa3a7ccd69aee7293a19dc06c327020d3cf908 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 8 Sep 2014 20:12:43 +0200 Subject: More fixes. --- src/ClientHandle.cpp | 12 +----------- src/Protocol/Protocol17x.cpp | 2 +- src/Protocol/Protocol18x.cpp | 5 +++++ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 4c36dec4d..a614d5597 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1198,19 +1198,9 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e cWorld * World = m_Player->GetWorld(); - // 1.8 protocol fix - if ((int)a_BlockFace == 255) - { - a_BlockFace = BLOCK_FACE_NONE; - } - if ( (a_BlockFace != BLOCK_FACE_NONE) && // The client is interacting with a specific block - ( - (Diff(m_Player->GetPosX(), (double)a_BlockX) > 6) || // The block is too far away - (Diff(m_Player->GetPosY(), (double)a_BlockY) > 6) || - (Diff(m_Player->GetPosZ(), (double)a_BlockZ) > 6) - ) + ((Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() >= 5) ) { AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 0b94cb144..af1dd06a5 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2560,7 +2560,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR)) { - WriteChar(0); + WriteShort(-1); return; } diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 1793583a2..46773a438 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1908,6 +1908,11 @@ void cProtocol180::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) } HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Face); + if (Face == 255) + { + Face = 0; + } + cItem Item; ReadItem(a_ByteBuffer, Item); -- cgit v1.2.3 From 4b1f4e8d7ecaed0cc9c4dffbf58c5665183297c7 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 9 Sep 2014 01:52:51 +0200 Subject: 1.8: Added new uuid field. --- src/ClientHandle.cpp | 42 +++++++++++++++++++++++++----------------- src/Protocol/Protocol18x.cpp | 17 +++++++++++++++++ src/Protocol/Protocol18x.h | 2 ++ 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index a614d5597..e91644fbc 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1192,6 +1192,8 @@ void cClientHandle::FinishDigAnimation() void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem) { + // TODO: Rewrite this function + LOGD("HandleRightClick: {%d, %d, %d}, face %d, HeldItem: %s", a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, ItemToFullString(a_HeldItem).c_str() ); @@ -1204,14 +1206,17 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e ) { AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - if (a_BlockY < cChunkDef::Height - 1) + if ((a_BlockX >= 0) && (a_BlockY >= 0) && (a_BlockZ >= 0)) { - World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things - } - if (a_BlockY > 0) - { - World->SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, m_Player); // 2 block high things + World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); + if (a_BlockY < cChunkDef::Height - 1) + { + World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things + } + if (a_BlockY > 0) + { + World->SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, m_Player); // 2 block high things + } } m_Player->GetInventory().SendEquippedSlot(); return; @@ -1221,17 +1226,20 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e if (PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ)) { // A plugin doesn't agree with the action, replace the block on the client and quit: - cChunkInterface ChunkInterface(World->GetChunkMap()); - BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType); - BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - - if (a_BlockFace != BLOCK_FACE_NONE) + if ((a_BlockX >= 0) && (a_BlockY >= 0) && (a_BlockZ >= 0)) { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things - m_Player->GetInventory().SendEquippedSlot(); + cChunkInterface ChunkInterface(World->GetChunkMap()); + BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType); + BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + + if (a_BlockFace != BLOCK_FACE_NONE) + { + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); + World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things + m_Player->GetInventory().SendEquippedSlot(); + } } return; } diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 46773a438..60501a5b5 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -2586,6 +2586,23 @@ cProtocol180::cPacketizer::~cPacketizer() +void cProtocol180::cPacketizer::WriteUUID(const AString & a_UUID) +{ + AString UUID_1 = a_UUID.substr(0, a_UUID.length() / 2); + AString UUID_2 = a_UUID.substr(a_UUID.length() / 2); + + UInt64 Value_1, Value_2; + sscanf(UUID_1.c_str(), "%llx", &Value_1); + sscanf(UUID_2.c_str(), "%llx", &Value_2); + + WriteInt64((Int64)Value_1); + WriteInt64((Int64)Value_2); +} + + + + + void cProtocol180::cPacketizer::WriteItem(const cItem & a_Item) { short ItemType = a_Item.m_ItemType; diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index f9d5a24dd..207af0b44 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -204,6 +204,8 @@ protected: m_Out.WritePosition(a_BlockX, a_BlockY, a_BlockZ); } + void WriteUUID(const AString & a_UUID); + void WriteBuf(const char * a_Data, size_t a_Size) { m_Out.Write(a_Data, a_Size); -- cgit v1.2.3 From d1d4f2146e12222071041db7088073dc4a90eb61 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 9 Sep 2014 01:54:40 +0200 Subject: PlayerSpawn packet: Send the correct uuid. --- src/Protocol/Protocol18x.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 60501a5b5..e336dcbec 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -947,11 +947,7 @@ void cProtocol180::SendPlayerSpawn(const cPlayer & a_Player) // Called to spawn another player for the client cPacketizer Pkt(*this, 0x0c); // Spawn Player packet Pkt.WriteVarInt(a_Player.GetUniqueID()); - - // Fake UUID - Pkt.WriteInt64(4053239666997989821); - Pkt.WriteInt64(-5603022497796657139); - + Pkt.WriteUUID(cMojangAPI::MakeUUIDShort(a_Player.GetUUID())); Pkt.WriteFPInt(a_Player.GetPosX()); Pkt.WriteFPInt(a_Player.GetPosY()); Pkt.WriteFPInt(a_Player.GetPosZ()); -- cgit v1.2.3 From f94df06b6601f9dcecd383f5d093d225f41d1c65 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 9 Sep 2014 03:02:25 +0200 Subject: Added the player list to the 1.8 protocol. --- lib/SQLiteCpp | 2 +- src/ClientHandle.cpp | 10 +++-- src/ClientHandle.h | 2 +- src/Entities/Entity.cpp | 2 +- src/Entities/Player.cpp | 4 +- src/Protocol/Protocol.h | 2 +- src/Protocol/Protocol125.cpp | 12 ++++-- src/Protocol/Protocol125.h | 2 +- src/Protocol/Protocol17x.cpp | 13 +++++-- src/Protocol/Protocol17x.h | 2 +- src/Protocol/Protocol18x.cpp | 74 +++++++++++++++++++++++++++++++++---- src/Protocol/Protocol18x.h | 2 +- src/Protocol/ProtocolRecognizer.cpp | 4 +- src/Protocol/ProtocolRecognizer.h | 2 +- src/World.cpp | 6 +-- src/World.h | 2 +- 16 files changed, 109 insertions(+), 32 deletions(-) diff --git a/lib/SQLiteCpp b/lib/SQLiteCpp index 203c2fb68..27b9d1118 160000 --- a/lib/SQLiteCpp +++ b/lib/SQLiteCpp @@ -1 +1 @@ -Subproject commit 203c2fb68bbf871eaf4ca98756a113d74d620dea +Subproject commit 27b9d111818af3b05bcf4153bb6e380fe1dd6816 diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index f24309159..f97ce26c9 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -127,7 +127,7 @@ cClientHandle::~cClientHandle() if (!m_Username.empty() && (World != NULL)) { // Send the Offline PlayerList packet: - World->BroadcastPlayerListItem(*m_Player, false, this); + World->BroadcastPlayerListItem(*m_Player, 4, this); } if (World != NULL) { @@ -366,6 +366,10 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID, m_Player->Initialize(*World); m_State = csAuthenticated; + // Send player list items + SendPlayerListItem(*m_Player, 0); + World->SendPlayerList(m_Player); + // Query player team m_Player->UpdateTeam(); @@ -2378,9 +2382,9 @@ void cClientHandle::SendPlayerAbilities() -void cClientHandle::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cClientHandle::SendPlayerListItem(const cPlayer & a_Player, char a_Action) { - m_Protocol->SendPlayerListItem(a_Player, a_IsOnline); + m_Protocol->SendPlayerListItem(a_Player, a_Action); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 74e89deee..eaa4e90fd 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -156,7 +156,7 @@ public: 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_ParticleAmmount); void SendPlayerAbilities (void); - void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline); + void SendPlayerListItem (const cPlayer & a_Player, char a_Action); void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+) void SendPlayerMoveLook (void); void SendPlayerPosition (void); diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 9bcdcffeb..fba688847 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -135,7 +135,7 @@ const char * cEntity::GetParentClass(void) const bool cEntity::Initialize(cWorld & a_World) { - if (cPluginManager::Get()->CallHookSpawningEntity(a_World, *this)) + if (cPluginManager::Get()->CallHookSpawningEntity(a_World, *this) && !IsPlayer()) { return false; } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index b0da6965a..a720d8c35 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -266,7 +266,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) cTimer t1; if (m_LastPlayerListTime + PLAYER_LIST_TIME_MS <= t1.GetNowTime()) { - m_World->SendPlayerList(this); + m_World->BroadcastPlayerListItem(*this, 2); m_LastPlayerListTime = t1.GetNowTime(); } @@ -1172,6 +1172,8 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) SetFlying(false); SetCanFly(false); } + + m_World->BroadcastPlayerListItem(*this, 1); } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 5811e5bff..902c72675 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -94,7 +94,7 @@ public: virtual void SendPlayerAbilities (void) = 0; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0; virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) = 0; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) = 0; + virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) = 0; virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+) virtual void SendPlayerMoveLook (void) = 0; virtual void SendPlayerPosition (void) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 77939d933..8c4534ff7 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -720,9 +720,15 @@ void cProtocol125::SendPaintingSpawn(const cPainting & a_Painting) -void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, char a_Action) { cCSLock Lock(m_CSPacket); + if (a_Action == 1) + { + // Ignore gamemode update + return; + } + AString PlayerName(a_Player.GetColor()); PlayerName.append(a_Player.GetName()); if (PlayerName.length() > 14) @@ -733,8 +739,8 @@ void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM); WriteString(PlayerName); - WriteBool (a_IsOnline); - WriteShort (a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); + WriteBool (a_Action != 4); + WriteShort ((a_Action == 4) ? 0 : a_Player.GetClientHandle()->GetPing()); Flush(); } diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 1063777a2..029845b8b 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -65,7 +65,7 @@ public: virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 162d4da30..b4f96bd88 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -867,14 +867,19 @@ void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_Sr -void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, char a_Action) { ASSERT(m_State == 3); // In game mode? - + if (a_Action == 1) + { + // Ignore gamemode update + return; + } + cPacketizer Pkt(*this, 0x38); // Playerlist Item packet Pkt.WriteString(a_Player.GetName()); - Pkt.WriteBool(a_IsOnline); - Pkt.WriteShort(a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); + Pkt.WriteBool(a_Action != 4); + Pkt.WriteShort((a_Action == 4) ? 0 : a_Player.GetClientHandle()->GetPing()); } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 24fe1cb20..6bb5873d3 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -101,7 +101,7 @@ public: virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index e336dcbec..5f1f97a4a 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -659,7 +659,7 @@ void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 Pkt.WriteChar((char)a_World.GetDimension()); Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) - Pkt.WriteByte(std::min(Server->GetMaxPlayers(), 60)); + Pkt.WriteByte(Server->GetMaxPlayers()); Pkt.WriteString("default"); // Level type - wtf? Pkt.WriteBool(false); // Reduced Debug Info - wtf? } @@ -868,14 +868,74 @@ void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_Sr -void cProtocol180::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cProtocol180::SendPlayerListItem(const cPlayer & a_Player, char a_Action) { ASSERT(m_State == 3); // In game mode? - - /*cPacketizer Pkt(*this, 0x38); // Playerlist Item packet - Pkt.WriteString(a_Player.GetName()); - Pkt.WriteBool(a_IsOnline); - Pkt.WriteShort(a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0);*/ + + cPacketizer Pkt(*this, 0x38); // Playerlist Item packet + Pkt.WriteVarInt(a_Action); + Pkt.WriteVarInt(1); + Pkt.WriteUUID(a_Player.GetUUID()); + + switch (a_Action) + { + case 0: + { + // Add Player + Pkt.WriteString(a_Player.GetName()); + + const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties(); + Pkt.WriteVarInt(Properties.size()); + for (Json::Value::iterator itr = Properties.begin(), end = Properties.end(); itr != end; ++itr) + { + Pkt.WriteString(((Json::Value)*itr).get("name", "").asString()); + Pkt.WriteString(((Json::Value)*itr).get("value", "").asString()); + AString Signature = ((Json::Value)*itr).get("signature", "").asString(); + if (Signature.empty()) + { + Pkt.WriteBool(false); + } + else + { + Pkt.WriteBool(true); + Pkt.WriteString(Signature); + } + } + + Pkt.WriteVarInt((UInt32)a_Player.GetGameMode()); + Pkt.WriteVarInt((UInt32)a_Player.GetClientHandle()->GetPing()); + Pkt.WriteBool(false); + break; + } + case 1: + { + // Update GameMode + Pkt.WriteVarInt((UInt32)a_Player.GetGameMode()); + break; + } + case 2: + { + // Update Ping + Pkt.WriteVarInt((UInt32)a_Player.GetClientHandle()->GetPing()); + break; + } + case 3: + { + // Update DisplayName + Pkt.WriteBool(false); + break; + } + case 4: + { + // Remove player + break; + } + default: + { + ASSERT(!"Unhandled player list item action!"); + return; + } + } } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 207af0b44..8e8570b68 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -97,7 +97,7 @@ public: virtual void SendPlayerAbilities (void) override; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index c535390cc..56e5b43f3 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -489,10 +489,10 @@ void cProtocolRecognizer::SendEntityAnimation(const cEntity & a_Entity, char a_A -void cProtocolRecognizer::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) +void cProtocolRecognizer::SendPlayerListItem(const cPlayer & a_Player, char a_Action) { ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerListItem(a_Player, a_IsOnline); + m_Protocol->SendPlayerListItem(a_Player, a_Action); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 2e8976a9f..4d2bceb68 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -101,7 +101,7 @@ public: virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override; + virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/World.cpp b/src/World.cpp index e669f6fa0..0e0846943 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2147,7 +2147,7 @@ void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src -void cWorld::BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude) +void cWorld::BroadcastPlayerListItem(const cPlayer & a_Player, char a_Action, const cClientHandle * a_Exclude) { cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) @@ -2157,7 +2157,7 @@ void cWorld::BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, { continue; } - ch->SendPlayerListItem(a_Player, a_IsOnline); + ch->SendPlayerListItem(a_Player, a_Action); } } @@ -2680,7 +2680,7 @@ void cWorld::SendPlayerList(cPlayer * a_DestPlayer) cClientHandle * ch = (*itr)->GetClientHandle(); if ((ch != NULL) && !ch->IsDestroyed()) { - a_DestPlayer->GetClientHandle()->SendPlayerListItem(*(*itr), true); + a_DestPlayer->GetClientHandle()->SendPlayerListItem(*(*itr), 0); } } } diff --git a/src/World.h b/src/World.h index 6316c6811..fae784c20 100644 --- a/src/World.h +++ b/src/World.h @@ -237,7 +237,7 @@ public: void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override; // tolua_export void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export - void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL); + void BroadcastPlayerListItem (const cPlayer & a_Player, char a_Action, const cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); -- cgit v1.2.3 From a880813f270a3b2e53477e87ea363c45b2a71dae Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 9 Sep 2014 11:37:46 +0200 Subject: Downgrade SQLiteCpp again --- lib/SQLiteCpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SQLiteCpp b/lib/SQLiteCpp index 27b9d1118..203c2fb68 160000 --- a/lib/SQLiteCpp +++ b/lib/SQLiteCpp @@ -1 +1 @@ -Subproject commit 27b9d111818af3b05bcf4153bb6e380fe1dd6816 +Subproject commit 203c2fb68bbf871eaf4ca98756a113d74d620dea -- cgit v1.2.3 From 71c3369e084d0b9e3b91f9517069e58aaecc15e3 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 9 Sep 2014 18:27:31 +0200 Subject: 1.8: Added MultiBlockChange packet. --- src/ClientHandle.cpp | 7 +-- src/Protocol/ChunkDataSerializer.cpp | 45 +++++++------------ src/Protocol/Protocol18x.cpp | 83 ++++++++++++++++++++++++++---------- src/Protocol/Protocol18x.h | 5 +++ 4 files changed, 86 insertions(+), 54 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index f97ce26c9..fa2c2124b 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -362,13 +362,14 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID, // Send experience m_Player->SendExperience(); - - m_Player->Initialize(*World); - m_State = csAuthenticated; // Send player list items SendPlayerListItem(*m_Player, 0); + World->BroadcastPlayerListItem(*m_Player, 0); World->SendPlayerList(m_Player); + + m_Player->Initialize(*World); + m_State = csAuthenticated; // Query player team m_Player->UpdateTeam(); diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index d4574954e..268cf4a9f 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -9,6 +9,7 @@ #include "ChunkDataSerializer.h" #include "zlib/zlib.h" #include "ByteBuffer.h" +#include "Protocol18x.h" @@ -54,7 +55,10 @@ const AString & cChunkDataSerializer::Serialize(int a_Version, int a_ChunkX, int break; } } - m_Serializations[a_Version] = data; + if (!data.empty()) + { + m_Serializations[a_Version] = data; + } return m_Serializations[a_Version]; } @@ -219,40 +223,23 @@ void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_Chu Packet.ReadAll(PacketData); Packet.CommitRead(); - cByteBuffer NumberBuffer(20); + cByteBuffer Buffer(20); if (PacketData.size() >= 256) { - AString PostData; - NumberBuffer.WriteVarInt(PacketData.size()); - NumberBuffer.ReadAll(PostData); - NumberBuffer.CommitRead(); - - // Compress the data: - const uLongf CompressedMaxSize = 200000; - char CompressedData[CompressedMaxSize]; - - uLongf CompressedSize = compressBound(PacketData.size()); - // Run-time check that our compile-time guess about CompressedMaxSize was enough: - ASSERT(CompressedSize <= CompressedMaxSize); - compress2((Bytef*)CompressedData, &CompressedSize, (const Bytef*)PacketData.data(), PacketData.size(), Z_DEFAULT_COMPRESSION); - - NumberBuffer.WriteVarInt(CompressedSize + PostData.size()); - NumberBuffer.WriteVarInt(PacketData.size()); - NumberBuffer.ReadAll(PostData); - NumberBuffer.CommitRead(); - - a_Data.clear(); - a_Data.resize(PostData.size() + CompressedSize); - a_Data.append(PostData.data(), PostData.size()); - a_Data.append(CompressedData, CompressedSize); + if (!cProtocol180::CompressPacket(PacketData, a_Data)) + { + ASSERT(!"Packet compression failed."); + a_Data.clear(); + return; + } } else { AString PostData; - NumberBuffer.WriteVarInt(Packet.GetUsedSpace() + 1); - NumberBuffer.WriteVarInt(0); - NumberBuffer.ReadAll(PostData); - NumberBuffer.CommitRead(); + Buffer.WriteVarInt(Packet.GetUsedSpace() + 1); + Buffer.WriteVarInt(0); + Buffer.ReadAll(PostData); + Buffer.CommitRead(); a_Data.clear(); a_Data.resize(PostData.size() + PacketData.size()); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 5f1f97a4a..c7c6402d9 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -200,18 +200,16 @@ void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x22); // Multi Block Change packet + cPacketizer Pkt(*this, 0x22); // Multi Block Change packet Pkt.WriteInt(a_ChunkX); Pkt.WriteInt(a_ChunkZ); Pkt.WriteVarInt((UInt32)a_Changes.size()); for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr) { - short Coords = itr->y | (itr->z << 8) | (itr->x << 12); + short Coords = (short) (itr->y | (itr->z << 8) | (itr->x << 12)); Pkt.WriteShort(Coords); - - UInt32 Block = ((UInt32)itr->BlockType << 4) | ((UInt32)itr->BlockMeta & 15); - Pkt.WriteVarInt(Block); - } // for itr - a_Changes[]*/ + Pkt.WriteVarInt((itr->BlockType & 0xFFF) << 4 | (itr->BlockMeta & 0xF)); + } // for itr - a_Changes[] } @@ -369,9 +367,9 @@ void cProtocol180::SendDestroyEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x13); // Destroy Entities packet + cPacketizer Pkt(*this, 0x13); // Destroy Entities packet Pkt.WriteVarInt(1); - Pkt.WriteVarInt(a_Entity.GetUniqueID());*/ + Pkt.WriteVarInt(a_Entity.GetUniqueID()); } @@ -437,10 +435,10 @@ void cProtocol180::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x04); // Entity Equipment packet + cPacketizer Pkt(*this, 0x04); // Entity Equipment packet Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); Pkt.WriteShort(a_SlotNum); - Pkt.WriteItem(a_Item);*/ + Pkt.WriteItem(a_Item); } @@ -451,9 +449,9 @@ void cProtocol180::SendEntityHeadLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x19); // Entity Head Look packet + cPacketizer Pkt(*this, 0x19); // Entity Head Look packet Pkt.WriteVarInt((UInt32)a_Entity.GetUniqueID()); - Pkt.WriteByteAngle(a_Entity.GetHeadYaw());*/ + Pkt.WriteByteAngle(a_Entity.GetHeadYaw()); } @@ -464,11 +462,11 @@ void cProtocol180::SendEntityLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x16); // Entity Look packet + cPacketizer Pkt(*this, 0x16); // Entity Look packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ + Pkt.WriteBool(true); // TODO: IsOnGround() on entities } @@ -479,10 +477,10 @@ void cProtocol180::SendEntityMetadata(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet + cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteEntityMetadata(a_Entity); - Pkt.WriteByte(0x7f); // The termination byte*/ + Pkt.WriteByte(0x7f); // The termination byte } @@ -506,12 +504,12 @@ void cProtocol180::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet + cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByte(a_RelX); Pkt.WriteByte(a_RelY); Pkt.WriteByte(a_RelZ); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ + Pkt.WriteBool(true); // TODO: IsOnGround() on entities } @@ -522,14 +520,14 @@ void cProtocol180::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet + cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByte(a_RelX); Pkt.WriteByte(a_RelY); Pkt.WriteByte(a_RelZ); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGround() on entities*/ + Pkt.WriteBool(true); // TODO: IsOnGround() on entities } @@ -1320,14 +1318,14 @@ void cProtocol180::SendTeleportEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0x18); + cPacketizer Pkt(*this, 0x18); Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteFPInt(a_Entity.GetPosX()); Pkt.WriteFPInt(a_Entity.GetPosY()); Pkt.WriteFPInt(a_Entity.GetPosZ()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteBool(true); // TODO: IsOnGrond() on entities*/ + Pkt.WriteBool(true); // TODO: IsOnGrond() on entities } @@ -1531,6 +1529,47 @@ void cProtocol180::SendWindowProperty(const cWindow & a_Window, int a_Property, +bool cProtocol180::CompressPacket(const AString & a_Packet, AString & a_CompressedData) +{ + // Compress the data: + const uLongf CompressedMaxSize = 200000; + char CompressedData[CompressedMaxSize]; + + uLongf CompressedSize = compressBound(a_Packet.size()); + if (CompressedSize >= CompressedMaxSize) + { + ASSERT(!"Too high packet size."); + return false; + } + + int Status = compress2((Bytef*)CompressedData, &CompressedSize, (const Bytef*)a_Packet.data(), a_Packet.size(), Z_DEFAULT_COMPRESSION); + if (Status != Z_OK) + { + return false; + } + + AString LengthData; + cByteBuffer Buffer(20); + Buffer.WriteVarInt((UInt32)a_Packet.size()); + Buffer.ReadAll(LengthData); + Buffer.CommitRead(); + + Buffer.WriteVarInt(CompressedSize + LengthData.size()); + Buffer.WriteVarInt(a_Packet.size()); + Buffer.ReadAll(LengthData); + Buffer.CommitRead(); + + a_CompressedData.clear(); + a_CompressedData.resize(LengthData.size() + CompressedSize); + a_CompressedData.append(LengthData.data(), LengthData.size()); + a_CompressedData.append(CompressedData, CompressedSize); + return true; +} + + + + + void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) { // Write the incoming data into the comm log file: diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 8e8570b68..33e298e48 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -133,6 +133,11 @@ public: virtual AString GetAuthServerID(void) override { return m_AuthServerID; } + /** Compress the packet. a_Packet must be without packet length. + a_Compressed will be set to the compressed packet includes packet length and data length. + If compression fails, the function returns false. */ + static bool CompressPacket(const AString & a_Packet, AString & a_Compressed); + protected: /** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */ -- cgit v1.2.3 From c967633d0ae42f3ffa02d2b31ab723db7ab2c6c8 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Wed, 10 Sep 2014 21:02:15 +0200 Subject: Added 1.8 Blocks and Items --- src/BlockID.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/BlockID.h b/src/BlockID.h index d835f9518..d6712a588 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -175,12 +175,35 @@ enum ENUM_BLOCK_ID E_BLOCK_NEW_LOG = 162, E_BLOCK_ACACIA_WOOD_STAIRS = 163, E_BLOCK_DARK_OAK_WOOD_STAIRS = 164, + E_BLOCK_SLIME_BLOCK = 165, + E_BLOCK_IRON_TRAPDOOR = 167, + E_BLOCK_PRISMARINE_BLOCK = 168, + E_BLOCK_SEA_LANTERN = 169, E_BLOCK_HAY_BALE = 170, E_BLOCK_CARPET = 171, E_BLOCK_HARDENED_CLAY = 172, E_BLOCK_BLOCK_OF_COAL = 173, E_BLOCK_PACKED_ICE = 174, E_BLOCK_BIG_FLOWER = 175, + E_BLOCK_RED_SANDSTONE = 179, + E_BLOCK_RED_SANDSTONE_STAIRS = 180, + E_BLOCK_NEW_STONE_SLAB = 181, + E_BLOCK_SPRUCE_FENCE_GATE = 182, + E_BLOCK_BIRCH_FENCE_GATE = 183, + E_BLOCK_JUNGLE_FENCE_GATE = 184, + E_BLOCK_DARK_OAK_FENCE_GATE = 185, + E_BLOCK_ACACIA_FENCE_GATE = 186, + E_BLOCK_SPRUCE_FENCE = 187, + E_BLOCK_BIRCH_FENCE = 188, + E_BLOCK_JUNGLE_FENCE = 189, + E_BLOCK_DARK_OAK_FENCE = 190, + E_BLOCK_ACACIA_FENCE = 191, + // I don't know which block has the ID 192, maybe there is no block but we have to wait for mcp + E_BLOCK_SPRUCE_DOOR = 193, + E_BLOCK_BIRCH_DOOR = 194, + E_BLOCK_JUNGLE_DOOR = 195, + E_BLOCK_ACACIA_DOOR = 196, + E_BLOCK_DARK_OAK_DOOR = 197, // Keep these two as the last values, without a number - they will get their correct number assigned automagically by C++ // IsValidBlock() depends on this @@ -356,6 +379,14 @@ enum ENUM_ITEM_ID E_ITEM_NETHER_QUARTZ = 406, E_ITEM_MINECART_WITH_TNT = 407, E_ITEM_MINECART_WITH_HOPPER = 408, + E_ITEM_PRISMARINE_SHARD = 409, + E_ITEM_PRISMARINE_CRYSTALS = 410, + E_ITEM_RAW_RABBIT = 411, + E_ITEM_COOKED_RABBIT = 412, + E_ITEM_RABBIT_STEW = 413, + E_ITEM_RABBITS_FOOD = 414, + E_ITEM_RABBIT_HIDE = 415, + E_ITEM_ARMOR_STAND = 416, E_ITEM_IRON_HORSE_ARMOR = 417, E_ITEM_GOLD_HORSE_ARMOR = 418, E_ITEM_DIAMOND_HORSE_ARMOR = 419, @@ -364,6 +395,12 @@ enum ENUM_ITEM_ID E_ITEM_MINECART_WITH_COMMAND_BLOCK = 422, E_ITEM_RAW_MUTTON = 423, E_ITEM_MUTTON = 424, + E_ITEM_BANNER = 425, + E_ITEM_SPRUCE_DOOR = 427, + E_ITEM_BIRCH_DOOR = 428, + E_ITEM_JUNGLE_DOOR = 429, + E_ITEM_ACACIA_DOOR = 430, + E_ITEM_DARK_OAK_DOOR = 431, // Keep these two as the last values of the consecutive list, without a number - they will get their correct number assigned automagically by C++ // IsValidItem() depends on this! -- cgit v1.2.3 From 074dcbf9505fa7ab3fc11efc7efbf919929e7b23 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Wed, 10 Sep 2014 21:07:37 +0200 Subject: Added iron trapdoor, fence gates and doors to the redstone simulator --- src/Simulator/IncrementalRedstoneSimulator.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 7b3a2c2fa..a024a8be7 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -286,8 +286,14 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_SPRUCE_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_BIRCH_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_JUNGLE_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_DARK_OAK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_ACACIA_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_ACTIVATOR_RAIL: @@ -298,6 +304,11 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int break; } case E_BLOCK_WOODEN_DOOR: + case E_BLOCK_SPRUCE_DOOR: + case E_BLOCK_BIRCH_DOOR: + case E_BLOCK_JUNGLE_DOOR: + case E_BLOCK_DARK_OAK_DOOR: + case E_BLOCK_ACACIA_DOOR: case E_BLOCK_IRON_DOOR: { HandleDoor(dataitr->x, dataitr->y, dataitr->z); -- cgit v1.2.3 From f173cfe4301913ed435086b493c3d2549a3786a7 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Wed, 10 Sep 2014 21:15:06 +0200 Subject: Added new blocks to the BlockHandler --- src/Blocks/BlockHandler.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 34925a252..689874049 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -176,12 +176,16 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) switch (a_BlockType) { // Block handlers, alphabetically sorted: + case E_BLOCK_ACACIA_DOOR: return new cBlockFenceGateHandler (a_BlockType); + case E_BLOCK_ACACIA_FENCE_GATE: return new cBlockDoorHandler (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_DOOR: return new cBlockDoorHandler (a_BlockType); + case E_BLOCK_BIRCH_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType); case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_BREWING_STAND: return new cBlockBrewingStandHandler (a_BlockType); case E_BLOCK_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType); @@ -199,6 +203,8 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_COBBLESTONE_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_COBWEB: return new cBlockCobWebHandler (a_BlockType); case E_BLOCK_CROPS: return new cBlockCropsHandler (a_BlockType); + case E_BLOCK_DARK_OAK_DOOR: return new cBlockDoorHandler (a_BlockType); + case E_BLOCK_DARK_OAK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType); case E_BLOCK_DARK_OAK_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_DEAD_BUSH: return new cBlockDeadBushHandler (a_BlockType); case E_BLOCK_DETECTOR_RAIL: return new cBlockRailHandler (a_BlockType); @@ -230,8 +236,11 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_INACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType); case E_BLOCK_IRON_DOOR: return new cBlockDoorHandler (a_BlockType); case E_BLOCK_IRON_ORE: return new cBlockOreHandler (a_BlockType); + case E_BLOCK_IRON_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType); case E_BLOCK_JACK_O_LANTERN: return new cBlockPumpkinHandler (a_BlockType); case E_BLOCK_JUKEBOX: return new cBlockEntityHandler (a_BlockType); + case E_BLOCK_JUNGLE_DOOR: return new cBlockDoorHandler (a_BlockType); + case E_BLOCK_JUNGLE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType); case E_BLOCK_JUNGLE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_LADDER: return new cBlockLadderHandler (a_BlockType); case E_BLOCK_LEVER: return new cBlockLeverHandler (a_BlockType); @@ -251,6 +260,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_NETHER_QUARTZ_ORE: return new cBlockOreHandler (a_BlockType); case E_BLOCK_NEW_LEAVES: return new cBlockLeavesHandler (a_BlockType); case E_BLOCK_NEW_LOG: return new cBlockSidewaysHandler (a_BlockType); + case E_BLOCK_NEW_STONE_SLAB: return new cBlockSlabHandler (a_BlockType); case E_BLOCK_NOTE_BLOCK: return new cBlockEntityHandler (a_BlockType); case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType); case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler; @@ -262,6 +272,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_QUARTZ_BLOCK: return new cBlockQuartzHandler (a_BlockType); case E_BLOCK_QUARTZ_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_RAIL: return new cBlockRailHandler (a_BlockType); + case E_BLOCK_RED_SANDSTONE_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_REDSTONE_LAMP_ON: return new cBlockRedstoneLampHandler (a_BlockType); case E_BLOCK_REDSTONE_ORE: return new cBlockOreHandler (a_BlockType); case E_BLOCK_REDSTONE_ORE_GLOWING: return new cBlockOreHandler (a_BlockType); @@ -277,6 +288,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_SAPLING: return new cBlockSaplingHandler (a_BlockType); case E_BLOCK_SIGN_POST: return new cBlockSignPostHandler (a_BlockType); case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType); + case E_BLOCK_SPRUCE_DOOR: return new cBlockDoorHandler (a_BlockType); case E_BLOCK_SPRUCE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_STAINED_GLASS: return new cBlockGlassHandler (a_BlockType); case E_BLOCK_STAINED_GLASS_PANE: return new cBlockGlassHandler (a_BlockType); -- cgit v1.2.3 From a9b4b60c80f4c23e58adb05622d4a1ff41277d57 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Wed, 10 Sep 2014 21:44:04 +0200 Subject: Added new blocks to the BlockInfo --- src/BlockID.h | 24 ++++++++--------- src/BlockInfo.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++ src/Blocks/BlockHandler.cpp | 1 + 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/BlockID.h b/src/BlockID.h index d6712a588..e7838da27 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -187,18 +187,18 @@ enum ENUM_BLOCK_ID E_BLOCK_BIG_FLOWER = 175, E_BLOCK_RED_SANDSTONE = 179, E_BLOCK_RED_SANDSTONE_STAIRS = 180, - E_BLOCK_NEW_STONE_SLAB = 181, - E_BLOCK_SPRUCE_FENCE_GATE = 182, - E_BLOCK_BIRCH_FENCE_GATE = 183, - E_BLOCK_JUNGLE_FENCE_GATE = 184, - E_BLOCK_DARK_OAK_FENCE_GATE = 185, - E_BLOCK_ACACIA_FENCE_GATE = 186, - E_BLOCK_SPRUCE_FENCE = 187, - E_BLOCK_BIRCH_FENCE = 188, - E_BLOCK_JUNGLE_FENCE = 189, - E_BLOCK_DARK_OAK_FENCE = 190, - E_BLOCK_ACACIA_FENCE = 191, - // I don't know which block has the ID 192, maybe there is no block but we have to wait for mcp + E_BLOCK_DOUBLE_NEW_STONE_SLAB= 181, + E_BLOCK_NEW_STONE_SLAB = 182, + E_BLOCK_SPRUCE_FENCE_GATE = 183, + E_BLOCK_BIRCH_FENCE_GATE = 184, + E_BLOCK_JUNGLE_FENCE_GATE = 185, + E_BLOCK_DARK_OAK_FENCE_GATE = 186, + E_BLOCK_ACACIA_FENCE_GATE = 187, + E_BLOCK_SPRUCE_FENCE = 188, + E_BLOCK_BIRCH_FENCE = 189, + E_BLOCK_JUNGLE_FENCE = 190, + E_BLOCK_DARK_OAK_FENCE = 191, + E_BLOCK_ACACIA_FENCE = 192, E_BLOCK_SPRUCE_DOOR = 193, E_BLOCK_BIRCH_DOOR = 194, E_BLOCK_JUNGLE_DOOR = 195, diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index 9ac66d35d..3586757b9 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -84,11 +84,15 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_LightValue = 9; a_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_LightValue = 9; a_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_LightValue = 7; + a_Info[E_BLOCK_SEA_LANTERN ].m_LightValue = 15; a_Info[E_BLOCK_STATIONARY_LAVA ].m_LightValue = 15; a_Info[E_BLOCK_TORCH ].m_LightValue = 14; // Spread blocks + a_Info[E_BLOCK_ACACIA_DOOR ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_ACACIA_FENCE ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_ACACIA_FENCE_GATE ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_AIR ].m_SpreadLightFalloff = 1; @@ -96,6 +100,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_BEACON ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_BED ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_BIG_FLOWER ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_BIRCH_DOOR ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_BIRCH_FENCE ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_BIRCH_FENCE_GATE ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_BROWN_MUSHROOM ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_BREWING_STAND ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_CACTUS ].m_SpreadLightFalloff = 1; @@ -109,6 +116,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_COBWEB ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_CROPS ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_DANDELION ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_DARK_OAK_DOOR ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_DARK_OAK_FENCE ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_DARK_OAK_FENCE_GATE ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_DAYLIGHT_SENSOR ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_DEAD_BUSH ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_DETECTOR_RAIL ].m_SpreadLightFalloff = 1; @@ -132,6 +142,10 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_INACTIVE_COMPARATOR ].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; + a_Info[E_BLOCK_JUNGLE_DOOR ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_JUNGLE_FENCE ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_JUNGLE_FENCE_GATE ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_LADDER ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_LEAVES ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_LEVER ].m_SpreadLightFalloff = 1; @@ -142,6 +156,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_NETHER_PORTAL ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_NETHER_WART ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_NEW_LEAVES ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_NEW_STONE_SLAB ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_PISTON ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_PISTON_EXTENSION ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_PISTON_MOVED_BLOCK ].m_SpreadLightFalloff = 1; @@ -158,6 +173,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_SAPLING ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_SNOW ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_SPRUCE_DOOR ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_SPRUCE_FENCE ].m_SpreadLightFalloff = 1; + 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_STICKY_PISTON ].m_SpreadLightFalloff = 1; @@ -186,6 +204,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) // Transparent blocks + a_Info[E_BLOCK_ACACIA_DOOR ].m_Transparent = true; + a_Info[E_BLOCK_ACACIA_FENCE ].m_Transparent = true; + a_Info[E_BLOCK_ACACIA_FENCE_GATE ].m_Transparent = true; a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_Transparent = true; a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_Transparent = true; a_Info[E_BLOCK_AIR ].m_Transparent = true; @@ -193,6 +214,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_BEACON ].m_Transparent = true; a_Info[E_BLOCK_BED ].m_Transparent = true; a_Info[E_BLOCK_BIG_FLOWER ].m_Transparent = true; + a_Info[E_BLOCK_BIRCH_DOOR ].m_Transparent = true; + a_Info[E_BLOCK_BIRCH_FENCE ].m_Transparent = true; + a_Info[E_BLOCK_BIRCH_FENCE_GATE ].m_Transparent = true; a_Info[E_BLOCK_BROWN_MUSHROOM ].m_Transparent = true; a_Info[E_BLOCK_BREWING_STAND ].m_Transparent = true; a_Info[E_BLOCK_CACTUS ].m_Transparent = true; @@ -206,6 +230,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_COBWEB ].m_Transparent = true; a_Info[E_BLOCK_CROPS ].m_Transparent = true; a_Info[E_BLOCK_DANDELION ].m_Transparent = true; + a_Info[E_BLOCK_DARK_OAK_DOOR ].m_Transparent = true; + a_Info[E_BLOCK_DARK_OAK_FENCE ].m_Transparent = true; + a_Info[E_BLOCK_DARK_OAK_FENCE_GATE ].m_Transparent = true; a_Info[E_BLOCK_DAYLIGHT_SENSOR ].m_Transparent = true; a_Info[E_BLOCK_DEAD_BUSH ].m_Transparent = true; a_Info[E_BLOCK_DETECTOR_RAIL ].m_Transparent = true; @@ -229,6 +256,10 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_Transparent = true; a_Info[E_BLOCK_IRON_BARS ].m_Transparent = true; a_Info[E_BLOCK_IRON_DOOR ].m_Transparent = true; + a_Info[E_BLOCK_IRON_TRAPDOOR ].m_Transparent = true; + a_Info[E_BLOCK_JUNGLE_DOOR ].m_Transparent = true; + a_Info[E_BLOCK_JUNGLE_FENCE ].m_Transparent = true; + a_Info[E_BLOCK_JUGNLE_FENCE_GATE ].m_Transparent = true; a_Info[E_BLOCK_LADDER ].m_Transparent = true; a_Info[E_BLOCK_LAVA ].m_Transparent = true; a_Info[E_BLOCK_LEAVES ].m_Transparent = true; @@ -241,6 +272,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_NETHER_PORTAL ].m_Transparent = true; a_Info[E_BLOCK_NETHER_WART ].m_Transparent = true; a_Info[E_BLOCK_NEW_LEAVES ].m_Transparent = true; + a_Info[E_BLOCK_NEW_STONE_SLAB ].m_Transparent = true; a_Info[E_BLOCK_PISTON ].m_Transparent = true; a_Info[E_BLOCK_PISTON_EXTENSION ].m_Transparent = true; a_Info[E_BLOCK_PISTON_MOVED_BLOCK ].m_Transparent = true; @@ -257,6 +289,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_SAPLING ].m_Transparent = true; a_Info[E_BLOCK_SIGN_POST ].m_Transparent = true; a_Info[E_BLOCK_SNOW ].m_Transparent = true; + a_Info[E_BLOCK_SPRUCE_DOOR ].m_Transparent = true; + a_Info[E_BLOCK_SPRUCE_FENCE ].m_Transparent = true; + a_Info[E_BLOCK_SPRUCE_FENCE_GATE ].m_Transparent = true; a_Info[E_BLOCK_STAINED_GLASS ].m_Transparent = true; a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_Transparent = true; a_Info[E_BLOCK_STATIONARY_LAVA ].m_Transparent = true; @@ -388,6 +423,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_DIAMOND_ORE ].m_IsSnowable = true; a_Info[E_BLOCK_DIRT ].m_IsSnowable = true; a_Info[E_BLOCK_DISPENSER ].m_IsSnowable = true; + a_Info[E_BLOCK_DOUBLE_NEW_STONE_SLAB].m_IsSnowable = true; a_Info[E_BLOCK_DOUBLE_STONE_SLAB ].m_IsSnowable = true; a_Info[E_BLOCK_DOUBLE_WOODEN_SLAB ].m_IsSnowable = true; a_Info[E_BLOCK_DROPPER ].m_IsSnowable = true; @@ -424,14 +460,17 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_NOTE_BLOCK ].m_IsSnowable = true; a_Info[E_BLOCK_OBSIDIAN ].m_IsSnowable = true; a_Info[E_BLOCK_PLANKS ].m_IsSnowable = true; + a_Info[E_BLOCK_PRISMARINE_BLOCK ].m_IsSnowable = true; a_Info[E_BLOCK_PUMPKIN ].m_IsSnowable = true; a_Info[E_BLOCK_QUARTZ_BLOCK ].m_IsSnowable = true; + a_Info[E_BLOCK_RED_SANDSTONE ].m_IsSnowable = true; a_Info[E_BLOCK_REDSTONE_LAMP_OFF ].m_IsSnowable = true; a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_IsSnowable = true; a_Info[E_BLOCK_REDSTONE_ORE ].m_IsSnowable = true; a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_IsSnowable = true; a_Info[E_BLOCK_SAND ].m_IsSnowable = true; a_Info[E_BLOCK_SANDSTONE ].m_IsSnowable = true; + a_Info[E_BLOCK_SEA_LANTERN ].m_IsSnowable = true; a_Info[E_BLOCK_SILVERFISH_EGG ].m_IsSnowable = true; a_Info[E_BLOCK_SNOW_BLOCK ].m_IsSnowable = true; a_Info[E_BLOCK_SOULSAND ].m_IsSnowable = true; @@ -537,8 +576,10 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_OBSIDIAN ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_PACKED_ICE ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_PLANKS ].m_FullyOccupiesVoxel = true; + a_Info[E_BLOCK_PRISMARINE_BLOCK ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_PUMPKIN ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_QUARTZ_BLOCK ].m_FullyOccupiesVoxel = true; + a_Info[E_BLOCK_RED_SANDSTONE ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_REDSTONE_LAMP_OFF ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_REDSTONE_ORE ].m_FullyOccupiesVoxel = true; @@ -732,12 +773,34 @@ 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"; // I hope it is named slime, it's definetly a new sound type though... + a_Info[E_BLOCK_IRON_TRAPDOOR ].m_PlaceSound = "dig.metal"; + a_Info[E_BLOCK_PRISMARINE_BLOCK ].m_PlaceSound = "dig.stone"; + a_Info[E_BLOCK_SEA_LANTERN ].m_PlaceSound = "dig.stone"; a_Info[E_BLOCK_HAY_BALE ].m_PlaceSound = "dig.grass"; a_Info[E_BLOCK_CARPET ].m_PlaceSound = "dig.cloth"; a_Info[E_BLOCK_HARDENED_CLAY ].m_PlaceSound = "dig.stone"; a_Info[E_BLOCK_BLOCK_OF_COAL ].m_PlaceSound = "dig.stone"; a_Info[E_BLOCK_PACKED_ICE ].m_PlaceSound = "dig.glass"; a_Info[E_BLOCK_BIG_FLOWER ].m_PlaceSound = "dig.grass"; + 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"; + a_Info[E_BLOCK_SPRUCE_FENCE_GATE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_BIRCH_FENCE_GATE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_JUNGLE_FENCE_GATE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_DARK_OAK_FENCE_GATE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_ACACIA_FENCE_GATE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_SPRUCE_FENCE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_BIRCH_FENCE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_JUNGLE_FENCE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_DARK_OAK_FENCE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_ACACIA_FENCE ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_SPRUCE_DOOR ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_BIRCH_DOOR ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_JUNGLE_DOOR ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_ACACIA_DOOR ].m_PlaceSound = "dig.wood"; + a_Info[E_BLOCK_DARK_OAK_DOOR ].m_PlaceSound = "dig.wood"; } diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 689874049..87be27a91 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -211,6 +211,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_DIAMOND_ORE: return new cBlockOreHandler (a_BlockType); case E_BLOCK_DIRT: return new cBlockDirtHandler (a_BlockType); case E_BLOCK_DISPENSER: return new cBlockDropSpenserHandler (a_BlockType); + case E_BLOCK_DOUBLE_NEW_STONE_SLAB: return new cBlockDropSpenserHandler (a_BlockType); case E_BLOCK_DOUBLE_STONE_SLAB: return new cBlockDoubleSlabHandler (a_BlockType); case E_BLOCK_DOUBLE_WOODEN_SLAB: return new cBlockDoubleSlabHandler (a_BlockType); case E_BLOCK_DROPPER: return new cBlockDropSpenserHandler (a_BlockType); -- cgit v1.2.3 From c0e86e736025a55222f62b8571969ea3a714c24e Mon Sep 17 00:00:00 2001 From: Masy98 Date: Wed, 10 Sep 2014 21:47:15 +0200 Subject: Fixed typo --- src/BlockInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index 3586757b9..adc112708 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -259,7 +259,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_IRON_TRAPDOOR ].m_Transparent = true; a_Info[E_BLOCK_JUNGLE_DOOR ].m_Transparent = true; a_Info[E_BLOCK_JUNGLE_FENCE ].m_Transparent = true; - a_Info[E_BLOCK_JUGNLE_FENCE_GATE ].m_Transparent = true; + a_Info[E_BLOCK_JUNGLE_FENCE_GATE ].m_Transparent = true; a_Info[E_BLOCK_LADDER ].m_Transparent = true; a_Info[E_BLOCK_LAVA ].m_Transparent = true; a_Info[E_BLOCK_LEAVES ].m_Transparent = true; -- cgit v1.2.3 From 214cc0f15d6ba7cafe6d3f1b35f631d6541cdf88 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Wed, 10 Sep 2014 21:50:46 +0200 Subject: Added stone slab in BlockSlab.h --- src/Blocks/BlockSlab.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h index 0ad30bb2b..4c46a39c5 100644 --- a/src/Blocks/BlockSlab.h +++ b/src/Blocks/BlockSlab.h @@ -96,7 +96,7 @@ public: /// Returns true if the specified blocktype is one of the slabs handled by this handler static bool IsAnySlabType(BLOCKTYPE a_BlockType) { - return ((a_BlockType == E_BLOCK_WOODEN_SLAB) || (a_BlockType == E_BLOCK_STONE_SLAB)); + return ((a_BlockType == E_BLOCK_WOODEN_SLAB) || (a_BlockType == E_BLOCK_STONE_SLAB) || (a_BlockType == E_BLOCK_NEW_STONE_SLAB)); } @@ -119,6 +119,7 @@ public: { case E_BLOCK_STONE_SLAB: return E_BLOCK_DOUBLE_STONE_SLAB; case E_BLOCK_WOODEN_SLAB: return E_BLOCK_DOUBLE_WOODEN_SLAB; + case E_BLOCK_NEW_STONE_SLAB: return E_BLOCK_DOUBLE_NEW_STONE_SLAB; } ASSERT(!"Unhandled slab type!"); return E_BLOCK_AIR; @@ -158,6 +159,7 @@ public: { case E_BLOCK_DOUBLE_STONE_SLAB: return E_BLOCK_STONE_SLAB; case E_BLOCK_DOUBLE_WOODEN_SLAB: return E_BLOCK_WOODEN_SLAB; + case E_BLOCK_DOUBLE_NEW_STONE_SLAB: return E_BLOCK_NEW_STONE_SLAB; } ASSERT(!"Unhandled double slab type!"); return a_BlockType; -- cgit v1.2.3 From e34767b265f3a86fff8d99206e7fa024fb7fdf54 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 11 Sep 2014 15:39:37 +0200 Subject: Fixed incorrect handlers --- src/Blocks/BlockHandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 87be27a91..a470e6b21 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -176,8 +176,8 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) switch (a_BlockType) { // Block handlers, alphabetically sorted: - case E_BLOCK_ACACIA_DOOR: return new cBlockFenceGateHandler (a_BlockType); - case E_BLOCK_ACACIA_FENCE_GATE: return new cBlockDoorHandler (a_BlockType); + case E_BLOCK_ACACIA_DOOR: return new cBlockDoorHandler (a_BlockType); + case E_BLOCK_ACACIA_FENCE_GATE: return new cBlockFenceGateHandler (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); @@ -211,7 +211,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_DIAMOND_ORE: return new cBlockOreHandler (a_BlockType); case E_BLOCK_DIRT: return new cBlockDirtHandler (a_BlockType); case E_BLOCK_DISPENSER: return new cBlockDropSpenserHandler (a_BlockType); - case E_BLOCK_DOUBLE_NEW_STONE_SLAB: return new cBlockDropSpenserHandler (a_BlockType); + case E_BLOCK_DOUBLE_NEW_STONE_SLAB: return new cBlockDoubleSlabHandler (a_BlockType); case E_BLOCK_DOUBLE_STONE_SLAB: return new cBlockDoubleSlabHandler (a_BlockType); case E_BLOCK_DOUBLE_WOODEN_SLAB: return new cBlockDoubleSlabHandler (a_BlockType); case E_BLOCK_DROPPER: return new cBlockDropSpenserHandler (a_BlockType); -- cgit v1.2.3 From 5f2e850b0f1650006a8b06578c18ec6bc03d9b37 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 11 Sep 2014 15:48:26 +0200 Subject: Added blocks to the fire simulator --- src/Simulator/FireSimulator.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Simulator/FireSimulator.cpp b/src/Simulator/FireSimulator.cpp index cdb5abde2..7ae84af7b 100644 --- a/src/Simulator/FireSimulator.cpp +++ b/src/Simulator/FireSimulator.cpp @@ -179,6 +179,17 @@ bool cFireSimulator::IsFuel(BLOCKTYPE a_BlockType) case E_BLOCK_WOOL: case E_BLOCK_BOOKCASE: case E_BLOCK_FENCE: + case E_BLOCK_SPRUCE_FENCE: + case E_BLOCK_BIRCH_FENCE: + case E_BLOCK_JUNGLE_FENCE: + case E_BLOCK_DARK_OAK_FENCE: + case E_BLOCK_ACACIA_FENCE: + case E_BLOCK_FENCE_GATE: + case E_BLOCK_SPRUCE_FENCE_GATE: + case E_BLOCK_BIRCH_FENCE_GATE: + case E_BLOCK_JUNGLE_FENCE_GATE: + case E_BLOCK_DARK_OAK_FENCE_GATE: + case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_TNT: case E_BLOCK_VINES: case E_BLOCK_HAY_BALE: -- cgit v1.2.3 From 8c3cd18cdd175ea1ca06916e557fdf42d6232d71 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 11 Sep 2014 15:57:36 +0200 Subject: Added 1.8 food to the food list --- src/BlockID.h | 2 +- src/Items/ItemFood.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/BlockID.h b/src/BlockID.h index e7838da27..623b40b13 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -394,7 +394,7 @@ enum ENUM_ITEM_ID E_ITEM_NAME_TAG = 421, E_ITEM_MINECART_WITH_COMMAND_BLOCK = 422, E_ITEM_RAW_MUTTON = 423, - E_ITEM_MUTTON = 424, + E_ITEM_COOKED_MUTTON = 424, E_ITEM_BANNER = 425, E_ITEM_SPRUCE_DOOR = 427, E_ITEM_BIRCH_DOOR = 428, diff --git a/src/Items/ItemFood.h b/src/Items/ItemFood.h index 9035344df..886c5e4a3 100644 --- a/src/Items/ItemFood.h +++ b/src/Items/ItemFood.h @@ -34,7 +34,9 @@ public: // Carrots handled in ItemSeeds case E_ITEM_COOKED_CHICKEN: return FoodInfo(6, 7.2); case E_ITEM_COOKED_FISH: return FoodInfo(5, 6); // TODO: Add other fish types + case E_ITEM_COOKED_MUTTON: return FoodInfo(6, 9.6); case E_ITEM_COOKED_PORKCHOP: return FoodInfo(8, 12.8); + case E_ITEM_COOKED_RABBIT: return FoodInfo(5, 6); case E_ITEM_COOKIE: return FoodInfo(2, 0.4); // Golden apple handled in ItemGoldenApple case E_ITEM_GOLDEN_CARROT: return FoodInfo(6, 14.4); @@ -43,16 +45,17 @@ public: case E_ITEM_POISONOUS_POTATO: return FoodInfo(2, 1.2); // Potatoes handled in ItemSeeds case E_ITEM_PUMPKIN_PIE: return FoodInfo(8, 4.8); + case E_ITEM_RABBIT_STEW: return FoodInfo(10, 12); case E_ITEM_RED_APPLE: return FoodInfo(4, 2.4); case E_ITEM_RAW_BEEF: return FoodInfo(3, 1.8); case E_ITEM_RAW_CHICKEN: return FoodInfo(2, 1.2); case E_ITEM_RAW_FISH: return FoodInfo(2, 1.2); case E_ITEM_RAW_MUTTON: return FoodInfo(2, 1.2); case E_ITEM_RAW_PORKCHOP: return FoodInfo(3, 1.8); + case E_ITEM_RAW_RABBIT: return FoodInfo(3, 1.8); case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8); case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2); case E_ITEM_STEAK: return FoodInfo(8, 12.8); - case E_ITEM_MUTTON: return FoodInfo(6, 9.6); } LOGWARNING("%s: Unknown food item (%d), returning zero nutrition", __FUNCTION__, m_ItemType); return FoodInfo(0, 0.f); -- cgit v1.2.3 From 741791ecfc784d5aa0c4e8de11a6f3e99d6cc39d Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 11 Sep 2014 16:07:54 +0200 Subject: Added barrier block --- src/BlockID.h | 1 + src/BlockInfo.cpp | 6 +++++- src/Blocks/BlockPiston.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/BlockID.h b/src/BlockID.h index 623b40b13..5f2ff15cc 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -176,6 +176,7 @@ enum ENUM_BLOCK_ID E_BLOCK_ACACIA_WOOD_STAIRS = 163, E_BLOCK_DARK_OAK_WOOD_STAIRS = 164, E_BLOCK_SLIME_BLOCK = 165, + E_BLOCK_BARRIER = 166, E_BLOCK_IRON_TRAPDOOR = 167, E_BLOCK_PRISMARINE_BLOCK = 168, E_BLOCK_SEA_LANTERN = 169, diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index adc112708..839f1e9f6 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -97,6 +97,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_AIR ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_ANVIL ].m_SpreadLightFalloff = 1; + a_Info[E_BLOCK_BARRIER ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_BEACON ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_BED ].m_SpreadLightFalloff = 1; a_Info[E_BLOCK_BIG_FLOWER ].m_SpreadLightFalloff = 1; @@ -211,6 +212,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_Transparent = true; a_Info[E_BLOCK_AIR ].m_Transparent = true; a_Info[E_BLOCK_ANVIL ].m_Transparent = true; + a_Info[E_BLOCK_BARRIER ].m_Transparent = true; a_Info[E_BLOCK_BEACON ].m_Transparent = true; a_Info[E_BLOCK_BED ].m_Transparent = true; a_Info[E_BLOCK_BIG_FLOWER ].m_Transparent = true; @@ -527,7 +529,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) // Blocks that fully occupy their voxel - used as a guide for torch placeable blocks, amongst other things: - a_Info[E_BLOCK_NEW_LOG ].m_FullyOccupiesVoxel = true; + a_Info[E_BLOCK_BARRIER ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_BEDROCK ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_BLOCK_OF_COAL ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_BLOCK_OF_REDSTONE ].m_FullyOccupiesVoxel = true; @@ -572,6 +574,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_NETHERRACK ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_NETHER_BRICK ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_NETHER_QUARTZ_ORE ].m_FullyOccupiesVoxel = true; + a_Info[E_BLOCK_NEW_LOG ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_NOTE_BLOCK ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_OBSIDIAN ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_PACKED_ICE ].m_FullyOccupiesVoxel = true; @@ -774,6 +777,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) 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"; // I hope it is named slime, it's definetly a new sound type though... + 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"; a_Info[E_BLOCK_SEA_LANTERN ].m_PlaceSound = "dig.stone"; diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h index 0bec603e3..f20e8af36 100644 --- a/src/Blocks/BlockPiston.h +++ b/src/Blocks/BlockPiston.h @@ -94,6 +94,7 @@ private: switch (a_BlockType) { case E_BLOCK_ANVIL: + case E_BLOCK_BARRIER: case E_BLOCK_BEACON: case E_BLOCK_BEDROCK: case E_BLOCK_BREWING_STAND: -- cgit v1.2.3 From b185e7f4e631779ac9b6087dd619ef9ce16b11b0 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 11 Sep 2014 16:11:03 +0200 Subject: Fixed mutton name in ItemHandler --- src/Items/ItemHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 67c945ce4..e9c0026a7 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -217,7 +217,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_GOLDEN_CARROT: case E_ITEM_MELON_SLICE: case E_ITEM_MUSHROOM_SOUP: - case E_ITEM_MUTTON: + case E_ITEM_COOKED_MUTTON: case E_ITEM_POISONOUS_POTATO: case E_ITEM_PUMPKIN_PIE: case E_ITEM_RED_APPLE: -- cgit v1.2.3 From a01994389dea9273916d983891815563c9433e4e Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 11 Sep 2014 16:24:16 +0200 Subject: Fixed mutton name in Sheep.cpp --- src/Items/ItemHandler.cpp | 12 ++++++++++-- src/Mobs/Sheep.cpp | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index e9c0026a7..df8bb6bfa 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -191,6 +191,11 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) return new cItemSeedsHandler(a_ItemType); } + case E_ITEM_ACACIA_DOOR: + case E_ITEM_BIRCH_DOOR: + case E_ITEM_DARK_OAK_DOOR: + case E_ITEM_JUNGLE_DOOR: + case E_ITEM_SPRUCE_DOOR: case E_ITEM_IRON_DOOR: case E_ITEM_WOODEN_DOOR: { @@ -212,20 +217,23 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_BREAD: case E_ITEM_COOKED_CHICKEN: case E_ITEM_COOKED_FISH: + case E_ITEM_COOKED_MUTTON: case E_ITEM_COOKED_PORKCHOP: + case E_ITEM_COOKED_RABBIT: case E_ITEM_COOKIE: case E_ITEM_GOLDEN_CARROT: case E_ITEM_MELON_SLICE: case E_ITEM_MUSHROOM_SOUP: - case E_ITEM_COOKED_MUTTON: case E_ITEM_POISONOUS_POTATO: case E_ITEM_PUMPKIN_PIE: - case E_ITEM_RED_APPLE: + case E_ITEM_RABBIT_STEW: case E_ITEM_RAW_BEEF: case E_ITEM_RAW_CHICKEN: case E_ITEM_RAW_FISH: case E_ITEM_RAW_MUTTON: case E_ITEM_RAW_PORKCHOP: + case E_ITEM_RAW_RABBIT: + case E_ITEM_RED_APPLE: case E_ITEM_ROTTEN_FLESH: case E_ITEM_SPIDER_EYE: case E_ITEM_STEAK: diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 1a82115d2..1122c9809 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -45,7 +45,7 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } - AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_MUTTON : E_ITEM_RAW_MUTTON); + AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_COOKED_MUTTON : E_ITEM_RAW_MUTTON); } -- cgit v1.2.3 From d4641576c0d4731fc771705f9642996aa92a3656 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 11 Sep 2014 16:33:52 +0200 Subject: Added new doors in ItemDoor.h --- src/Items/ItemDoor.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Items/ItemDoor.h b/src/Items/ItemDoor.h index c1b439024..402cef6c6 100644 --- a/src/Items/ItemDoor.h +++ b/src/Items/ItemDoor.h @@ -30,7 +30,21 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - a_BlockType = (m_ItemType == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR; + switch (m_ItemType) { + case E_ITEM_WOODEN_DOOR: a_BlockType = E_BLOCK_WOODEN_DOOR; break; + case E_ITEM_IRON_DOOR: a_BlockType = E_BLOCK_IRON_DOOR; break; + case E_ITEM_SPRUCE_DOOR: a_BlockType = E_BLOCK_SPRUCE_DOOR; break; + case E_ITEM_BIRCH_DOOR: a_BlockType = E_BLOCK_BIRCH_DOOR; break; + case E_ITEM_JUNGLE_DOOR: a_BlockType = E_BLOCK_JUNGLE_DOOR; break; + case E_ITEM_DARK_OAK_DOOR: a_BlockType = E_BLOCK_DARK_OAK_DOOR; break; + case E_ITEM_ACACIA_DOOR: a_BlockType = E_BLOCK_ACACIA_DOOR; break; + default: + { + ASSERT(!"Unhandled door type"); + return false; + } + } + cChunkInterface ChunkInterface(a_World->GetChunkMap()); bool Meta = BlockHandler(a_BlockType)->GetPlacementBlockTypeMeta( ChunkInterface, a_Player, -- cgit v1.2.3 From 3bd3ac2200392542b111d2bcd2951bd342edf721 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 11 Sep 2014 17:03:09 +0200 Subject: 1.8: Added ParticleEffect packet. --- src/Chunk.cpp | 4 +- src/Chunk.h | 2 +- src/ChunkMap.cpp | 4 +- src/ChunkMap.h | 2 +- src/ClientHandle.cpp | 4 +- src/ClientHandle.h | 2 +- src/Protocol/Protocol.h | 2 +- src/Protocol/Protocol125.cpp | 2 +- src/Protocol/Protocol125.h | 2 +- src/Protocol/Protocol15x.cpp | 4 +- src/Protocol/Protocol15x.h | 2 +- src/Protocol/Protocol17x.cpp | 4 +- src/Protocol/Protocol17x.h | 2 +- src/Protocol/Protocol18x.cpp | 100 +++++++++++++++++++++++++++++++----- src/Protocol/Protocol18x.h | 5 +- src/Protocol/ProtocolRecognizer.cpp | 4 +- src/Protocol/ProtocolRecognizer.h | 2 +- src/World.cpp | 4 +- src/World.h | 2 +- 19 files changed, 115 insertions(+), 38 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 99e48df95..79602e64e 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -3043,7 +3043,7 @@ void cChunk::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation -void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude) +void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude) { for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) { @@ -3051,7 +3051,7 @@ void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src { continue; } - (*itr)->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmmount); + (*itr)->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount); } // for itr - LoadedByClient[] } diff --git a/src/Chunk.h b/src/Chunk.h index f282694c2..e88e72bdc 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -326,7 +326,7 @@ public: void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL); void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL); - void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); + void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 9c105c5af..e03c9b86c 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -617,7 +617,7 @@ void cChunkMap::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animat -void cChunkMap::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude) +void cChunkMap::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude) { cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; @@ -629,7 +629,7 @@ void cChunkMap::BroadcastParticleEffect(const AString & a_ParticleName, float a_ return; } // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmmount, a_Exclude); + Chunk->BroadcastParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount, a_Exclude); } diff --git a/src/ChunkMap.h b/src/ChunkMap.h index 7354536d4..dcfd1e336 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -87,7 +87,7 @@ public: void BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL); void BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL); - void BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); + void BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); void BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index fa2c2124b..3b32b06b9 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2339,9 +2339,9 @@ void cClientHandle::SendMapInfo(int a_ID, unsigned int a_Scale) -void cClientHandle::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +void cClientHandle::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) { - m_Protocol->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmmount); + m_Protocol->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index eaa4e90fd..7c5597b8b 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -154,7 +154,7 @@ public: 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_ParticleAmmount); + 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 SendPlayerAbilities (void); void SendPlayerListItem (const cPlayer & a_Player, char a_Action); void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+) diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 902c72675..2b41b809c 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -93,7 +93,7 @@ public: virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0; virtual void SendPlayerAbilities (void) = 0; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0; - virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) = 0; + virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) = 0; virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) = 0; virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+) virtual void SendPlayerMoveLook (void) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 8c4534ff7..1d6049097 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -701,7 +701,7 @@ void cProtocol125::SendEntityAnimation(const cEntity & a_Entity, char a_Animatio -void cProtocol125::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +void cProtocol125::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) { // Not supported by this protocol version } diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 029845b8b..262e1818d 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -60,7 +60,7 @@ public: virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override; virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void 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) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message diff --git a/src/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp index 2b1f01b08..089296fdf 100644 --- a/src/Protocol/Protocol15x.cpp +++ b/src/Protocol/Protocol15x.cpp @@ -80,7 +80,7 @@ void cProtocol150::SendWindowOpen(const cWindow & a_Window) -void cProtocol150::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +void cProtocol150::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) { cCSLock Lock(m_CSPacket); WriteByte(PACKET_PARTICLE_EFFECT); @@ -92,7 +92,7 @@ void cProtocol150::SendParticleEffect(const AString & a_ParticleName, float a_Sr WriteFloat(a_OffsetY); WriteFloat(a_OffsetZ); WriteFloat(a_ParticleData); - WriteInt(a_ParticleAmmount); + WriteInt(a_ParticleAmount); Flush(); } diff --git a/src/Protocol/Protocol15x.h b/src/Protocol/Protocol15x.h index 0d171a67c..968d5ebcf 100644 --- a/src/Protocol/Protocol15x.h +++ b/src/Protocol/Protocol15x.h @@ -29,7 +29,7 @@ public: cProtocol150(cClientHandle * a_Client); virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void 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) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index b4f96bd88..d83e86ece 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -847,7 +847,7 @@ void cProtocol172::SendEntityAnimation(const cEntity & a_Entity, char a_Animatio -void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +void cProtocol172::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) { ASSERT(m_State == 3); // In game mode? @@ -860,7 +860,7 @@ void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_Sr Pkt.WriteFloat(a_OffsetY); Pkt.WriteFloat(a_OffsetZ); Pkt.WriteFloat(a_ParticleData); - Pkt.WriteInt(a_ParticleAmmount); + Pkt.WriteInt(a_ParticleAmount); } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 6bb5873d3..60088a1b8 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -98,7 +98,7 @@ public: virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void 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) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index c7c6402d9..2ea83351e 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -779,7 +779,7 @@ void cProtocol180::SendPickupSpawn(const cPickup & a_Pickup) { ASSERT(m_State == 3); // In game mode? - /*{ + { cPacketizer Pkt(*this, 0x0e); // Spawn Object packet Pkt.WriteVarInt(a_Pickup.GetUniqueID()); Pkt.WriteByte(2); // Type = Pickup @@ -797,7 +797,7 @@ void cProtocol180::SendPickupSpawn(const cPickup & a_Pickup) Pkt.WriteByte((0x05 << 5) | 10); // Slot type + index 10 Pkt.WriteItem(a_Pickup.GetItem()); Pkt.WriteByte(0x7f); // End of metadata - }*/ + } } @@ -846,12 +846,14 @@ void cProtocol180::SendEntityAnimation(const cEntity & a_Entity, char a_Animatio -void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +void cProtocol180::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) { ASSERT(m_State == 3); // In game mode? - - /*cPacketizer Pkt(*this, 0x2A); - Pkt.WriteString(a_ParticleName); + int ParticleID = GetParticleID(a_ParticleName); + + cPacketizer Pkt(*this, 0x2A); + Pkt.WriteInt(ParticleID); + Pkt.WriteBool(false); Pkt.WriteFloat(a_SrcX); Pkt.WriteFloat(a_SrcY); Pkt.WriteFloat(a_SrcZ); @@ -859,7 +861,7 @@ void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_Sr Pkt.WriteFloat(a_OffsetY); Pkt.WriteFloat(a_OffsetZ); Pkt.WriteFloat(a_ParticleData); - Pkt.WriteInt(a_ParticleAmmount);*/ + Pkt.WriteInt(a_ParticleAmount); } @@ -1230,7 +1232,7 @@ void cProtocol180::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, { ASSERT(m_State == 3); // In game mode? - /*cPacketizer Pkt(*this, 0xe); // Spawn Object packet + cPacketizer Pkt(*this, 0xe); // Spawn Object packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByte(a_ObjectType); Pkt.WriteFPInt(a_Entity.GetPosX()); @@ -1244,7 +1246,7 @@ void cProtocol180::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, Pkt.WriteShort((short)(a_Entity.GetSpeedX() * 400)); Pkt.WriteShort((short)(a_Entity.GetSpeedY() * 400)); Pkt.WriteShort((short)(a_Entity.GetSpeedZ() * 400)); - }*/ + } } @@ -1570,6 +1572,71 @@ bool cProtocol180::CompressPacket(const AString & a_Packet, AString & a_Compress +int cProtocol180::GetParticleID(const AString & a_ParticleName) +{ + static bool IsInitialized = false; + static std::map ParticleMap; + if (!IsInitialized) + { + // Initialize the ParticleMap: + ParticleMap["explode"] = 0; + ParticleMap["largeexplode"] = 1; + ParticleMap["hugeexplosion"] = 2; + ParticleMap["fireworksspark"] = 3; + ParticleMap["bubble"] = 4; + ParticleMap["splash"] = 5; + ParticleMap["wake"] = 6; + ParticleMap["suspended"] = 7; + ParticleMap["depthsuspend"] = 8; + ParticleMap["crit"] = 9; + ParticleMap["magiccrit"] = 10; + ParticleMap["smoke"] = 11; + ParticleMap["largesmoke"] = 12; + ParticleMap["spell"] = 13; + ParticleMap["instantspell"] = 14; + ParticleMap["mobspell"] = 15; + ParticleMap["mobspellambient"] = 16; + ParticleMap["witchmagic"] = 17; + ParticleMap["dripwater"] = 18; + ParticleMap["driplava"] = 19; + ParticleMap["angryvillager"] = 20; + ParticleMap["happyVillager"] = 21; + ParticleMap["townaura"] = 22; + ParticleMap["note"] = 23; + ParticleMap["portal"] = 24; + ParticleMap["enchantmenttable"] = 25; + ParticleMap["flame"] = 26; + ParticleMap["lava"] = 27; + ParticleMap["footstep"] = 28; + ParticleMap["cloud"] = 29; + ParticleMap["reddust"] = 30; + ParticleMap["snowballpoof"] = 31; + ParticleMap["snowshovel"] = 32; + ParticleMap["slime"] = 33; + ParticleMap["heart"] = 34; + ParticleMap["barrier"] = 35; + ParticleMap["iconcrack"] = 36; + ParticleMap["blockcrack"] = 37; + ParticleMap["blockdust"] = 38; + ParticleMap["droplet"] = 39; + ParticleMap["take"] = 40; + ParticleMap["mobappearance"] = 41; + } + + AString ParticleName = StrToLower(a_ParticleName); + if (ParticleMap.find(ParticleName) == ParticleMap.end()) + { + LOGWARNING("Unknown particle: %s", a_ParticleName.c_str()); + return 0; + } + + return ParticleMap[ParticleName]; +} + + + + + void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) { // Write the incoming data into the comm log file: @@ -2685,13 +2752,20 @@ void cProtocol180::cPacketizer::WriteUUID(const AString & a_UUID) { AString UUID_1 = a_UUID.substr(0, a_UUID.length() / 2); AString UUID_2 = a_UUID.substr(a_UUID.length() / 2); - - UInt64 Value_1, Value_2; + + Int64 Value_1, Value_2; sscanf(UUID_1.c_str(), "%llx", &Value_1); sscanf(UUID_2.c_str(), "%llx", &Value_2); - WriteInt64((Int64)Value_1); - WriteInt64((Int64)Value_2); + AString SValue_1, SValue_2; + Printf(SValue_1, "%lld", Value_1); + Printf(SValue_2, "%lld", Value_2); + + StringToInteger(SValue_1.c_str(), Value_1); + StringToInteger(SValue_2.c_str(), Value_2); + + WriteInt64(Value_1); + WriteInt64(Value_2); } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 33e298e48..2b3063556 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -96,7 +96,7 @@ public: virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void 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) override; virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; @@ -138,6 +138,9 @@ public: If compression fails, the function returns false. */ static bool CompressPacket(const AString & a_Packet, AString & a_Compressed); + /** The 1.8 protocol use a particle id instead of a string. This function converts the name to the id. If the name is incorrect, it returns 0. */ + static int GetParticleID(const AString & a_ParticleName); + protected: /** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */ diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 56e5b43f3..cf63583db 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -441,10 +441,10 @@ void cProtocolRecognizer::SendMapInfo(int a_ID, unsigned int a_Scale) -void cProtocolRecognizer::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) +void cProtocolRecognizer::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) { ASSERT(m_Protocol != NULL); - m_Protocol->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmmount); + m_Protocol->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 4d2bceb68..f73b0b92a 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -96,7 +96,7 @@ public: virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override; virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override; + virtual void 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) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendPlayerAbilities (void) override; diff --git a/src/World.cpp b/src/World.cpp index 0e0846943..351dded24 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2138,9 +2138,9 @@ void cWorld::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation -void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude) +void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude) { - m_ChunkMap->BroadcastParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmmount, a_Exclude); + m_ChunkMap->BroadcastParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount, a_Exclude); } diff --git a/src/World.h b/src/World.h index fae784c20..2c363c0af 100644 --- a/src/World.h +++ b/src/World.h @@ -236,7 +236,7 @@ public: void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL); void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override; // tolua_export - void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export + void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = NULL); // tolua_export void BroadcastPlayerListItem (const cPlayer & a_Player, char a_Action, const cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); -- cgit v1.2.3 From 0b044e1c83a62c266afaf0852ccbd5e7b01cec5e Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 11 Sep 2014 17:48:21 +0100 Subject: Possibly decoupled IncrementalRedstoneSimulator from the rest of the server THis wil hopefully allow for unit testing --- src/BlockEntities/CommandBlockEntity.h | 7 +- src/BlockEntities/RedstonePoweredEntity.h | 2 +- src/Blocks/GetHandlerCompileTimeTemplate.h | 54 + src/Chunk.cpp | 6 +- src/Chunk.h | 18 +- src/Simulator/CMakeLists.txt | 1 - src/Simulator/FireSimulator.h | 2 +- src/Simulator/FluidSimulator.h | 7 +- src/Simulator/IncrementalRedstoneSimulator.cpp | 2231 +----------------------- src/Simulator/IncrementalRedstoneSimulator.h | 28 +- src/Simulator/IncrementalRedstoneSimulator.inc | 2208 +++++++++++++++++++++++ src/Simulator/NoopRedstoneSimulator.h | 4 +- src/Simulator/RedstoneSimulator.cpp | 19 - src/Simulator/RedstoneSimulator.h | 11 +- src/Simulator/SandSimulator.h | 9 +- src/Simulator/Simulator.cpp | 50 +- src/Simulator/Simulator.h | 17 +- src/Simulator/Simulator.inc | 49 + src/Simulator/SimulatorManager.cpp | 2 +- src/Simulator/SimulatorManager.h | 4 +- src/World.cpp | 6 +- src/World.h | 7 +- 22 files changed, 2403 insertions(+), 2339 deletions(-) create mode 100644 src/Blocks/GetHandlerCompileTimeTemplate.h create mode 100644 src/Simulator/IncrementalRedstoneSimulator.inc delete mode 100644 src/Simulator/RedstoneSimulator.cpp create mode 100644 src/Simulator/Simulator.inc diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h index d02bf7d7b..22cd44322 100644 --- a/src/BlockEntities/CommandBlockEntity.h +++ b/src/BlockEntities/CommandBlockEntity.h @@ -10,7 +10,7 @@ #pragma once #include "BlockEntity.h" - +#include "RedstonePoweredEntity.h" @@ -27,7 +27,8 @@ namespace Json // tolua_begin class cCommandBlockEntity : - public cBlockEntity + public cBlockEntity, + public cRedstonePoweredEntity { typedef cBlockEntity super; @@ -52,7 +53,7 @@ public: // tolua_begin /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate - void SetRedstonePower(bool a_IsPowered); + virtual void SetRedstonePower(bool a_IsPowered) override; /// Sets the command block to execute a command in the next tick void Activate(void); diff --git a/src/BlockEntities/RedstonePoweredEntity.h b/src/BlockEntities/RedstonePoweredEntity.h index f11df4fc4..eac4e35d4 100644 --- a/src/BlockEntities/RedstonePoweredEntity.h +++ b/src/BlockEntities/RedstonePoweredEntity.h @@ -6,7 +6,7 @@ class cRedstonePoweredEntity { public: - virtual ~cRedstonePoweredEntity() {}; + virtual ~cRedstonePoweredEntity() {} /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate virtual void SetRedstonePower(bool a_IsPowered) = 0; diff --git a/src/Blocks/GetHandlerCompileTimeTemplate.h b/src/Blocks/GetHandlerCompileTimeTemplate.h new file mode 100644 index 000000000..658497bf2 --- /dev/null +++ b/src/Blocks/GetHandlerCompileTimeTemplate.h @@ -0,0 +1,54 @@ + +#pragma once + +class cBlockTorchHandler; +class cBlockLeverHandler; +class cBlockButtonHandler; +class cBlockTripwireHookHandler; +class cBlockDoorHandler; +class cBlockPistonHandler; + +template +class GetHandlerCompileTime; + +template<> +class GetHandlerCompileTime +{ +public: + typedef cBlockTorchHandler type; +}; + +template<> +class GetHandlerCompileTime +{ +public: + typedef cBlockLeverHandler type; +}; + +template<> +class GetHandlerCompileTime +{ +public: + typedef cBlockButtonHandler type; +}; + +template<> +class GetHandlerCompileTime +{ +public: + typedef cBlockTripwireHookHandler type; +}; + +template<> +class GetHandlerCompileTime +{ +public: + typedef cBlockDoorHandler type; +}; + +template<> +class GetHandlerCompileTime +{ +public: + typedef cBlockPistonHandler type; +}; diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 99e48df95..46520eb56 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1366,9 +1366,9 @@ void cChunk::CreateBlockEntities(void) void cChunk::WakeUpSimulators(void) { - cSimulator * WaterSimulator = m_World->GetWaterSimulator(); - cSimulator * LavaSimulator = m_World->GetLavaSimulator(); - cSimulator * RedstoneSimulator = m_World->GetRedstoneSimulator(); + cSimulator * WaterSimulator = m_World->GetWaterSimulator(); + cSimulator * LavaSimulator = m_World->GetLavaSimulator(); + cSimulator * RedstoneSimulator = m_World->GetRedstoneSimulator(); int BaseX = m_PosX * cChunkDef::Width; int BaseZ = m_PosZ * cChunkDef::Width; for (int x = 0; x < Width; x++) diff --git a/src/Chunk.h b/src/Chunk.h index f282694c2..9a0e96513 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -9,6 +9,8 @@ #include "Simulator/SandSimulator.h" #include "Simulator/IncrementalRedstoneSimulator.h" +#include "Blocks/GetHandlerCompileTimeTemplate.h" + @@ -416,10 +418,10 @@ public: cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return &m_RedstoneSimulatorData; } cRedstoneSimulatorChunkData * GetRedstoneSimulatorQueuedData(void) { return &m_RedstoneSimulatorQueuedData; } - cIncrementalRedstoneSimulator::PoweredBlocksList * GetRedstoneSimulatorPoweredBlocksList(void) { return &m_RedstoneSimulatorPoweredBlocksList; } - cIncrementalRedstoneSimulator::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; } - cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; } - cIncrementalRedstoneSimulator::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; } + cIncrementalRedstoneSimulator::PoweredBlocksList * GetRedstoneSimulatorPoweredBlocksList(void) { return &m_RedstoneSimulatorPoweredBlocksList; } + cIncrementalRedstoneSimulator::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; } + cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; } + cIncrementalRedstoneSimulator::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; } bool IsRedstoneDirty(void) const { return m_IsRedstoneDirty; } void SetIsRedstoneDirty(bool a_Flag) { m_IsRedstoneDirty = a_Flag; } @@ -506,10 +508,10 @@ private: cRedstoneSimulatorChunkData m_RedstoneSimulatorData; cRedstoneSimulatorChunkData m_RedstoneSimulatorQueuedData; - cIncrementalRedstoneSimulator::PoweredBlocksList m_RedstoneSimulatorPoweredBlocksList; - cIncrementalRedstoneSimulator::LinkedBlocksList m_RedstoneSimulatorLinkedBlocksList; - cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList m_RedstoneSimulatorSimulatedPlayerToggleableList; - cIncrementalRedstoneSimulator::RepeatersDelayList m_RedstoneSimulatorRepeatersDelayList; + cIncrementalRedstoneSimulator::PoweredBlocksList m_RedstoneSimulatorPoweredBlocksList; + cIncrementalRedstoneSimulator::LinkedBlocksList m_RedstoneSimulatorLinkedBlocksList; + cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList m_RedstoneSimulatorSimulatedPlayerToggleableList; + cIncrementalRedstoneSimulator::RepeatersDelayList m_RedstoneSimulatorRepeatersDelayList; /** Indicates if simulate-once blocks should be updated by the redstone simulator */ bool m_IsRedstoneDirty; diff --git a/src/Simulator/CMakeLists.txt b/src/Simulator/CMakeLists.txt index 521b145b6..5aa406717 100644 --- a/src/Simulator/CMakeLists.txt +++ b/src/Simulator/CMakeLists.txt @@ -10,7 +10,6 @@ SET (SRCS FloodyFluidSimulator.cpp FluidSimulator.cpp IncrementalRedstoneSimulator.cpp - RedstoneSimulator.cpp SandSimulator.cpp Simulator.cpp SimulatorManager.cpp diff --git a/src/Simulator/FireSimulator.h b/src/Simulator/FireSimulator.h index 9ccc3ef4f..f76dbe342 100644 --- a/src/Simulator/FireSimulator.h +++ b/src/Simulator/FireSimulator.h @@ -16,7 +16,7 @@ it progresses to the next step (blockmeta++). This value is updated if a neighbo The simulator reads its parameters from the ini file given to the constructor. */ class cFireSimulator : - public cSimulator + public cSimulator { public: cFireSimulator(cWorld & a_World, cIniFile & a_IniFile); diff --git a/src/Simulator/FluidSimulator.h b/src/Simulator/FluidSimulator.h index 672b740a2..0877a7bf1 100644 --- a/src/Simulator/FluidSimulator.h +++ b/src/Simulator/FluidSimulator.h @@ -4,7 +4,8 @@ #include "Simulator.h" - +class cChunk; +class cWorld; enum Direction @@ -36,9 +37,9 @@ public: class cFluidSimulator : - public cSimulator + public cSimulator { - typedef cSimulator super; + typedef cSimulator super; public: cFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid); diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 7b3a2c2fa..515d72457 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -1,2216 +1,23 @@ -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "IncrementalRedstoneSimulator.h" -#include "BoundingBox.h" -#include "../BlockEntities/RedstonePoweredEntity.h" -#include "../BlockEntities/ChestEntity.h" -#include "../BlockEntities/CommandBlockEntity.h" -#include "../Entities/Pickup.h" -#include "../Blocks/BlockTorch.h" -#include "../Blocks/BlockDoor.h" -#include "../Blocks/BlockButton.h" -#include "../Blocks/BlockLever.h" -#include "../Blocks/BlockPiston.h" -#include "../Blocks/BlockTripwireHook.h" - - - - - -cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(cWorld & a_World) : - super(a_World), - m_RedstoneSimulatorChunkData(), - m_PoweredBlocks(), - m_LinkedPoweredBlocks(), - m_SimulatedPlayerToggleableBlocks(), - m_RepeatersDelayList(), - m_Chunk() -{ -} - - - - - -cIncrementalRedstoneSimulator::~cIncrementalRedstoneSimulator() -{ -} - - - - - -void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk, cChunk * a_OtherChunk) -{ - if ((a_Chunk == NULL) || !a_Chunk->IsValid()) - { - return; - } - else if ((a_BlockY < 0) || (a_BlockY > cChunkDef::Height)) - { - return; - } - - // We may be called with coordinates in a chunk that is not the first chunk parameter - // In that case, the actual chunk (which the coordinates are in), will be passed as the second parameter - // Use that Chunk pointer to get a relative position - - int RelX = 0; - int RelZ = 0; - BLOCKTYPE Block; - NIBBLETYPE Meta; - - if (a_OtherChunk != NULL) - { - RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width; - RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width; - a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); - - // If a_OtherChunk is passed (not NULL), it is the chunk that had a block change, and a_Chunk will be the neighbouring chunk of that block - // Because said neighbouring chunk does not know of this change but still needs to update its redstone, we set it to dirty - a_Chunk->SetIsRedstoneDirty(true); - } - else - { - RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; - RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; - a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); - } - - // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid - // Checking only when a block is changed, as opposed to every tick, also improves performance - - PoweredBlocksList * PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); - for (PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end();) - { - if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) - { - ++itr; - continue; - } - - if (!IsPotentialSource(Block)) - { - LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = PoweredBlocks->erase(itr); - continue; - } - else if ( - // Changeable sources - ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) || - ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) || - ((Block == E_BLOCK_DETECTOR_RAIL) && ((Meta & 0x08) == 0)) || - (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) || - ((Block == E_BLOCK_TRIPWIRE_HOOK) && ((Meta & 0x08) == 0)) - ) - { - LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = PoweredBlocks->erase(itr); - continue; - } - ++itr; - } - - LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); - // We loop through all values (insteading of breaking out at the first) to make sure everything is gone, as there can be multiple SourceBlock entries for one AddBlock coordinate - for (LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end();) - { - if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) - { - if (!IsPotentialSource(Block)) - { - LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = LinkedPoweredBlocks->erase(itr); - continue; - } - else if ( - // Things that can send power through a block but which depends on meta - ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) || - ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) || - (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) - ) - { - LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = LinkedPoweredBlocks->erase(itr); - continue; - } - } - else if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) - { - if (!IsViableMiddleBlock(Block)) - { - LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = LinkedPoweredBlocks->erase(itr); - continue; - } - } - ++itr; - } - - SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); - for (SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks->begin(); itr != SimulatedPlayerToggleableBlocks->end(); ++itr) - { - if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ))) - { - continue; - } - - if (!IsAllowedBlock(Block)) - { - LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z); - SimulatedPlayerToggleableBlocks->erase(itr); - break; - } - } - - RepeatersDelayList * RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); - for (RepeatersDelayList::iterator itr = RepeatersDelayList->begin(); itr != RepeatersDelayList->end(); ++itr) - { - if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ))) - { - continue; - } - - if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) - { - RepeatersDelayList->erase(itr); - break; - } - } - - if (a_OtherChunk != NULL) - { - // DO NOT touch our chunk's data structure if we are being called with coordinates from another chunk - this one caused me massive grief :P - return; - } - - cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); - for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr) - { - if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block - { - if (!IsAllowedBlock(Block)) - { - itr->DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list - } - else - { - itr->DataTwo = false; - itr->Data = Block; // Update block information - } - return; - } - } - - if (!IsAllowedBlock(Block)) - { - return; - } - - for (cRedstoneSimulatorChunkData::iterator itr = a_Chunk->GetRedstoneSimulatorQueuedData()->begin(); itr != a_Chunk->GetRedstoneSimulatorQueuedData()->end(); ++itr) - { - if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) - { - // Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data - return; - } - } - a_Chunk->GetRedstoneSimulatorQueuedData()->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); -} - - - - - -void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) -{ - m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); - if (m_RedstoneSimulatorChunkData->empty() && a_Chunk->GetRedstoneSimulatorQueuedData()->empty()) - { - return; - } - - m_RedstoneSimulatorChunkData->insert(m_RedstoneSimulatorChunkData->end(), a_Chunk->GetRedstoneSimulatorQueuedData()->begin(), a_Chunk->GetRedstoneSimulatorQueuedData()->end()); - a_Chunk->GetRedstoneSimulatorQueuedData()->clear(); - - m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); - m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); - m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); - m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); - m_Chunk = a_Chunk; - bool ShouldUpdateSimulateOnceBlocks = false; - - if (a_Chunk->IsRedstoneDirty()) - { - // Simulate the majority of devices only if something (blockwise or power-wise) has changed - // Make sure to allow the chunk to resimulate after the initial run if there was a power change (ShouldUpdateSimulateOnceBlocks helps to do this) - a_Chunk->SetIsRedstoneDirty(false); - ShouldUpdateSimulateOnceBlocks = true; - } - - HandleRedstoneRepeaterDelays(); - - for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();) - { - if (dataitr->DataTwo) - { - dataitr = m_RedstoneSimulatorChunkData->erase(dataitr); - continue; - } - - switch (dataitr->Data) - { - case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->x, dataitr->y, dataitr->z); break; - - case E_BLOCK_WOODEN_PRESSURE_PLATE: - case E_BLOCK_STONE_PRESSURE_PLATE: - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - { - HandlePressurePlate(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - default: break; - } - - if (ShouldUpdateSimulateOnceBlocks) - { - switch (dataitr->Data) - { - case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break; - - case E_BLOCK_ACTIVATOR_RAIL: - case E_BLOCK_DETECTOR_RAIL: - case E_BLOCK_POWERED_RAIL: - { - HandleRail(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - case E_BLOCK_WOODEN_DOOR: - case E_BLOCK_IRON_DOOR: - { - HandleDoor(dataitr->x, dataitr->y, dataitr->z); - break; - } - case E_BLOCK_REDSTONE_LAMP_OFF: - case E_BLOCK_REDSTONE_LAMP_ON: - { - HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - { - HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z); - break; - } - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: - { - HandlePiston(dataitr->x, dataitr->y, dataitr->z); - break; - } - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_REDSTONE_REPEATER_ON: - { - HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - case E_BLOCK_REDSTONE_TORCH_OFF: - case E_BLOCK_REDSTONE_TORCH_ON: - { - HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_WOODEN_BUTTON: - { - HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z); - break; - } - default: break; - } - } - ++dataitr; - } -} - - - - -void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) -{ - if (AreCoordsOnChunkBoundary(a_BlockX, a_BlockY, a_BlockZ)) - { - // On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk) - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); - - // Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position - // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordinates are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 2, a_BlockZ), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 2, a_BlockZ), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 2), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 2), a_Chunk); - - return; - } - - // Not on boundary, just alert this chunk for speed - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); -} - - - - - -void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) -{ - static const struct // Define which directions the torch can power - { - int x, y, z; - } gCrossCoords[] = - { - { 1, 0, 0}, - {-1, 0, 0}, - { 0, 0, 1}, - { 0, 0, -1}, - { 0, 1, 0}, - } ; - - if (a_MyState == E_BLOCK_REDSTONE_TORCH_ON) - { - // Check if the block the torch is on is powered - int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ; - AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on - - cChunk * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z); - if ((Neighbour == NULL) || !Neighbour->IsValid()) - { - return; - } - - if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour)) - { - // There was a match, torch goes off - m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_TORCH_OFF, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); - return; - } - - // Torch still on, make all 4(X, Z) + 1(Y) sides powered - for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) - { - BLOCKTYPE Type = 0; - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, Type)) - { - continue; - } - if (i + 1 < ARRAYCOUNT(gCrossCoords)) // Sides of torch, not top (top is last) - { - if ( - IsMechanism(Type) && // Is it a mechanism? Not block/other torch etc. - (!Vector3i(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z).Equals(Vector3i(X, Y, Z))) // CAN'T power block is that it is on - ) - { - SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - } - } - else - { - // Top side, power whatever is there, including blocks - SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - // Power all blocks surrounding block above torch - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YP); - } - } - - if (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) != 0x5) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath - { - BLOCKTYPE Type = m_Chunk->GetBlock(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ); - - if (IsMechanism(Type)) // Still can't make a normal block powered though! - { - SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - } - } - } - else - { - // Check if the block the torch is on is powered - int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ; - AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on - - cChunk * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z); - if ((Neighbour == NULL) || !Neighbour->IsValid()) - { - return; - } - - // See if off state torch can be turned on again - if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour)) - { - return; // Something matches, torch still powered - } - - // Block torch on not powered, can be turned on again! - m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_TORCH_ON, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); // Set self as powered -} - - - - - -void cIncrementalRedstoneSimulator::HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - if (IsLeverOn(Meta)) - { - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - - eBlockFace Dir = cBlockLeverHandler::BlockMetaDataToBlockFace(Meta); - - Dir = ReverseBlockFace(Dir); - - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir); - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - NIBBLETYPE MetaData = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - - if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) - { - if ((MetaData & 0x4) == 0) - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData | 0x4); - m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); - } - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); - } - } - else - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) - { - if ((MetaData & 0x4) != 0) - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData & ~0x04); - m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); - } - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - if (IsButtonOn(Meta)) - { - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - - eBlockFace Dir = cBlockButtonHandler::BlockMetaDataToBlockFace(Meta); - Dir = ReverseBlockFace(Dir); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir); - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - static const struct // Define which directions the wire can receive power from - { - int x, y, z; - } gCrossCoords[] = - { - { 1, 0, 0}, /* Wires on same level start */ - {-1, 0, 0}, - { 0, 0, 1}, - { 0, 0, -1}, /* Wires on same level stop */ - { 1, 1, 0}, /* Wires one higher, surrounding self start */ - {-1, 1, 0}, - { 0, 1, 1}, - { 0, 1, -1}, /* Wires one higher, surrounding self stop */ - { 1, -1, 0}, /* Wires one lower, surrounding self start */ - {-1, -1, 0}, - { 0, -1, 1}, - { 0, -1, -1}, /* Wires one lower, surrounding self stop */ - } ; - - static const struct // Define which directions the wire will check for repeater prescence - { - int x, y, z; - } gSideCoords[] = - { - { 1, 0, 0 }, - {-1, 0, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, - { 0, 1, 0 }, - }; - - // Check to see if directly beside a power source - unsigned char MyPower; - if (!IsWirePowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower)) - { - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0); - m_World.WakeUpSimulators(BlockX, a_RelBlockY, BlockZ); - return; - } - - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - - if (MyPower < 1) - { - return; - } - - MyPower--; - - for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power - { - if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above... - { - BLOCKTYPE Type = 0; - if (a_RelBlockY + 1 >= cChunkDef::Height) - { - continue; - } - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, Type)) - { - continue; - } - if (cBlockInfo::IsSolid(Type)) // If there is something solid above us (wire cut off)... - { - continue; // We don't receive power from that wire - } - } - else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us - { - BLOCKTYPE Type = 0; - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY, a_RelBlockZ + gCrossCoords[i].z, Type)) - { - continue; - } - if (cBlockInfo::IsSolid(Type)) - { - continue; - } - } - - BLOCKTYPE Type = 0; - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, Type)) - { - continue; - } - if (Type == E_BLOCK_REDSTONE_WIRE) - { - SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - } - } - - for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them - { - BLOCKTYPE Type = 0; - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, Type)) - { - continue; - } - if (Type == E_BLOCK_REDSTONE_REPEATER_OFF) - { - SetBlockPowered(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - } - } - - // Wire still powered, power blocks beneath - SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, MyPower); - - switch (GetWireDirection(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - case REDSTONE_NONE: - { - SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower); - break; - } - case REDSTONE_X_POS: - { - SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower); - break; - } - case REDSTONE_X_NEG: - { - SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower); - break; - } - case REDSTONE_Z_POS: - { - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower); - break; - } - case REDSTONE_Z_NEG: - { - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower); - break; - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) -{ - /* Repeater Orientation Mini Guide: - =================================== - - | - | Z Axis - V - - X Axis ----> - - Repeater directions, values from a cWorld::GetBlockMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) lookup: - - East (Right) (X+): 0x1 - West (Left) (X-): 0x3 - North (Up) (Z-): 0x2 - South (Down) (Z+): 0x0 - // TODO: Add E_META_XXX enum entries for all meta values and update project with them - - Sun rises from East (X+) - - */ - - // Create a variable holding my meta to avoid multiple lookups. - NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON); - - if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta)) // If we're locked, change nothing. Otherwise: - { - bool IsSelfPowered = IsRepeaterPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta); - if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked. - { - QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true); - } - else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked. - { - QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false); - } - } -} - -void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays() -{ - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();) - { - if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? - { - int RelBlockX = itr->a_RelBlockPos.x; - int RelBlockY = itr->a_RelBlockPos.y; - int RelBlockZ = itr->a_RelBlockPos.z; - BLOCKTYPE Block; - NIBBLETYPE Meta; - m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta); - if (itr->ShouldPowerOn) - { - if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance - { - m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); - } - - switch (Meta & 0x3) // We only want the direction (bottom) bits - { - case 0x0: - { - SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ - 1, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZM); - break; - } - case 0x1: - { - SetBlockPowered(RelBlockX + 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XP); - break; - } - case 0x2: - { - SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ + 1, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZP); - break; - } - case 0x3: - { - SetBlockPowered(RelBlockX - 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XM); - break; - } - } - } - else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF) - { - m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta); - } - itr = m_RepeatersDelayList->erase(itr); - } - else - { - LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); - itr->a_ElapsedTicks++; - itr++; - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - if (IsPistonPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness) - { - cBlockPistonHandler::ExtendPiston(BlockX, a_RelBlockY, BlockZ, &m_World); - } - else - { - cBlockPistonHandler::RetractPiston(BlockX, a_RelBlockY, BlockZ, &m_World); - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - class cSetPowerToDropSpenser : - public cRedstonePoweredCallback - { - bool m_IsPowered; - public: - cSetPowerToDropSpenser(bool a_IsPowered) : m_IsPowered(a_IsPowered) {} - - virtual bool Item(cRedstonePoweredEntity * a_DropSpenser) override - { - a_DropSpenser->SetRedstonePower(m_IsPowered); - return false; - } - } DrSpSP (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); - - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - m_Chunk->DoWithRedstonePoweredEntityAt(BlockX, a_RelBlockY, BlockZ, DrSpSP); -} - - - - - -void cIncrementalRedstoneSimulator::HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) -{ - if (a_MyState == E_BLOCK_REDSTONE_LAMP_OFF) - { - if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_LAMP_ON, 0); - } - } - else - { - if (!AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_LAMP_OFF, 0); - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - m_Chunk->BroadcastSoundEffect("game.tnt.primed", (double)BlockX, (double)a_RelBlockY, (double)BlockZ, 0.5f, 0.6f); - m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_AIR, 0); - m_World.SpawnPrimedTNT(BlockX + 0.5, a_RelBlockY + 0.5, BlockZ + 0.5); // 80 ticks to boom - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) - { - cChunkInterface ChunkInterface(m_World.GetChunkMap()); - if (!cBlockDoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ)) - { - cBlockDoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, true); - m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); - } - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); - } - } - else - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) - { - cChunkInterface ChunkInterface(m_World.GetChunkMap()); - if (cBlockDoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ)) - { - cBlockDoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, false); - m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); - } - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - class cSetPowerToCommandBlock : - public cCommandBlockCallback - { - bool m_IsPowered; - public: - cSetPowerToCommandBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {} - - virtual bool Item(cCommandBlockEntity * a_CommandBlock) override - { - a_CommandBlock->SetRedstonePower(m_IsPowered); - return false; - } - } CmdBlockSP (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); - - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - m_Chunk->DoWithCommandBlockAt(BlockX, a_RelBlockY, BlockZ, CmdBlockSP); -} - - - - - -void cIncrementalRedstoneSimulator::HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType) -{ - switch (a_MyType) - { - case E_BLOCK_DETECTOR_RAIL: - { - if ((m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x08) == 0x08) - { - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType); - } - break; - } - case E_BLOCK_ACTIVATOR_RAIL: - case E_BLOCK_POWERED_RAIL: - { - if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0x08); - } - else - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x07); - } - break; - } - default: LOGD("Unhandled type of rail in %s", __FUNCTION__); - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) - { - m_World.SetTrapdoorOpen(BlockX, a_RelBlockY, BlockZ, true); - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); - } - } - else - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) - { - m_World.SetTrapdoorOpen(BlockX, a_RelBlockY, BlockZ, false); - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - bool m_bAreCoordsPowered = AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - - if (m_bAreCoordsPowered) - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) - { - class cSetPowerToNoteBlock : - public cRedstonePoweredCallback - { - public: - cSetPowerToNoteBlock() {} - - virtual bool Item(cRedstonePoweredEntity * a_NoteBlock) override - { - a_NoteBlock->SetRedstonePower(true); - return false; - } - } NoteBlockSP; - - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - m_Chunk->DoWithRedstonePoweredEntityAt(BlockX, a_RelBlockY, BlockZ, NoteBlockSP); - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); - } - } - else - { - if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) - { - SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX, BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); - - if (!m_World.IsChunkLighted(ChunkX, ChunkZ)) - { - m_World.QueueLightChunk(ChunkX, ChunkZ); - } - else - { - if (m_Chunk->GetTimeAlteredLight(m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8) - { - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - } - else - { - WakeUp(BlockX, a_RelBlockY, BlockZ, m_Chunk); - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - switch (a_MyType) - { - case E_BLOCK_STONE_PRESSURE_PLATE: - { - // MCS feature - stone pressure plates can only be triggered by players :D - cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(BlockX + 0.5f, (float)a_RelBlockY, BlockZ + 0.5f), 0.5f, false); - - if (a_Player != NULL) - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x1); - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); - } - else - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0); - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - } - break; - } - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: - { - class cPressurePlateCallback : - public cEntityCallback - { - public: - cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : - m_NumberOfEntities(0), - m_X(a_BlockX), - m_Y(a_BlockY), - m_Z(a_BlockZ) - { - } - - virtual bool Item(cEntity * a_Entity) override - { - Vector3f EntityPos = a_Entity->GetPosition(); - Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); - double Distance = (EntityPos - BlockPos).Length(); - - if (Distance <= 0.5) - { - m_NumberOfEntities++; - } - return false; - } - - bool GetPowerLevel(unsigned char & a_PowerLevel) const - { - a_PowerLevel = std::min(m_NumberOfEntities, MAX_POWER_LEVEL); - return (a_PowerLevel > 0); - } - - protected: - int m_NumberOfEntities; - - int m_X; - int m_Y; - int m_Z; - }; - - cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ); - m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback); - - unsigned char Power; - NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - if (PressurePlateCallback.GetPowerLevel(Power)) - { - if (Meta == E_META_PRESSURE_PLATE_RAISED) - { - m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F); - } - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED); - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); - } - else - { - if (Meta == E_META_PRESSURE_PLATE_DEPRESSED) - { - m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F); - } - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED); - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - } - - break; - } - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - { - class cPressurePlateCallback : - public cEntityCallback - { - public: - cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : - m_NumberOfEntities(0), - m_X(a_BlockX), - m_Y(a_BlockY), - m_Z(a_BlockZ) - { - } - - virtual bool Item(cEntity * a_Entity) override - { - Vector3f EntityPos = a_Entity->GetPosition(); - Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); - double Distance = (EntityPos - BlockPos).Length(); - - if (Distance <= 0.5) - { - m_NumberOfEntities++; - } - return false; - } - - bool GetPowerLevel(unsigned char & a_PowerLevel) const - { - a_PowerLevel = std::min((int)ceil(m_NumberOfEntities / 10.f), MAX_POWER_LEVEL); - return (a_PowerLevel > 0); - } - - protected: - int m_NumberOfEntities; - - int m_X; - int m_Y; - int m_Z; - }; - - cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ); - m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback); - - unsigned char Power; - NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - if (PressurePlateCallback.GetPowerLevel(Power)) - { - if (Meta == E_META_PRESSURE_PLATE_RAISED) - { - m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F); - } - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED); - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); - } - else - { - if (Meta == E_META_PRESSURE_PLATE_DEPRESSED) - { - m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F); - } - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED); - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - } - - break; - } - case E_BLOCK_WOODEN_PRESSURE_PLATE: - { - class cPressurePlateCallback : - public cEntityCallback - { - public: - cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : - m_FoundEntity(false), - m_X(a_BlockX), - m_Y(a_BlockY), - m_Z(a_BlockZ) - { - } - - virtual bool Item(cEntity * a_Entity) override - { - Vector3f EntityPos = a_Entity->GetPosition(); - Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); - double Distance = (EntityPos - BlockPos).Length(); - - if (Distance <= 0.5) - { - m_FoundEntity = true; - return true; // Break out, we only need to know for plates that at least one entity is on top - } - return false; - } - - bool FoundEntity(void) const - { - return m_FoundEntity; - } - - protected: - bool m_FoundEntity; - - int m_X; - int m_Y; - int m_Z; - } ; - - cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ); - m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback); - - NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - if (PressurePlateCallback.FoundEntity()) - { - if (Meta == E_META_PRESSURE_PLATE_RAISED) - { - m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F); - } - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED); - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); - } - else - { - if (Meta == E_META_PRESSURE_PLATE_DEPRESSED) - { - m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F); - } - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED); - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - } - break; - } - default: - { - LOGD("Unimplemented pressure plate type %s in cRedstoneSimulator", ItemToFullString(a_MyType).c_str()); - break; - } - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; - int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; - int RelX = a_RelBlockX, RelZ = a_RelBlockZ; - bool FoundActivated = false; - eBlockFace FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); - - for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks - { - BLOCKTYPE Type; - NIBBLETYPE Meta; - - AddFaceDirection(RelX, a_RelBlockY, RelZ, FaceToGoTowards); - m_Chunk->UnboundedRelGetBlock(RelX, a_RelBlockY, RelZ, Type, Meta); - - if (Type == E_BLOCK_TRIPWIRE) - { - if (Meta == 0x1) - { - FoundActivated = true; - } - } - else if (Type == E_BLOCK_TRIPWIRE_HOOK) - { - if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards) - { - // Other hook facing in opposite direction - circuit completed! - break; - } - else - { - // Tripwire hook not connected at all, AND away all the power state bits - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3); - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - return; - } - } - else - { - // Tripwire hook not connected at all, AND away all the power state bits - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3); - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - return; - } - } - - if (FoundActivated) - { - // Connected and activated, set the 3rd and 4th highest bits - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0xC); - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - } - else - { - // Connected but not activated, AND away the highest bit - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7) | 0x4); - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - class cGetTrappedChestPlayers : - public cChestCallback - { - public: - cGetTrappedChestPlayers(void) : - m_NumberOfPlayers(0) - { - } - - virtual bool Item(cChestEntity * a_Chest) override - { - ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST); - m_NumberOfPlayers = a_Chest->GetNumberOfPlayers(); - return (m_NumberOfPlayers <= 0); - } - - unsigned char GetPowerLevel(void) const - { - return std::min(m_NumberOfPlayers, MAX_POWER_LEVEL); - } - - private: - int m_NumberOfPlayers; - - } GTCP; - - int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; - int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; - if (m_Chunk->DoWithChestAt(BlockX, a_RelBlockY, BlockZ, GTCP)) - { - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, GTCP.GetPowerLevel()); - } - else - { - SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); - } -} - - - - - -void cIncrementalRedstoneSimulator::HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; - int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; - - class cTripwireCallback : - public cEntityCallback - { - public: - cTripwireCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : - m_FoundEntity(false), - m_X(a_BlockX), - m_Y(a_BlockY), - m_Z(a_BlockZ) - { - } - - virtual bool Item(cEntity * a_Entity) override - { - cBoundingBox bbWire(m_X, m_X + 1, m_Y, m_Y + 0.1, m_Z, m_Z + 1); - cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight()); - - if (bbEntity.DoesIntersect(bbWire)) - { - m_FoundEntity = true; - return true; // One entity is sufficient to trigger the wire - } - return false; - } - - bool FoundEntity(void) const - { - return m_FoundEntity; - } - - protected: - bool m_FoundEntity; - - int m_X; - int m_Y; - int m_Z; - }; - - cTripwireCallback TripwireCallback(BlockX, a_RelBlockY, BlockZ); - m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), TripwireCallback); - - if (TripwireCallback.FoundEntity()) - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x1); - } - else - { - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0); - } -} - - - - - -bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk) -{ - // Torches want to access neighbour's data when on a wall, hence the extra chunk parameter - - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - for (PoweredBlocksList::const_iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end(); ++itr) // Check powered list - { - if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) - { - return true; - } - } - return false; -} - - - - - -bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list - { - if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) - { - return true; - } - } - return false; -} - - - - - -bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta) -{ - // Repeaters cannot be powered by any face except their back; verify that this is true for a source - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) - { - if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } - - switch (a_Meta & 0x3) - { - case 0x0: - { - // Flip the coords to check the back of the repeater - if (itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ + 1))) { return true; } - break; - } - case 0x1: - { - if (itr->a_SourcePos.Equals(Vector3i(BlockX - 1, a_RelBlockY, BlockZ))) { return true; } - break; - } - case 0x2: - { - if (itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ - 1))) { return true; } - break; - } - case 0x3: - { - if (itr->a_SourcePos.Equals(Vector3i(BlockX + 1, a_RelBlockY, BlockZ))) { return true; } - break; - } - } - } - - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) - { - if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } - - switch (a_Meta & 0x3) - { - case 0x0: - { - if (itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ + 1))) { return true; } - break; - } - case 0x1: - { - if (itr->a_MiddlePos.Equals(Vector3i(BlockX - 1, a_RelBlockY, BlockZ))) { return true; } - break; - } - case 0x2: - { - if (itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ - 1))) { return true; } - break; - } - case 0x3: - { - if (itr->a_MiddlePos.Equals(Vector3i(BlockX + 1, a_RelBlockY, BlockZ))) { return true; } - break; - } - } - } - return false; // Couldn't find power source behind repeater -} - - - - - -bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta) -{ - switch (a_Meta & 0x3) // We only want the 'direction' part of our metadata - { - // If the repeater is looking up or down (If parallel to the Z axis) - case 0x0: - case 0x2: - { - // Check if eastern(right) neighbor is a powered on repeater who is facing us - BLOCKTYPE Block = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater? - { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ) & 0x3; - if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked - } - - // Check if western(left) neighbor is a powered on repeater who is facing us - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) - { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX -1, a_RelBlockY, a_RelBlockZ) & 0x3; - if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked - } - - break; - } - - // If the repeater is looking left or right (If parallel to the x axis) - case 0x1: - case 0x3: - { - // Check if southern(down) neighbor is a powered on repeater who is facing us - BLOCKTYPE Block = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) - { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1) & 0x3; - if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked - } - - // Check if northern(up) neighbor is a powered on repeater who is facing us - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) - { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1) & 0x3; - if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked - } - - break; - } - } - - return false; // None of the checks succeeded, I am not a locked repeater -} - - - - -bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta) -{ - // Pistons cannot be powered through their front face; this function verifies that a source meets this requirement - - eBlockFace Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); - int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; - int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; - - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) - { - if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } - - AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face); - - if (!itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) - { - return true; - } - - AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true); - } - - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) - { - if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } - - AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face); - - if (!itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) - { - return true; - } - - AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true); - } - return false; // Source was in front of the piston's front face -} - - - - -bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel) -{ - a_PowerLevel = 0; - int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; - int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; - - for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list - { - if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) - { - continue; - } - a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block) - } - - for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list - { - if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) - { - continue; - } - - BLOCKTYPE Type = E_BLOCK_AIR; - int RelSourceX = itr->a_SourcePos.x - m_Chunk->GetPosX() * cChunkDef::Width; - int RelSourceZ = itr->a_SourcePos.z - m_Chunk->GetPosZ() * cChunkDef::Width; - if (!m_Chunk->UnboundedRelGetBlockType(RelSourceX, itr->a_SourcePos.y, RelSourceZ, Type) || (Type == E_BLOCK_REDSTONE_WIRE)) - { - continue; - } - a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel); - } - - return (a_PowerLevel != 0); // Answer the inital question: is the wire powered? -} - - - - - -bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered) -{ - for (SimulatedPlayerToggleableList::const_iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr) - { - if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - if (itr->WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current? - { - return false; // It was, coordinates are no longer simulated - } - else - { - return true; // It wasn't, don't resimulate block, and allow players to toggle - } - } - } - return false; // Block wasn't even in the list, not simulated -} - - - - - -void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel) -{ - BLOCKTYPE MiddleBlock = 0; - switch (a_Direction) - { - case BLOCK_FACE_XM: - { - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, MiddleBlock)) - { - return; - } - - SetBlockLinkedPowered(a_RelBlockX - 2, a_RelBlockY, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - - break; - } - case BLOCK_FACE_XP: - { - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, MiddleBlock)) - { - return; - } - - SetBlockLinkedPowered(a_RelBlockX + 2, a_RelBlockY, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - - break; - } - case BLOCK_FACE_YM: - { - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, MiddleBlock)) - { - return; - } - - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 2, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - - break; - } - case BLOCK_FACE_YP: - { - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, MiddleBlock)) - { - return; - } - - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 2, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - - break; - } - case BLOCK_FACE_ZM: - { - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, MiddleBlock)) - { - return; - } - - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 2, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - - break; - } - case BLOCK_FACE_ZP: - { - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, MiddleBlock)) - { - return; - } - - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 2, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); - - break; - } - default: - { - ASSERT(!"Unhandled face direction when attempting to set blocks as linked powered!"); // Zombies, that wasn't supposed to happen... - break; - } - } -} - - - - - -void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel) -{ - static const struct - { - int x, y, z; - } gCrossCoords[] = - { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, - { 0, 1, 0 }, - { 0, -1, 0 } - }; - - for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions - { - SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_PowerLevel); - } -} - - - - - -void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX; - int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ; - - cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values - if ((Neighbour == NULL) || !Neighbour->IsValid()) - { - return; - } - - PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList(); // We need to insert the value into the chunk who owns the block position - for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) - { - if ( - itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && - itr->a_SourcePos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) - ) - { - // Check for duplicates, update power level, don't add a new listing - itr->a_PowerLevel = a_PowerLevel; - return; - } - } - - // No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk - // TODO: on C++11 support, change this to a llama function pased to a std::remove_if - for (PoweredBlocksList::iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) - { - if ( - itr->a_BlockPos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) && - itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && - (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE) - ) - { - BLOCKTYPE Block; - NIBBLETYPE Meta; - Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block, Meta); - - if (Block == E_BLOCK_REDSTONE_WIRE) - { - if (Meta < a_PowerLevel) - { - m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it - break; - } - else - { - // Powered wires try to power their source - don't let them! - return; - } - } - } - } - - sPoweredBlocks RC; - RC.a_BlockPos = Vector3i(BlockX, a_RelBlockY, BlockZ); - RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ); - RC.a_PowerLevel = a_PowerLevel; - Powered->push_back(RC); - Neighbour->SetIsRedstoneDirty(true); - m_Chunk->SetIsRedstoneDirty(true); -} - - - - - -void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( - int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, - int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, - int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, - BLOCKTYPE a_MiddleBlock, unsigned char a_PowerLevel - ) -{ - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - int MiddleX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelMiddleX; - int MiddleZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelMiddleZ; - int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX; - int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ; - - if (!IsViableMiddleBlock(a_MiddleBlock)) - { - return; - } - - cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ); - if ((Neighbour == NULL) || !Neighbour->IsValid()) - { - return; - } - - LinkedBlocksList * Linked = Neighbour->GetRedstoneSimulatorLinkedBlocksList(); - for (LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list - { - if ( - itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && - itr->a_MiddlePos.Equals(Vector3i(MiddleX, a_RelMiddleY, MiddleZ)) && - itr->a_SourcePos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) - ) - { - // Check for duplicates, update power level, don't add a new listing - itr->a_PowerLevel = a_PowerLevel; - return; - } - } - - sLinkedPoweredBlocks RC; - RC.a_BlockPos = Vector3i(BlockX, a_RelBlockY, BlockZ); - RC.a_MiddlePos = Vector3i(MiddleX, a_RelMiddleY, MiddleZ); - RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ); - RC.a_PowerLevel = a_PowerLevel; - Linked->push_back(RC); - Neighbour->SetIsRedstoneDirty(true); - m_Chunk->SetIsRedstoneDirty(true); -} - - - - - -void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered) -{ - for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr) - { - if (!itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - continue; - } - - if (itr->WasLastStatePowered != WasLastStatePowered) - { - // If power states different, update listing - itr->WasLastStatePowered = WasLastStatePowered; - return; - } - else - { - // If states the same, just ignore - return; - } - } - - // We have arrive here; no block must be in list - add one - sSimulatedPlayerToggleableList RC; - RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - RC.WasLastStatePowered = WasLastStatePowered; - m_SimulatedPlayerToggleableBlocks->push_back(RC); -} - - - - - -bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn) -{ - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) - { - if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry - { - return false; - } - - // Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit - itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description - itr->a_ElapsedTicks = 0; - itr->ShouldPowerOn = ShouldPowerOn; - return false; - } - } - - // Self not in list, add self to list - sRepeatersDelayList RC; - RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - - // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.) - // Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility - RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; - - RC.a_ElapsedTicks = 0; - RC.ShouldPowerOn = ShouldPowerOn; - m_RepeatersDelayList->push_back(RC); - return true; -} - - - - - -void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_SourceX, int a_SourceY, int a_SourceZ, cChunk * a_Chunk, bool a_IsFirstCall) -{ - if (!a_IsFirstCall) // The neighbouring chunks passed when this parameter is false may be invalid - { - if ((a_Chunk == NULL) || !a_Chunk->IsValid()) - { - return; - } - } - // TODO: on C++11 support, change both of these to llama functions pased to a std::remove_if - - for (PoweredBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end();) - { - if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))) - { - itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->erase(itr); - a_Chunk->SetIsRedstoneDirty(true); - continue; - } - ++itr; - } - for (LinkedBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->end();) - { - if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))) - { - itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->erase(itr); - a_Chunk->SetIsRedstoneDirty(true); - continue; - } - ++itr; - } - - if (a_IsFirstCall && AreCoordsOnChunkBoundary(a_SourceX, a_SourceY, a_SourceZ)) - { - // +- 2 to accomodate linked powered blocks - SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX - 2, a_SourceZ), false); - SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX + 2, a_SourceZ), false); - SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ - 2), false); - SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ + 2), false); - } -} - - - - - -cIncrementalRedstoneSimulator::eRedstoneDirection cIncrementalRedstoneSimulator::GetWireDirection(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - int Dir = REDSTONE_NONE; - - BLOCKTYPE NegX = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, NegX)) - { - if (IsPotentialSource(NegX)) - { - Dir |= (REDSTONE_X_POS); - } - } - - BLOCKTYPE PosX = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, PosX)) - { - if (IsPotentialSource(PosX)) - { - Dir |= (REDSTONE_X_NEG); - } - } - - BLOCKTYPE NegZ = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, NegZ)) - { - if (IsPotentialSource(NegZ)) - { - if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner - { - Dir ^= REDSTONE_X_POS; - Dir |= REDSTONE_X_NEG; - } - if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner - { - Dir ^= REDSTONE_X_NEG; - Dir |= REDSTONE_X_POS; - } - Dir |= REDSTONE_Z_POS; - } - } - - BLOCKTYPE PosZ = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, PosZ)) - { - if (IsPotentialSource(PosZ)) - { - if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner - { - Dir ^= REDSTONE_X_POS; - Dir |= REDSTONE_X_NEG; - } - if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner - { - Dir ^= REDSTONE_X_NEG; - Dir |= REDSTONE_X_POS; - } - Dir |= REDSTONE_Z_NEG; - } - } - return (eRedstoneDirection)Dir; -} - - - - - -bool cIncrementalRedstoneSimulator::IsLeverOn(NIBBLETYPE a_BlockMeta) -{ - // Extract the ON bit from metadata and return if true if it is set: - return ((a_BlockMeta & 0x8) == 0x8); -} - +#include "Globals.h" +#ifndef SELF_TEST +#include "IncrementalRedstoneSimulator.h" +#include "IncrementalRedstoneSimulator.inc" + +#include "Chunk.h" +#include "World.h" +#include "Blocks/GetHandlerCompileTimeTemplate.h" +#include "Blocks/BlockTorch.h" +#include "Blocks/BlockLever.h" +#include "Blocks/BlockButton.h" +#include "Blocks/BlockTripwireHook.h" +#include "Blocks/BlockDoor.h" +#include "Blocks/BlockPiston.h" +#include "BlockEntities/ChestEntity.h" + +#pragma clang diagnostic ignored "-Wweak-template-vtables" +template class cIncrementalRedstoneSimulator; +#endif diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 79740a8f6..bc2c4ffd0 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -6,23 +6,25 @@ /// Per-chunk data for the simulator, specified individual chunks to simulate typedef cCoordWithBlockAndBoolVector cRedstoneSimulatorChunkData; +class cRedstonePoweredEntity; +typedef cItemCallback cRedstonePoweredCallback; - +template class GetHandlerCompileTime, class ChestType> class cIncrementalRedstoneSimulator : - public cRedstoneSimulator + public cRedstoneSimulator { - typedef cRedstoneSimulator super; + typedef cRedstoneSimulator super; public: - cIncrementalRedstoneSimulator(cWorld & a_World); + cIncrementalRedstoneSimulator(WorldType & a_World); ~cIncrementalRedstoneSimulator(); virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used - virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; + virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, ChunkType * a_Chunk) override; virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); } - virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override; + virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override; enum eRedstoneDirection { @@ -82,9 +84,9 @@ private: SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks; RepeatersDelayList * m_RepeatersDelayList; - virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); } - void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk, cChunk * a_OtherChunk = NULL); - cChunk * m_Chunk; + virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); } + void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk, ChunkType * a_OtherChunk = NULL); + ChunkType * m_Chunk; // We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly // In addition to being non-performant, it would stop the player from actually breaking said device @@ -159,12 +161,12 @@ private: /** Removes a block from the Powered and LinkedPowered lists Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests */ - void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk, bool a_IsFirstCall = true); + void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, ChunkType * a_Chunk, bool a_IsFirstCall = true); /** Returns if a coordinate is powered or linked powered */ bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); } /** Returns if a coordinate is in the directly powered blocks list */ - bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk); + bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, ChunkType * a_Chunk); /** Returns if a coordinate is in the indirectly powered blocks list */ bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); /** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */ @@ -312,5 +314,7 @@ private: }; - +#ifdef SELF_TEST +#include "IncrementalRedstoneSimulator.inc" +#endif diff --git a/src/Simulator/IncrementalRedstoneSimulator.inc b/src/Simulator/IncrementalRedstoneSimulator.inc new file mode 100644 index 000000000..6d1f7b0ae --- /dev/null +++ b/src/Simulator/IncrementalRedstoneSimulator.inc @@ -0,0 +1,2208 @@ + +#include "IncrementalRedstoneSimulator.h" +#include "BoundingBox.h" +#include "BlockEntities/RedstonePoweredEntity.h" +#include "Blocks/ChunkInterface.h" + + + +template class GetHandlerCompileTime, class ChestType> +cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(WorldType & a_World) : + super(a_World), + m_RedstoneSimulatorChunkData(), + m_PoweredBlocks(), + m_LinkedPoweredBlocks(), + m_SimulatedPlayerToggleableBlocks(), + m_RepeatersDelayList(), + m_Chunk() +{ +} + + + + +template class GetHandlerCompileTime, class ChestType> +cIncrementalRedstoneSimulator::~cIncrementalRedstoneSimulator() +{ +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk, ChunkType * a_OtherChunk) +{ + if ((a_Chunk == NULL) || !a_Chunk->IsValid()) + { + return; + } + else if ((a_BlockY < 0) || (a_BlockY > cChunkDef::Height)) + { + return; + } + + // We may be called with coordinates in a chunk that is not the first chunk parameter + // In that case, the actual chunk (which the coordinates are in), will be passed as the second parameter + // Use that Chunk pointer to get a relative position + + int RelX = 0; + int RelZ = 0; + BLOCKTYPE Block; + NIBBLETYPE Meta; + + if (a_OtherChunk != NULL) + { + RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width; + RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width; + a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + + // If a_OtherChunk is passed (not NULL), it is the chunk that had a block change, and a_Chunk will be the neighbouring chunk of that block + // Because said neighbouring chunk does not know of this change but still needs to update its redstone, we set it to dirty + a_Chunk->SetIsRedstoneDirty(true); + } + else + { + RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; + RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; + a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + } + + // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid + // Checking only when a block is changed, as opposed to every tick, also improves performance + + PoweredBlocksList * PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); + for (typename PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end();) + { + if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) + { + ++itr; + continue; + } + + if (!IsPotentialSource(Block)) + { + LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); + itr = PoweredBlocks->erase(itr); + continue; + } + else if ( + // Changeable sources + ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) || + ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) || + ((Block == E_BLOCK_DETECTOR_RAIL) && ((Meta & 0x08) == 0)) || + (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) || + ((Block == E_BLOCK_TRIPWIRE_HOOK) && ((Meta & 0x08) == 0)) + ) + { + LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); + itr = PoweredBlocks->erase(itr); + continue; + } + ++itr; + } + + LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); + // We loop through all values (insteading of breaking out at the first) to make sure everything is gone, as there can be multiple SourceBlock entries for one AddBlock coordinate + for (typename LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end();) + { + if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) + { + if (!IsPotentialSource(Block)) + { + LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); + itr = LinkedPoweredBlocks->erase(itr); + continue; + } + else if ( + // Things that can send power through a block but which depends on meta + ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) || + ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) || + (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) + ) + { + LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); + itr = LinkedPoweredBlocks->erase(itr); + continue; + } + } + else if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) + { + if (!IsViableMiddleBlock(Block)) + { + LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); + itr = LinkedPoweredBlocks->erase(itr); + continue; + } + } + ++itr; + } + + SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); + for (typename SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks->begin(); itr != SimulatedPlayerToggleableBlocks->end(); ++itr) + { + if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ))) + { + continue; + } + + if (!IsAllowedBlock(Block)) + { + LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z); + SimulatedPlayerToggleableBlocks->erase(itr); + break; + } + } + + RepeatersDelayList * RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); + for (typename RepeatersDelayList::iterator itr = RepeatersDelayList->begin(); itr != RepeatersDelayList->end(); ++itr) + { + if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ))) + { + continue; + } + + if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) + { + RepeatersDelayList->erase(itr); + break; + } + } + + if (a_OtherChunk != NULL) + { + // DO NOT touch our chunk's data structure if we are being called with coordinates from another chunk - this one caused me massive grief :P + return; + } + + cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); + for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr) + { + if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block + { + if (!IsAllowedBlock(Block)) + { + itr->DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list + } + else + { + itr->DataTwo = false; + itr->Data = Block; // Update block information + } + return; + } + } + + if (!IsAllowedBlock(Block)) + { + return; + } + + for (cRedstoneSimulatorChunkData::iterator itr = a_Chunk->GetRedstoneSimulatorQueuedData()->begin(); itr != a_Chunk->GetRedstoneSimulatorQueuedData()->end(); ++itr) + { + if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) + { + // Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data + return; + } + } + a_Chunk->GetRedstoneSimulatorQueuedData()->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, ChunkType * a_Chunk) +{ + m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); + if (m_RedstoneSimulatorChunkData->empty() && a_Chunk->GetRedstoneSimulatorQueuedData()->empty()) + { + return; + } + + m_RedstoneSimulatorChunkData->insert(m_RedstoneSimulatorChunkData->end(), a_Chunk->GetRedstoneSimulatorQueuedData()->begin(), a_Chunk->GetRedstoneSimulatorQueuedData()->end()); + a_Chunk->GetRedstoneSimulatorQueuedData()->clear(); + + m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); + m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); + m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); + m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); + m_Chunk = a_Chunk; + bool ShouldUpdateSimulateOnceBlocks = false; + + if (a_Chunk->IsRedstoneDirty()) + { + // Simulate the majority of devices only if something (blockwise or power-wise) has changed + // Make sure to allow the chunk to resimulate after the initial run if there was a power change (ShouldUpdateSimulateOnceBlocks helps to do this) + a_Chunk->SetIsRedstoneDirty(false); + ShouldUpdateSimulateOnceBlocks = true; + } + + HandleRedstoneRepeaterDelays(); + + for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();) + { + if (dataitr->DataTwo) + { + dataitr = m_RedstoneSimulatorChunkData->erase(dataitr); + continue; + } + + switch (dataitr->Data) + { + case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->x, dataitr->y, dataitr->z); break; + + case E_BLOCK_WOODEN_PRESSURE_PLATE: + case E_BLOCK_STONE_PRESSURE_PLATE: + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + { + HandlePressurePlate(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + default: break; + } + + if (ShouldUpdateSimulateOnceBlocks) + { + switch (dataitr->Data) + { + case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break; + + case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_DETECTOR_RAIL: + case E_BLOCK_POWERED_RAIL: + { + HandleRail(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + case E_BLOCK_WOODEN_DOOR: + case E_BLOCK_IRON_DOOR: + { + HandleDoor(dataitr->x, dataitr->y, dataitr->z); + break; + } + case E_BLOCK_REDSTONE_LAMP_OFF: + case E_BLOCK_REDSTONE_LAMP_ON: + { + HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + case E_BLOCK_DISPENSER: + case E_BLOCK_DROPPER: + { + HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z); + break; + } + case E_BLOCK_PISTON: + case E_BLOCK_STICKY_PISTON: + { + HandlePiston(dataitr->x, dataitr->y, dataitr->z); + break; + } + case E_BLOCK_REDSTONE_REPEATER_OFF: + case E_BLOCK_REDSTONE_REPEATER_ON: + { + HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + case E_BLOCK_REDSTONE_TORCH_OFF: + case E_BLOCK_REDSTONE_TORCH_ON: + { + HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_WOODEN_BUTTON: + { + HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z); + break; + } + default: break; + } + } + ++dataitr; + } +} + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) +{ + if (AreCoordsOnChunkBoundary(a_BlockX, a_BlockY, a_BlockZ)) + { + // On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk) + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); + + // Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position + // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordinates are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 2, a_BlockZ), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 2, a_BlockZ), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 2), a_Chunk); + RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 2), a_Chunk); + + return; + } + + // Not on boundary, just alert this chunk for speed + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) +{ + static const struct // Define which directions the torch can power + { + int x, y, z; + } gCrossCoords[] = + { + { 1, 0, 0}, + {-1, 0, 0}, + { 0, 0, 1}, + { 0, 0, -1}, + { 0, 1, 0}, + } ; + + if (a_MyState == E_BLOCK_REDSTONE_TORCH_ON) + { + // Check if the block the torch is on is powered + int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ; + AddFaceDirection(X, Y, Z, GetHandlerCompileTime::type::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on + + ChunkType * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z); + if ((Neighbour == NULL) || !Neighbour->IsValid()) + { + return; + } + + if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour)) + { + // There was a match, torch goes off + m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_TORCH_OFF, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); + return; + } + + // Torch still on, make all 4(X, Z) + 1(Y) sides powered + for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) + { + BLOCKTYPE Type = 0; + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, Type)) + { + continue; + } + if (i + 1 < ARRAYCOUNT(gCrossCoords)) // Sides of torch, not top (top is last) + { + if ( + IsMechanism(Type) && // Is it a mechanism? Not block/other torch etc. + (!Vector3i(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z).Equals(Vector3i(X, Y, Z))) // CAN'T power block is that it is on + ) + { + SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + } + } + else + { + // Top side, power whatever is there, including blocks + SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + // Power all blocks surrounding block above torch + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YP); + } + } + + if (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) != 0x5) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath + { + BLOCKTYPE Type = m_Chunk->GetBlock(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ); + + if (IsMechanism(Type)) // Still can't make a normal block powered though! + { + SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + } + } + } + else + { + // Check if the block the torch is on is powered + int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ; + AddFaceDirection(X, Y, Z, GetHandlerCompileTime::type::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on + + ChunkType * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z); + if ((Neighbour == NULL) || !Neighbour->IsValid()) + { + return; + } + + // See if off state torch can be turned on again + if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour)) + { + return; // Something matches, torch still powered + } + + // Block torch on not powered, can be turned on again! + m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_TORCH_ON, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); // Set self as powered +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + if (IsLeverOn(Meta)) + { + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + + eBlockFace Dir = GetHandlerCompileTime::type::BlockMetaDataToBlockFace(Meta); + + Dir = ReverseBlockFace(Dir); + + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + NIBBLETYPE MetaData = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + + if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) + { + if ((MetaData & 0x4) == 0) + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData | 0x4); + m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + } + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); + } + } + else + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) + { + if ((MetaData & 0x4) != 0) + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData & ~0x04); + m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + } + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + if (IsButtonOn(Meta)) + { + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + + eBlockFace Dir = GetHandlerCompileTime::type::BlockMetaDataToBlockFace(Meta); + Dir = ReverseBlockFace(Dir); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + static const struct // Define which directions the wire can receive power from + { + int x, y, z; + } gCrossCoords[] = + { + { 1, 0, 0}, /* Wires on same level start */ + {-1, 0, 0}, + { 0, 0, 1}, + { 0, 0, -1}, /* Wires on same level stop */ + { 1, 1, 0}, /* Wires one higher, surrounding self start */ + {-1, 1, 0}, + { 0, 1, 1}, + { 0, 1, -1}, /* Wires one higher, surrounding self stop */ + { 1, -1, 0}, /* Wires one lower, surrounding self start */ + {-1, -1, 0}, + { 0, -1, 1}, + { 0, -1, -1}, /* Wires one lower, surrounding self stop */ + } ; + + static const struct // Define which directions the wire will check for repeater prescence + { + int x, y, z; + } gSideCoords[] = + { + { 1, 0, 0 }, + {-1, 0, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 }, + { 0, 1, 0 }, + }; + + // Check to see if directly beside a power source + unsigned char MyPower; + if (!IsWirePowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower)) + { + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0); + this->m_World.WakeUpSimulators(BlockX, a_RelBlockY, BlockZ); + return; + } + + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + + if (MyPower < 1) + { + return; + } + + MyPower--; + + for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power + { + if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above... + { + BLOCKTYPE Type = 0; + if (a_RelBlockY + 1 >= cChunkDef::Height) + { + continue; + } + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, Type)) + { + continue; + } + if (cBlockInfo::IsSolid(Type)) // If there is something solid above us (wire cut off)... + { + continue; // We don't receive power from that wire + } + } + else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us + { + BLOCKTYPE Type = 0; + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY, a_RelBlockZ + gCrossCoords[i].z, Type)) + { + continue; + } + if (cBlockInfo::IsSolid(Type)) + { + continue; + } + } + + BLOCKTYPE Type = 0; + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, Type)) + { + continue; + } + if (Type == E_BLOCK_REDSTONE_WIRE) + { + SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + } + } + + for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them + { + BLOCKTYPE Type = 0; + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, Type)) + { + continue; + } + if (Type == E_BLOCK_REDSTONE_REPEATER_OFF) + { + SetBlockPowered(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + } + } + + // Wire still powered, power blocks beneath + SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, MyPower); + + switch (GetWireDirection(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + case REDSTONE_NONE: + { + SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower); + break; + } + case REDSTONE_X_POS: + { + SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower); + break; + } + case REDSTONE_X_NEG: + { + SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower); + break; + } + case REDSTONE_Z_POS: + { + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower); + break; + } + case REDSTONE_Z_NEG: + { + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower); + break; + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) +{ + /* Repeater Orientation Mini Guide: + =================================== + + | + | Z Axis + V + + X Axis ----> + + Repeater directions, values from a WorldType::GetBlockMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) lookup: + + East (Right) (X+): 0x1 + West (Left) (X-): 0x3 + North (Up) (Z-): 0x2 + South (Down) (Z+): 0x0 + // TODO: Add E_META_XXX enum entries for all meta values and update project with them + + Sun rises from East (X+) + + */ + + // Create a variable holding my meta to avoid multiple lookups. + NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON); + + if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta)) // If we're locked, change nothing. Otherwise: + { + bool IsSelfPowered = IsRepeaterPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta); + if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked. + { + QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true); + } + else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked. + { + QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false); + } + } +} + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays() +{ + for (typename RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();) + { + if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? + { + int RelBlockX = itr->a_RelBlockPos.x; + int RelBlockY = itr->a_RelBlockPos.y; + int RelBlockZ = itr->a_RelBlockPos.z; + BLOCKTYPE Block; + NIBBLETYPE Meta; + m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta); + if (itr->ShouldPowerOn) + { + if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance + { + m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); + } + + switch (Meta & 0x3) // We only want the direction (bottom) bits + { + case 0x0: + { + SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ - 1, RelBlockX, RelBlockY, RelBlockZ); + SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZM); + break; + } + case 0x1: + { + SetBlockPowered(RelBlockX + 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ); + SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XP); + break; + } + case 0x2: + { + SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ + 1, RelBlockX, RelBlockY, RelBlockZ); + SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZP); + break; + } + case 0x3: + { + SetBlockPowered(RelBlockX - 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ); + SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XM); + break; + } + } + } + else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF) + { + m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta); + } + itr = m_RepeatersDelayList->erase(itr); + } + else + { + LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); + itr->a_ElapsedTicks++; + itr++; + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + if (IsPistonPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness) + { + GetHandlerCompileTime::type::ExtendPiston(BlockX, a_RelBlockY, BlockZ, &this->m_World); + } + else + { + GetHandlerCompileTime::type::RetractPiston(BlockX, a_RelBlockY, BlockZ, &this->m_World); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + class cSetPowerToDropSpenser : + public cRedstonePoweredCallback + { + bool m_IsPowered; + public: + cSetPowerToDropSpenser(bool a_IsPowered) : m_IsPowered(a_IsPowered) {} + + virtual bool Item(cRedstonePoweredEntity * a_DropSpenser) override + { + a_DropSpenser->SetRedstonePower(m_IsPowered); + return false; + } + } DrSpSP (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); + + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + m_Chunk->DoWithRedstonePoweredEntityAt(BlockX, a_RelBlockY, BlockZ, DrSpSP); +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) +{ + if (a_MyState == E_BLOCK_REDSTONE_LAMP_OFF) + { + if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_LAMP_ON, 0); + } + } + else + { + if (!AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_LAMP_OFF, 0); + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + m_Chunk->BroadcastSoundEffect("game.tnt.primed", (double)BlockX, (double)a_RelBlockY, (double)BlockZ, 0.5f, 0.6f); + m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_AIR, 0); + this->m_World.SpawnPrimedTNT(BlockX + 0.5, a_RelBlockY + 0.5, BlockZ + 0.5); // 80 ticks to boom + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + typedef typename GetHandlerCompileTime::type DoorHandler; + + if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) + { + cChunkInterface ChunkInterface(this->m_World.GetChunkMap()); + if (!DoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ)) + { + DoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, true); + m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + } + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); + } + } + else + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) + { + cChunkInterface ChunkInterface(this->m_World.GetChunkMap()); + if (DoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ)) + { + DoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, false); + m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + } + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + class cSetPowerToCommandBlock : + public cRedstonePoweredCallback + { + bool m_IsPowered; + public: + cSetPowerToCommandBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {} + + virtual bool Item(cRedstonePoweredEntity * a_CommandBlock) override + { + a_CommandBlock->SetRedstonePower(m_IsPowered); + return false; + } + } CmdBlockSP (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); + + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + m_Chunk->DoWithRedstonePoweredEntityAt(BlockX, a_RelBlockY, BlockZ, CmdBlockSP); +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType) +{ + switch (a_MyType) + { + case E_BLOCK_DETECTOR_RAIL: + { + if ((m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x08) == 0x08) + { + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType); + } + break; + } + case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_POWERED_RAIL: + { + if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0x08); + } + else + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x07); + } + break; + } + default: LOGD("Unhandled type of rail in %s", __FUNCTION__); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) + { + this->m_World.SetTrapdoorOpen(BlockX, a_RelBlockY, BlockZ, true); + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); + } + } + else + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) + { + this->m_World.SetTrapdoorOpen(BlockX, a_RelBlockY, BlockZ, false); + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + bool m_bAreCoordsPowered = AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + + if (m_bAreCoordsPowered) + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) + { + class cSetPowerToNoteBlock : + public cRedstonePoweredCallback + { + public: + cSetPowerToNoteBlock() {} + + virtual bool Item(cRedstonePoweredEntity * a_NoteBlock) override + { + a_NoteBlock->SetRedstonePower(true); + return false; + } + } NoteBlockSP; + + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + m_Chunk->DoWithRedstonePoweredEntityAt(BlockX, a_RelBlockY, BlockZ, NoteBlockSP); + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); + } + } + else + { + if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) + { + SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX, BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + int ChunkX, ChunkZ; + cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); + + if (!this->m_World.IsChunkLighted(ChunkX, ChunkZ)) + { + this->m_World.QueueLightChunk(ChunkX, ChunkZ); + } + else + { + if (m_Chunk->GetTimeAlteredLight(this->m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8) + { + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + } + else + { + WakeUp(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + switch (a_MyType) + { + case E_BLOCK_STONE_PRESSURE_PLATE: + { + // MCS feature - stone pressure plates can only be triggered by players :D + cPlayer * a_Player = this->m_World.FindClosestPlayer(Vector3f(BlockX + 0.5f, (float)a_RelBlockY, BlockZ + 0.5f), 0.5f, false); + + if (a_Player != NULL) + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x1); + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); + } + else + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0); + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } + break; + } + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: + { + class cPressurePlateCallback : + public cEntityCallback + { + public: + cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : + m_NumberOfEntities(0), + m_X(a_BlockX), + m_Y(a_BlockY), + m_Z(a_BlockZ) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + Vector3f EntityPos = a_Entity->GetPosition(); + Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); + double Distance = (EntityPos - BlockPos).Length(); + + if (Distance <= 0.5) + { + m_NumberOfEntities++; + } + return false; + } + + bool GetPowerLevel(unsigned char & a_PowerLevel) const + { + a_PowerLevel = std::min(m_NumberOfEntities, MAX_POWER_LEVEL); + return (a_PowerLevel > 0); + } + + protected: + int m_NumberOfEntities; + + int m_X; + int m_Y; + int m_Z; + }; + + cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ); + this->m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback); + + unsigned char Power; + NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + if (PressurePlateCallback.GetPowerLevel(Power)) + { + if (Meta == E_META_PRESSURE_PLATE_RAISED) + { + m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F); + } + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED); + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); + } + else + { + if (Meta == E_META_PRESSURE_PLATE_DEPRESSED) + { + m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F); + } + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED); + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } + + break; + } + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + { + class cPressurePlateCallback : + public cEntityCallback + { + public: + cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : + m_NumberOfEntities(0), + m_X(a_BlockX), + m_Y(a_BlockY), + m_Z(a_BlockZ) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + Vector3f EntityPos = a_Entity->GetPosition(); + Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); + double Distance = (EntityPos - BlockPos).Length(); + + if (Distance <= 0.5) + { + m_NumberOfEntities++; + } + return false; + } + + bool GetPowerLevel(unsigned char & a_PowerLevel) const + { + a_PowerLevel = std::min((int)ceil(m_NumberOfEntities / 10.f), MAX_POWER_LEVEL); + return (a_PowerLevel > 0); + } + + protected: + int m_NumberOfEntities; + + int m_X; + int m_Y; + int m_Z; + }; + + cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ); + this->m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback); + + unsigned char Power; + NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + if (PressurePlateCallback.GetPowerLevel(Power)) + { + if (Meta == E_META_PRESSURE_PLATE_RAISED) + { + m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F); + } + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED); + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); + } + else + { + if (Meta == E_META_PRESSURE_PLATE_DEPRESSED) + { + m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F); + } + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED); + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } + + break; + } + case E_BLOCK_WOODEN_PRESSURE_PLATE: + { + class cPressurePlateCallback : + public cEntityCallback + { + public: + cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : + m_FoundEntity(false), + m_X(a_BlockX), + m_Y(a_BlockY), + m_Z(a_BlockZ) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + Vector3f EntityPos = a_Entity->GetPosition(); + Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); + double Distance = (EntityPos - BlockPos).Length(); + + if (Distance <= 0.5) + { + m_FoundEntity = true; + return true; // Break out, we only need to know for plates that at least one entity is on top + } + return false; + } + + bool FoundEntity(void) const + { + return m_FoundEntity; + } + + protected: + bool m_FoundEntity; + + int m_X; + int m_Y; + int m_Z; + } ; + + cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ); + this->m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback); + + NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + if (PressurePlateCallback.FoundEntity()) + { + if (Meta == E_META_PRESSURE_PLATE_RAISED) + { + m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F); + } + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED); + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType); + } + else + { + if (Meta == E_META_PRESSURE_PLATE_DEPRESSED) + { + m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F); + } + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED); + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } + break; + } + default: + { + LOGD("Unimplemented pressure plate type %s in cRedstoneSimulator", ItemToFullString(a_MyType).c_str()); + break; + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; + int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; + int RelX = a_RelBlockX, RelZ = a_RelBlockZ; + bool FoundActivated = false; + eBlockFace FaceToGoTowards = GetHandlerCompileTime::type::MetadataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); + + for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks + { + BLOCKTYPE Type; + NIBBLETYPE Meta; + + AddFaceDirection(RelX, a_RelBlockY, RelZ, FaceToGoTowards); + m_Chunk->UnboundedRelGetBlock(RelX, a_RelBlockY, RelZ, Type, Meta); + + if (Type == E_BLOCK_TRIPWIRE) + { + if (Meta == 0x1) + { + FoundActivated = true; + } + } + else if (Type == E_BLOCK_TRIPWIRE_HOOK) + { + if (ReverseBlockFace( GetHandlerCompileTime::type::MetadataToDirection(Meta)) == FaceToGoTowards) + { + // Other hook facing in opposite direction - circuit completed! + break; + } + else + { + // Tripwire hook not connected at all, AND away all the power state bits + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3); + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + return; + } + } + else + { + // Tripwire hook not connected at all, AND away all the power state bits + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3); + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + return; + } + } + + if (FoundActivated) + { + // Connected and activated, set the 3rd and 4th highest bits + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0xC); + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + } + else + { + // Connected but not activated, AND away the highest bit + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7) | 0x4); + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + class cGetTrappedChestPlayers : + public cChestCallback + { + public: + cGetTrappedChestPlayers(void) : + m_NumberOfPlayers(0) + { + } + + virtual bool Item(ChestType * a_Chest) override + { + ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST); + m_NumberOfPlayers = a_Chest->GetNumberOfPlayers(); + return (m_NumberOfPlayers <= 0); + } + + unsigned char GetPowerLevel(void) const + { + return std::min(m_NumberOfPlayers, MAX_POWER_LEVEL); + } + + private: + int m_NumberOfPlayers; + + } GTCP; + + int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; + int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; + if (m_Chunk->DoWithChestAt(BlockX, a_RelBlockY, BlockZ, GTCP)) + { + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, GTCP.GetPowerLevel()); + } + else + { + SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; + int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; + + class cTripwireCallback : + public cEntityCallback + { + public: + cTripwireCallback(int a_BlockX, int a_BlockY, int a_BlockZ) : + m_FoundEntity(false), + m_X(a_BlockX), + m_Y(a_BlockY), + m_Z(a_BlockZ) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + cBoundingBox bbWire(m_X, m_X + 1, m_Y, m_Y + 0.1, m_Z, m_Z + 1); + cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight()); + + if (bbEntity.DoesIntersect(bbWire)) + { + m_FoundEntity = true; + return true; // One entity is sufficient to trigger the wire + } + return false; + } + + bool FoundEntity(void) const + { + return m_FoundEntity; + } + + protected: + bool m_FoundEntity; + + int m_X; + int m_Y; + int m_Z; + }; + + cTripwireCallback TripwireCallback(BlockX, a_RelBlockY, BlockZ); + this->m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), TripwireCallback); + + if (TripwireCallback.FoundEntity()) + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x1); + } + else + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, ChunkType * a_Chunk) +{ + // Torches want to access neighbour's data when on a wall, hence the extra chunk parameter + + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + for (typename PoweredBlocksList::const_iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end(); ++itr) // Check powered list + { + if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) + { + return true; + } + } + return false; +} + + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + for (typename LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list + { + if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) + { + return true; + } + } + return false; +} + + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta) +{ + // Repeaters cannot be powered by any face except their back; verify that this is true for a source + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + + for (typename PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) + { + if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } + + switch (a_Meta & 0x3) + { + case 0x0: + { + // Flip the coords to check the back of the repeater + if (itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ + 1))) { return true; } + break; + } + case 0x1: + { + if (itr->a_SourcePos.Equals(Vector3i(BlockX - 1, a_RelBlockY, BlockZ))) { return true; } + break; + } + case 0x2: + { + if (itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ - 1))) { return true; } + break; + } + case 0x3: + { + if (itr->a_SourcePos.Equals(Vector3i(BlockX + 1, a_RelBlockY, BlockZ))) { return true; } + break; + } + } + } + + for (typename LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) + { + if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } + + switch (a_Meta & 0x3) + { + case 0x0: + { + if (itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ + 1))) { return true; } + break; + } + case 0x1: + { + if (itr->a_MiddlePos.Equals(Vector3i(BlockX - 1, a_RelBlockY, BlockZ))) { return true; } + break; + } + case 0x2: + { + if (itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ - 1))) { return true; } + break; + } + case 0x3: + { + if (itr->a_MiddlePos.Equals(Vector3i(BlockX + 1, a_RelBlockY, BlockZ))) { return true; } + break; + } + } + } + return false; // Couldn't find power source behind repeater +} + + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta) +{ + switch (a_Meta & 0x3) // We only want the 'direction' part of our metadata + { + // If the repeater is looking up or down (If parallel to the Z axis) + case 0x0: + case 0x2: + { + // Check if eastern(right) neighbor is a powered on repeater who is facing us + BLOCKTYPE Block = 0; + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater? + { + NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ) & 0x3; + if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked + } + + // Check if western(left) neighbor is a powered on repeater who is facing us + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) + { + NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX -1, a_RelBlockY, a_RelBlockZ) & 0x3; + if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked + } + + break; + } + + // If the repeater is looking left or right (If parallel to the x axis) + case 0x1: + case 0x3: + { + // Check if southern(down) neighbor is a powered on repeater who is facing us + BLOCKTYPE Block = 0; + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) + { + NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1) & 0x3; + if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked + } + + // Check if northern(up) neighbor is a powered on repeater who is facing us + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) + { + NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1) & 0x3; + if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked + } + + break; + } + } + + return false; // None of the checks succeeded, I am not a locked repeater +} + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta) +{ + // Pistons cannot be powered through their front face; this function verifies that a source meets this requirement + + eBlockFace Face = GetHandlerCompileTime::type::MetaDataToDirection(a_Meta); + int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; + int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; + + for (typename PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) + { + if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } + + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face); + + if (!itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) + { + return true; + } + + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true); + } + + for (typename LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) + { + if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } + + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face); + + if (!itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) + { + return true; + } + + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true); + } + return false; // Source was in front of the piston's front face +} + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel) +{ + a_PowerLevel = 0; + int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; + int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; + + for (typename PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list + { + if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) + { + continue; + } + a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block) + } + + for (typename LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list + { + if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) + { + continue; + } + + BLOCKTYPE Type = E_BLOCK_AIR; + int RelSourceX = itr->a_SourcePos.x - m_Chunk->GetPosX() * cChunkDef::Width; + int RelSourceZ = itr->a_SourcePos.z - m_Chunk->GetPosZ() * cChunkDef::Width; + if (!m_Chunk->UnboundedRelGetBlockType(RelSourceX, itr->a_SourcePos.y, RelSourceZ, Type) || (Type == E_BLOCK_REDSTONE_WIRE)) + { + continue; + } + a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel); + } + + return (a_PowerLevel != 0); // Answer the inital question: is the wire powered? +} + + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered) +{ + for (typename SimulatedPlayerToggleableList::const_iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr) + { + if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + { + if (itr->WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current? + { + return false; // It was, coordinates are no longer simulated + } + else + { + return true; // It wasn't, don't resimulate block, and allow players to toggle + } + } + } + return false; // Block wasn't even in the list, not simulated +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel) +{ + BLOCKTYPE MiddleBlock = 0; + switch (a_Direction) + { + case BLOCK_FACE_XM: + { + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, MiddleBlock)) + { + return; + } + + SetBlockLinkedPowered(a_RelBlockX - 2, a_RelBlockY, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + + break; + } + case BLOCK_FACE_XP: + { + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, MiddleBlock)) + { + return; + } + + SetBlockLinkedPowered(a_RelBlockX + 2, a_RelBlockY, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + + break; + } + case BLOCK_FACE_YM: + { + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, MiddleBlock)) + { + return; + } + + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 2, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + + break; + } + case BLOCK_FACE_YP: + { + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, MiddleBlock)) + { + return; + } + + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 2, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + + break; + } + case BLOCK_FACE_ZM: + { + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, MiddleBlock)) + { + return; + } + + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 2, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + + break; + } + case BLOCK_FACE_ZP: + { + if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, MiddleBlock)) + { + return; + } + + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 2, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel); + + break; + } + default: + { + ASSERT(!"Unhandled face direction when attempting to set blocks as linked powered!"); // Zombies, that wasn't supposed to happen... + break; + } + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel) +{ + static const struct + { + int x, y, z; + } gCrossCoords[] = + { + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 }, + { 0, 1, 0 }, + { 0, -1, 0 } + }; + + for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions + { + SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_PowerLevel); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX; + int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ; + + ChunkType * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values + if ((Neighbour == NULL) || !Neighbour->IsValid()) + { + return; + } + + PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList(); // We need to insert the value into the chunk who owns the block position + for (typename PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) + { + if ( + itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && + itr->a_SourcePos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) + ) + { + // Check for duplicates, update power level, don't add a new listing + itr->a_PowerLevel = a_PowerLevel; + return; + } + } + + // No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk + // TODO: on C++11 support, change this to a llama function pased to a std::remove_if + for (typename PoweredBlocksList::iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) + { + if ( + itr->a_BlockPos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) && + itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && + (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE) + ) + { + BLOCKTYPE Block; + NIBBLETYPE Meta; + Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block, Meta); + + if (Block == E_BLOCK_REDSTONE_WIRE) + { + if (Meta < a_PowerLevel) + { + m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it + break; + } + else + { + // Powered wires try to power their source - don't let them! + return; + } + } + } + } + + sPoweredBlocks RC; + RC.a_BlockPos = Vector3i(BlockX, a_RelBlockY, BlockZ); + RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ); + RC.a_PowerLevel = a_PowerLevel; + Powered->push_back(RC); + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( + int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, + int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, + int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, + BLOCKTYPE a_MiddleBlock, unsigned char a_PowerLevel + ) +{ + int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; + int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + int MiddleX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelMiddleX; + int MiddleZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelMiddleZ; + int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX; + int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ; + + if (!IsViableMiddleBlock(a_MiddleBlock)) + { + return; + } + + ChunkType * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ); + if ((Neighbour == NULL) || !Neighbour->IsValid()) + { + return; + } + + LinkedBlocksList * Linked = Neighbour->GetRedstoneSimulatorLinkedBlocksList(); + for (typename LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list + { + if ( + itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && + itr->a_MiddlePos.Equals(Vector3i(MiddleX, a_RelMiddleY, MiddleZ)) && + itr->a_SourcePos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) + ) + { + // Check for duplicates, update power level, don't add a new listing + itr->a_PowerLevel = a_PowerLevel; + return; + } + } + + sLinkedPoweredBlocks RC; + RC.a_BlockPos = Vector3i(BlockX, a_RelBlockY, BlockZ); + RC.a_MiddlePos = Vector3i(MiddleX, a_RelMiddleY, MiddleZ); + RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ); + RC.a_PowerLevel = a_PowerLevel; + Linked->push_back(RC); + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered) +{ + for (typename SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr) + { + if (!itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + { + continue; + } + + if (itr->WasLastStatePowered != WasLastStatePowered) + { + // If power states different, update listing + itr->WasLastStatePowered = WasLastStatePowered; + return; + } + else + { + // If states the same, just ignore + return; + } + } + + // We have arrive here; no block must be in list - add one + sSimulatedPlayerToggleableList RC; + RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + RC.WasLastStatePowered = WasLastStatePowered; + m_SimulatedPlayerToggleableBlocks->push_back(RC); +} + + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn) +{ + for (typename RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) + { + if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + { + if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry + { + return false; + } + + // Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit + itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description + itr->a_ElapsedTicks = 0; + itr->ShouldPowerOn = ShouldPowerOn; + return false; + } + } + + // Self not in list, add self to list + sRepeatersDelayList RC; + RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + + // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.) + // Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility + RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; + + RC.a_ElapsedTicks = 0; + RC.ShouldPowerOn = ShouldPowerOn; + m_RepeatersDelayList->push_back(RC); + return true; +} + + + + +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_SourceX, int a_SourceY, int a_SourceZ, ChunkType * a_Chunk, bool a_IsFirstCall) +{ + if (!a_IsFirstCall) // The neighbouring chunks passed when this parameter is false may be invalid + { + if ((a_Chunk == NULL) || !a_Chunk->IsValid()) + { + return; + } + } + // TODO: on C++11 support, change both of these to llama functions pased to a std::remove_if + + for (typename PoweredBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end();) + { + if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))) + { + itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->erase(itr); + a_Chunk->SetIsRedstoneDirty(true); + continue; + } + ++itr; + } + for (typename LinkedBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->end();) + { + if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))) + { + itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->erase(itr); + a_Chunk->SetIsRedstoneDirty(true); + continue; + } + ++itr; + } + + if (a_IsFirstCall && AreCoordsOnChunkBoundary(a_SourceX, a_SourceY, a_SourceZ)) + { + // +- 2 to accomodate linked powered blocks + SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX - 2, a_SourceZ), false); + SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX + 2, a_SourceZ), false); + SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ - 2), false); + SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ + 2), false); + } +} + + + + +template class GetHandlerCompileTime, class ChestType> +typename cIncrementalRedstoneSimulator::eRedstoneDirection cIncrementalRedstoneSimulator::GetWireDirection(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + int Dir = REDSTONE_NONE; + + BLOCKTYPE NegX = 0; + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, NegX)) + { + if (IsPotentialSource(NegX)) + { + Dir |= (REDSTONE_X_POS); + } + } + + BLOCKTYPE PosX = 0; + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, PosX)) + { + if (IsPotentialSource(PosX)) + { + Dir |= (REDSTONE_X_NEG); + } + } + + BLOCKTYPE NegZ = 0; + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, NegZ)) + { + if (IsPotentialSource(NegZ)) + { + if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner + { + Dir ^= REDSTONE_X_POS; + Dir |= REDSTONE_X_NEG; + } + if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner + { + Dir ^= REDSTONE_X_NEG; + Dir |= REDSTONE_X_POS; + } + Dir |= REDSTONE_Z_POS; + } + } + + BLOCKTYPE PosZ = 0; + if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, PosZ)) + { + if (IsPotentialSource(PosZ)) + { + if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner + { + Dir ^= REDSTONE_X_POS; + Dir |= REDSTONE_X_NEG; + } + if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner + { + Dir ^= REDSTONE_X_NEG; + Dir |= REDSTONE_X_POS; + } + Dir |= REDSTONE_Z_NEG; + } + } + return (eRedstoneDirection)Dir; +} + + + + +template class GetHandlerCompileTime, class ChestType> +bool cIncrementalRedstoneSimulator::IsLeverOn(NIBBLETYPE a_BlockMeta) +{ + // Extract the ON bit from metadata and return if true if it is set: + return ((a_BlockMeta & 0x8) == 0x8); +} + + + + diff --git a/src/Simulator/NoopRedstoneSimulator.h b/src/Simulator/NoopRedstoneSimulator.h index f9ed47982..88e141e85 100644 --- a/src/Simulator/NoopRedstoneSimulator.h +++ b/src/Simulator/NoopRedstoneSimulator.h @@ -8,9 +8,9 @@ class cRedstoneNoopSimulator : - public cRedstoneSimulator + public cRedstoneSimulator { - typedef cRedstoneSimulator super; + typedef cRedstoneSimulator super; public: cRedstoneNoopSimulator(cWorld & a_World) : diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp deleted file mode 100644 index a83f21106..000000000 --- a/src/Simulator/RedstoneSimulator.cpp +++ /dev/null @@ -1,19 +0,0 @@ - -#include "Globals.h" - -#include "RedstoneSimulator.h" -#include "../World.h" - - - - - -cRedstoneSimulator::cRedstoneSimulator(cWorld & a_World) : - super(a_World) -{ -} - - - - - diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h index b3e20c9a5..56843e37f 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -5,13 +5,16 @@ - +template class cRedstoneSimulator : - public cSimulator + public cSimulator { - typedef cSimulator super; + typedef cSimulator super; public: - cRedstoneSimulator(cWorld & a_World); + cRedstoneSimulator(WorldType & a_World) : + super(a_World) + { + } } ; diff --git a/src/Simulator/SandSimulator.h b/src/Simulator/SandSimulator.h index 1262f2792..feb82b4d5 100644 --- a/src/Simulator/SandSimulator.h +++ b/src/Simulator/SandSimulator.h @@ -3,13 +3,15 @@ #include "Simulator.h" +/// Per-chunk data for the simulator, specified individual chunks to simulate; Data is not used +typedef cCoordWithIntList cSandSimulatorChunkData; - +#include "Chunk.h" /// Despite the class name, this simulator takes care of all blocks that fall when suspended in the air. class cSandSimulator : - public cSimulator + public cSimulator { public: cSandSimulator(cWorld & a_World, cIniFile & a_IniFile); @@ -55,8 +57,7 @@ protected: -/// Per-chunk data for the simulator, specified individual chunks to simulate; Data is not used -typedef cCoordWithIntList cSandSimulatorChunkData; + diff --git a/src/Simulator/Simulator.cpp b/src/Simulator/Simulator.cpp index 0739f0187..7b944382b 100644 --- a/src/Simulator/Simulator.cpp +++ b/src/Simulator/Simulator.cpp @@ -1,50 +1,8 @@ -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Simulator.h" -#include "../World.h" -#include "../BlockID.h" -#include "../Defines.h" -#include "../Chunk.h" - - - - - -cSimulator::cSimulator(cWorld & a_World) - : m_World(a_World) -{ -} - - - - - -cSimulator::~cSimulator() -{ -} - - - - - -void cSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) -{ - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); - AddBlock(a_BlockX - 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ)); - AddBlock(a_BlockX + 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ)); - AddBlock(a_BlockX, a_BlockY, a_BlockZ - 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1)); - AddBlock(a_BlockX, a_BlockY, a_BlockZ + 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1)); - if (a_BlockY > 0) - { - AddBlock(a_BlockX, a_BlockY - 1, a_BlockZ, a_Chunk); - } - if (a_BlockY < cChunkDef::Height - 1) - { - AddBlock(a_BlockX, a_BlockY + 1, a_BlockZ, a_Chunk); - } -} - +#include "Globals.h" +#include "Simulator.inc" +#pragma clang diagnostic ignored "-Wweak-template-vtables" +template class cSimulator; diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h index 4d9a18867..ff53b17e1 100644 --- a/src/Simulator/Simulator.h +++ b/src/Simulator/Simulator.h @@ -8,17 +8,12 @@ -class cWorld; -class cChunk; - - - - +template class cSimulator { public: - cSimulator(cWorld & a_World); + cSimulator(WorldType & a_World); virtual ~cSimulator(); /// Called in each tick, a_Dt is the time passed since the last tick, in msec @@ -26,7 +21,7 @@ public: /// Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct access to chunk data available virtual void SimulateChunk(float a_Dt, int a_ChunkX, - int a_ChunkZ, cChunk * a_Chunk) + int a_ChunkZ, ChunkType * a_Chunk) { UNUSED(a_Dt); UNUSED(a_ChunkX); @@ -35,7 +30,7 @@ public: } /// Called when a block changes - virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk); + virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk); virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) = 0; @@ -43,9 +38,9 @@ protected: friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up /// Called to simulate a new block - virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) = 0; + virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) = 0; - cWorld & m_World; + WorldType & m_World; } ; diff --git a/src/Simulator/Simulator.inc b/src/Simulator/Simulator.inc new file mode 100644 index 000000000..1599ea60f --- /dev/null +++ b/src/Simulator/Simulator.inc @@ -0,0 +1,49 @@ + + +#include "Simulator.h" +#include "../World.h" +#include "../BlockID.h" +#include "../Defines.h" +#include "../Chunk.h" + + + + +template +cSimulator::cSimulator(WorldType & a_World) + : m_World(a_World) +{ +} + + + + +template +cSimulator::~cSimulator() +{ +} + + + + +template +void cSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) +{ + AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); + AddBlock(a_BlockX - 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ)); + AddBlock(a_BlockX + 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ)); + AddBlock(a_BlockX, a_BlockY, a_BlockZ - 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1)); + AddBlock(a_BlockX, a_BlockY, a_BlockZ + 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1)); + if (a_BlockY > 0) + { + AddBlock(a_BlockX, a_BlockY - 1, a_BlockZ, a_Chunk); + } + if (a_BlockY < cChunkDef::Height - 1) + { + AddBlock(a_BlockX, a_BlockY + 1, a_BlockZ, a_Chunk); + } +} + + + + diff --git a/src/Simulator/SimulatorManager.cpp b/src/Simulator/SimulatorManager.cpp index 918bac7a1..dafdcd239 100644 --- a/src/Simulator/SimulatorManager.cpp +++ b/src/Simulator/SimulatorManager.cpp @@ -70,7 +70,7 @@ void cSimulatorManager::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk -void cSimulatorManager::RegisterSimulator(cSimulator * a_Simulator, int a_Rate) +void cSimulatorManager::RegisterSimulator(cSimulator * a_Simulator, int a_Rate) { m_Simulators.push_back(std::make_pair(a_Simulator, a_Rate)); } diff --git a/src/Simulator/SimulatorManager.h b/src/Simulator/SimulatorManager.h index 31a709316..185141764 100644 --- a/src/Simulator/SimulatorManager.h +++ b/src/Simulator/SimulatorManager.h @@ -37,10 +37,10 @@ public: void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk); - void RegisterSimulator(cSimulator * a_Simulator, int a_Rate); // Takes ownership of the simulator object! + void RegisterSimulator(cSimulator * a_Simulator, int a_Rate); // Takes ownership of the simulator object! protected: - typedef std::vector > cSimulators; + typedef std::vector *, int> > cSimulators; cWorld & m_World; cSimulators m_Simulators; diff --git a/src/World.cpp b/src/World.cpp index fdc0aebad..732c9f14c 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -3258,7 +3258,7 @@ void cWorld::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicke -cRedstoneSimulator * cWorld::InitializeRedstoneSimulator(cIniFile & a_IniFile) +cRedstoneSimulator * cWorld::InitializeRedstoneSimulator(cIniFile & a_IniFile) { AString SimulatorName = a_IniFile.GetValueSet("Physics", "RedstoneSimulator", "Incremental"); @@ -3268,11 +3268,11 @@ cRedstoneSimulator * cWorld::InitializeRedstoneSimulator(cIniFile & a_IniFile) SimulatorName = "Incremental"; } - cRedstoneSimulator * res = NULL; + cRedstoneSimulator * res = NULL; if (NoCaseCompare(SimulatorName, "Incremental") == 0) { - res = new cIncrementalRedstoneSimulator(*this); + res = new cIncrementalRedstoneSimulator(*this); } else if (NoCaseCompare(SimulatorName, "noop") == 0) { diff --git a/src/World.h b/src/World.h index 274bd2dcf..e4fe2965f 100644 --- a/src/World.h +++ b/src/World.h @@ -33,6 +33,7 @@ class cFireSimulator; class cFluidSimulator; class cSandSimulator; +template class cRedstoneSimulator; class cItem; class cPlayer; @@ -502,7 +503,7 @@ public: inline cFluidSimulator * GetWaterSimulator(void) { return m_WaterSimulator; } inline cFluidSimulator * GetLavaSimulator (void) { return m_LavaSimulator; } - inline cRedstoneSimulator * GetRedstoneSimulator(void) { return m_RedstoneSimulator; } + inline cRedstoneSimulator * GetRedstoneSimulator(void) { return m_RedstoneSimulator; } /** Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true */ bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Exported in ManualBindings.cpp @@ -910,7 +911,7 @@ private: cFluidSimulator * m_WaterSimulator; cFluidSimulator * m_LavaSimulator; cFireSimulator * m_FireSimulator; - cRedstoneSimulator * m_RedstoneSimulator; + cRedstoneSimulator * m_RedstoneSimulator; cCriticalSection m_CSPlayers; cPlayerList m_Players; @@ -1051,7 +1052,7 @@ private: cFluidSimulator * InitializeFluidSimulator(cIniFile & a_IniFile, const char * a_FluidName, BLOCKTYPE a_SimulateBlock, BLOCKTYPE a_StationaryBlock); /** Creates a new redstone simulator.*/ - cRedstoneSimulator * InitializeRedstoneSimulator(cIniFile & a_IniFile); + cRedstoneSimulator * InitializeRedstoneSimulator(cIniFile & a_IniFile); /** Adds the players queued in the m_PlayersToAdd queue into the m_Players list. Assumes it is called from the Tick thread. */ -- cgit v1.2.3 From b87585977fb60e3ffa44864dc8ba28a031e47e2f Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 11 Sep 2014 17:57:34 +0100 Subject: Don't include IncrementalRedsonteSimulator.inc when in SELF_TEST mode --- src/Simulator/IncrementalRedstoneSimulator.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index bc2c4ffd0..0120a3208 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -313,8 +313,3 @@ private: } }; - -#ifdef SELF_TEST -#include "IncrementalRedstoneSimulator.inc" -#endif - -- cgit v1.2.3 From c45bf7cf55cac42fd168df6d008cb814dd94eae1 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 11 Sep 2014 20:06:28 +0200 Subject: 1.8: Fixed hangings. --- src/Entities/ItemFrame.cpp | 2 +- src/Protocol/Protocol17x.cpp | 2 +- src/Protocol/Protocol18x.cpp | 114 +++++++++++++++++++++++++++++++------------ src/Protocol/Protocol18x.h | 3 ++ 4 files changed, 89 insertions(+), 32 deletions(-) diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp index 0bc10ec60..7f923ef61 100644 --- a/src/Entities/ItemFrame.cpp +++ b/src/Entities/ItemFrame.cpp @@ -26,7 +26,7 @@ void cItemFrame::OnRightClicked(cPlayer & a_Player) { // Item not empty, rotate, clipping values to zero to three inclusive m_Rotation++; - if (m_Rotation >= 4) + if (m_Rotation >= 8) { m_Rotation = 0; } diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index d83e86ece..2b0c8baf8 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2834,7 +2834,7 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) WriteByte(0xA2); WriteItem(Frame.GetItem()); WriteByte(0x3); - WriteByte(Frame.GetRotation()); + WriteByte(Frame.GetRotation() / 2); break; } default: break; diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 2ea83351e..28fffd851 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -406,9 +406,7 @@ void cProtocol180::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x36); // Sign Editor Open packet - Pkt.WriteInt(a_BlockX); - Pkt.WriteInt(a_BlockY); - Pkt.WriteInt(a_BlockZ); + Pkt.WritePosition(a_BlockX, a_BlockX, a_BlockZ); } @@ -702,12 +700,23 @@ void cProtocol180::SendLoginSuccess(void) void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) { ASSERT(m_State == 3); // In game mode? - - /*cPacketizer Pkt(*this, 0x10); // Spawn Painting packet + double PosX = a_Painting.GetPosX(); + double PosY = a_Painting.GetPosY(); + double PosZ = a_Painting.GetPosZ(); + + switch (a_Painting.GetDirection()) + { + case 0: PosZ += 1; break; + case 1: PosX -= 1; break; + case 2: PosZ -= 1; break; + case 3: PosX += 1; break; + } + + cPacketizer Pkt(*this, 0x10); // Spawn Painting packet Pkt.WriteVarInt(a_Painting.GetUniqueID()); Pkt.WriteString(a_Painting.GetName().c_str()); - Pkt.WritePosition(Vector3i(a_Painting.GetPosX(), a_Painting.GetPosY(), a_Painting.GetPosZ())); - Pkt.WriteChar(a_Painting.GetDirection());*/ + Pkt.WritePosition(PosX, PosY, PosZ); + Pkt.WriteChar(a_Painting.GetDirection()); } @@ -1194,7 +1203,7 @@ void cProtocol180::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) Pkt.WriteFPInt(a_FallingBlock.GetPosZ()); Pkt.WriteByteAngle(a_FallingBlock.GetYaw()); Pkt.WriteByteAngle(a_FallingBlock.GetPitch()); - Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10 + Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 12)); Pkt.WriteShort((short)(a_FallingBlock.GetSpeedX() * 400)); Pkt.WriteShort((short)(a_FallingBlock.GetSpeedY() * 400)); Pkt.WriteShort((short)(a_FallingBlock.GetSpeedZ() * 400)); @@ -1231,15 +1240,22 @@ void cProtocol180::SendSpawnMob(const cMonster & a_Mob) void cProtocol180::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) { ASSERT(m_State == 3); // In game mode? - + double PosX = a_Entity.GetPosX(); + double PosZ = a_Entity.GetPosZ(); + double Yaw = a_Entity.GetYaw(); + if (a_ObjectType == 71) + { + FixItemFramePositions(a_ObjectData, PosX, PosZ, Yaw); + } + cPacketizer Pkt(*this, 0xe); // Spawn Object packet Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteByte(a_ObjectType); - Pkt.WriteFPInt(a_Entity.GetPosX()); + Pkt.WriteFPInt(PosX); Pkt.WriteFPInt(a_Entity.GetPosY()); - Pkt.WriteFPInt(a_Entity.GetPosZ()); + Pkt.WriteFPInt(PosZ); Pkt.WriteByteAngle(a_Entity.GetPitch()); - Pkt.WriteByteAngle(a_Entity.GetYaw()); + Pkt.WriteByteAngle(Yaw); Pkt.WriteInt(a_ObjectData); if (a_ObjectData != 0) { @@ -1416,14 +1432,11 @@ void cProtocol180::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, cons ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x33); - Pkt.WriteInt(a_BlockX); - Pkt.WriteShort((short)a_BlockY); - Pkt.WriteInt(a_BlockZ); - // Need to send only up to 15 chars, otherwise the client crashes (#598) - Pkt.WriteString(a_Line1.substr(0, 15)); - Pkt.WriteString(a_Line2.substr(0, 15)); - Pkt.WriteString(a_Line3.substr(0, 15)); - Pkt.WriteString(a_Line4.substr(0, 15)); + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); + Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line1.c_str())); + Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line2.c_str())); + Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line3.c_str())); + Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line4.c_str())); } @@ -1637,6 +1650,41 @@ int cProtocol180::GetParticleID(const AString & a_ParticleName) +void cProtocol180::FixItemFramePositions(int a_ObjectData, double & a_PosX, double & a_PosZ, double & a_Yaw) +{ + switch (a_ObjectData) + { + case 0: + { + a_PosZ += 1; + a_Yaw = 0; + break; + } + case 1: + { + a_PosX -= 1; + a_Yaw = 90; + break; + } + case 2: + { + a_PosZ -= 1; + a_Yaw = 180; + break; + } + case 3: + { + a_PosX += 1; + a_Yaw = 270; + break; + } + } +} + + + + + void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) { // Write the incoming data into the comm log file: @@ -2328,14 +2376,20 @@ void cProtocol180::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) void cProtocol180::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) { - HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockX); - HANDLE_READ(a_ByteBuffer, ReadBEShort, short, BlockY); - HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockZ); - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line1); - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line2); - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line3); - HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line4); - m_Client->HandleUpdateSign(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); + int BlockX, BlockY, BlockZ; + if (!a_ByteBuffer.ReadPosition(BlockX, BlockY, BlockZ)) + { + return; + } + + AString Lines[4]; + for (int i = 0; i < 4; i++) + { + HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line); + Lines[i] = Line.substr(1, Line.length() - 2); // Remove "" + } + + m_Client->HandleUpdateSign(BlockX, BlockY, BlockZ, Lines[0], Lines[1], Lines[2], Lines[3]); } @@ -3062,9 +3116,9 @@ void cProtocol180::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) case cEntity::etItemFrame: { cItemFrame & Frame = (cItemFrame &)a_Entity; - WriteByte(0xA2); + WriteByte(0xA8); WriteItem(Frame.GetItem()); - WriteByte(0x3); + WriteByte(0x09); WriteByte(Frame.GetRotation()); break; } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 2b3063556..97ab3e93c 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -141,6 +141,9 @@ public: /** The 1.8 protocol use a particle id instead of a string. This function converts the name to the id. If the name is incorrect, it returns 0. */ static int GetParticleID(const AString & a_ParticleName); + /** Minecraft 1.8 use other locations to spawn the item frame. This function converts the 1.7 positions to 1.8 positions. */ + static void FixItemFramePositions(int a_ObjectData, double & a_PosX, double & a_PosZ, double & a_Yaw); + protected: /** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */ -- cgit v1.2.3 From d815aeaefd965d58b2ed993021137de43a95958a Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 11 Sep 2014 22:21:53 +0200 Subject: 1.8: Fixed sign placing. --- src/Protocol/Protocol18x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 28fffd851..978ae7807 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -406,7 +406,7 @@ void cProtocol180::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x36); // Sign Editor Open packet - Pkt.WritePosition(a_BlockX, a_BlockX, a_BlockZ); + Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); } -- cgit v1.2.3 From 6d5a5eb665d8f13dd3e4e7c279967556b0f9fa91 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 11 Sep 2014 22:27:35 +0200 Subject: Removed GetProtocolVersion() from the protocols. --- src/Protocol/Protocol.h | 8 ++------ src/Protocol/Protocol125.cpp | 3 +-- src/Protocol/Protocol132.cpp | 2 -- src/Protocol/Protocol14x.cpp | 3 --- src/Protocol/Protocol17x.cpp | 4 +--- src/Protocol/Protocol18x.cpp | 3 +-- src/Protocol/ProtocolRecognizer.cpp | 2 +- 7 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 2b41b809c..8c9fadd1a 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -46,11 +46,11 @@ typedef unsigned char Byte; class cProtocol { public: - cProtocol(cClientHandle * a_Client, int a_ProtocolVersion) : - m_ProtocolVersion(a_ProtocolVersion), + cProtocol(cClientHandle * a_Client) : m_Client(a_Client) { } + virtual ~cProtocol() {} /// Called when client sends some data @@ -131,11 +131,7 @@ public: /// Returns the ServerID used for authentication through session.minecraft.net virtual AString GetAuthServerID(void) = 0; - /** Returns the protocol version of this protocol. */ - int GetProtocolVersion(void) const { return m_ProtocolVersion; } - protected: - int m_ProtocolVersion; cClientHandle * m_Client; cCriticalSection m_CSPacket; // Each SendXYZ() function must acquire this CS in order to send the whole packet at once diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 1d6049097..0c481024e 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -16,7 +16,6 @@ Documentation: #include "../ClientHandle.h" #include "../World.h" #include "ChunkDataSerializer.h" -#include "ProtocolRecognizer.h" #include "../Entities/Entity.h" #include "../Entities/ExpOrb.h" #include "../Mobs/Monster.h" @@ -133,7 +132,7 @@ typedef unsigned char Byte; cProtocol125::cProtocol125(cClientHandle * a_Client) : - super(a_Client, cProtocolRecognizer::PROTO_VERSION_1_2_5), + super(a_Client), m_ReceivedData(32 KiB), m_LastSentDimension(dimNotSet) { diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index 6fbc3a264..5fd2655b8 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -5,7 +5,6 @@ #include "Globals.h" #include "ChunkDataSerializer.h" -#include "ProtocolRecognizer.h" #include "Protocol132.h" #include "../Root.h" #include "../Server.h" @@ -79,7 +78,6 @@ cProtocol132::cProtocol132(cClientHandle * a_Client) : super(a_Client), m_IsEncrypted(false) { - m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_3_2; } diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp index 2d737acb4..d33314a2f 100644 --- a/src/Protocol/Protocol14x.cpp +++ b/src/Protocol/Protocol14x.cpp @@ -23,7 +23,6 @@ Implements the 1.4.x protocol classes representing these protocols: #include "../UI/Window.h" #include "../Entities/Pickup.h" #include "../Entities/FallingBlock.h" -#include "ProtocolRecognizer.h" #ifdef _MSC_VER #pragma warning(push) @@ -73,7 +72,6 @@ enum cProtocol142::cProtocol142(cClientHandle * a_Client) : super(a_Client) { - m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_4_2; } @@ -152,7 +150,6 @@ void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_Do cProtocol146::cProtocol146(cClientHandle * a_Client) : super(a_Client) { - m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_4_6; } diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 2b0c8baf8..b3c78a8ba 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -12,7 +12,6 @@ Implements the 1.7.x protocol classes: #include "Globals.h" #include "json/json.h" #include "Protocol17x.h" -#include "ProtocolRecognizer.h" #include "ChunkDataSerializer.h" #include "PolarSSL++/Sha1Checksum.h" @@ -93,7 +92,7 @@ extern bool g_ShouldLogCommIn, g_ShouldLogCommOut; // cProtocol172: cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : - super(a_Client, cProtocolRecognizer::PROTO_VERSION_1_7_2), + super(a_Client), m_ServerAddress(a_ServerAddress), m_ServerPort(a_ServerPort), m_State(a_State), @@ -3064,7 +3063,6 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity) cProtocol176::cProtocol176(cClientHandle * a_Client, const AString &a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : super(a_Client, a_ServerAddress, a_ServerPort, a_State) { - m_ProtocolVersion = cProtocolRecognizer::PROTO_VERSION_1_7_6; } diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 978ae7807..142cae6a5 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -11,7 +11,6 @@ Implements the 1.8.x protocol classes: #include "Globals.h" #include "json/json.h" #include "Protocol18x.h" -#include "ProtocolRecognizer.h" #include "ChunkDataSerializer.h" #include "PolarSSL++/Sha1Checksum.h" @@ -92,7 +91,7 @@ extern bool g_ShouldLogCommIn, g_ShouldLogCommOut; // cProtocol180: cProtocol180::cProtocol180(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : - super(a_Client, cProtocolRecognizer::PROTO_VERSION_1_8_0), + super(a_Client), m_ServerAddress(a_ServerAddress), m_ServerPort(a_ServerPort), m_State(a_State), diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index cf63583db..28b2b9c4b 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -26,7 +26,7 @@ cProtocolRecognizer::cProtocolRecognizer(cClientHandle * a_Client) : - super(a_Client, 0), + super(a_Client), m_Protocol(NULL), m_Buffer(512) { -- cgit v1.2.3 From c7044fa1dd77a04c57780443a5dc88165c2d2ca1 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 11 Sep 2014 23:17:27 +0200 Subject: 1.8: Fixed inventory open packet. --- src/Protocol/Protocol18x.cpp | 5 ++--- src/UI/Window.cpp | 28 ++++++++++++++++++++++++++++ src/UI/Window.h | 3 ++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 142cae6a5..04af848dc 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1515,10 +1515,9 @@ void cProtocol180::SendWindowOpen(const cWindow & a_Window) cPacketizer Pkt(*this, 0x2d); Pkt.WriteChar(a_Window.GetWindowID()); - Pkt.WriteChar(a_Window.GetWindowType()); - Pkt.WriteString(a_Window.GetWindowTitle()); + Pkt.WriteString(a_Window.GetWindowTypeName()); + Pkt.WriteString(Printf("{\"text\":\"%s\"}", a_Window.GetWindowTitle().c_str())); Pkt.WriteChar(a_Window.GetNumNonInventorySlots()); - Pkt.WriteBool(true); if (a_Window.GetWindowType() == cWindow::wtAnimalChest) { Pkt.WriteInt(0); // TODO: The animal's EntityID diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index 66900269f..1b7b07f77 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -57,6 +57,34 @@ cWindow::~cWindow() +const AString cWindow::GetWindowTypeName(void) const +{ + switch (m_WindowType) + { + case wtChest: return "minecraft:chest"; + case wtWorkbench: return "minecraft:crafting_table"; + case wtFurnace: return "minecraft:furnace"; + case wtDropSpenser: return "minecraft:dispenser"; + case wtEnchantment: return "minecraft:enchanting_table"; + case wtBrewery: return "minecraft:brewing_stand"; + case wtNPCTrade: return "minecraft:villager"; + case wtBeacon: return "minecraft:beacon"; + case wtAnvil: return "minecraft:anvil"; + case wtHopper: return "minecraft:hopper"; + case wtDropper: return "minecraft:dropper"; + case wtAnimalChest: return "EntityHorse"; + default: + { + ASSERT(!"Unknown inventory type!"); + return ""; + } + } +} + + + + + int cWindow::GetNumSlots(void) const { int res = 0; diff --git a/src/UI/Window.h b/src/UI/Window.h index 3d860407f..bc5becf11 100644 --- a/src/UI/Window.h +++ b/src/UI/Window.h @@ -63,7 +63,7 @@ public: wtBeacon = 7, wtAnvil = 8, wtHopper = 9, - // Unknown: 10 + wtDropper = 10, wtAnimalChest = 11, }; @@ -76,6 +76,7 @@ public: char GetWindowID(void) const { return m_WindowID; } // tolua_export int GetWindowType(void) const { return m_WindowType; } // tolua_export + const AString GetWindowTypeName(void) const; // tolua_export cWindowOwner * GetOwner(void) { return m_Owner; } void SetOwner( cWindowOwner * a_Owner) { m_Owner = a_Owner; } -- cgit v1.2.3 From a02d96d1f574ed08a50129413fca71154354b300 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 00:36:46 +0200 Subject: 1.8: Fixed enderman spawning. --- src/Protocol/Protocol18x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 04af848dc..abc9f7e60 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -3223,7 +3223,7 @@ void cProtocol180::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) case cMonster::mtEnderman: { - WriteByte(0x10); + WriteByte(0x30); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); WriteByte(0x11); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); -- cgit v1.2.3 From e10237fb4dc7e9c9c3d0a67cfd2672fbb1d9083d Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 00:41:07 +0200 Subject: 1.8: Enderman, byte -> short --- src/Protocol/Protocol18x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index abc9f7e60..154da212c 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -3224,7 +3224,7 @@ void cProtocol180::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) case cMonster::mtEnderman: { WriteByte(0x30); - WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); + WriteShort((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); WriteByte(0x11); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); WriteByte(0x12); -- cgit v1.2.3 From 85ec697d32c3e5a4b2e711c25c6f836a0a948419 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 01:15:21 +0200 Subject: 1.8: Fixed workbench, enchanting and anvil window. --- src/Protocol/Protocol18x.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 154da212c..ba39bb3e6 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1506,18 +1506,34 @@ void cProtocol180::SendWindowClose(const cWindow & a_Window) void cProtocol180::SendWindowOpen(const cWindow & a_Window) { ASSERT(m_State == 3); // In game mode? - + if (a_Window.GetWindowType() < 0) { // Do not send this packet for player inventory windows return; } - + cPacketizer Pkt(*this, 0x2d); Pkt.WriteChar(a_Window.GetWindowID()); Pkt.WriteString(a_Window.GetWindowTypeName()); Pkt.WriteString(Printf("{\"text\":\"%s\"}", a_Window.GetWindowTitle().c_str())); - Pkt.WriteChar(a_Window.GetNumNonInventorySlots()); + + switch (a_Window.GetWindowType()) + { + case cWindow::wtWorkbench: + case cWindow::wtEnchantment: + case cWindow::wtAnvil: + { + Pkt.WriteChar(0); + break; + } + default: + { + Pkt.WriteChar(a_Window.GetNumNonInventorySlots()); + break; + } + } + if (a_Window.GetWindowType() == cWindow::wtAnimalChest) { Pkt.WriteInt(0); // TODO: The animal's EntityID -- cgit v1.2.3 From 4e2d75bde56a8c0913006b5978ff418ea042ef0b Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 01:37:19 +0200 Subject: 1.8: Fixed eating. --- src/ClientHandle.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 3b32b06b9..2bffc3cb1 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1207,6 +1207,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e if ( (a_BlockFace != BLOCK_FACE_NONE) && // The client is interacting with a specific block + IsValidBlock(a_HeldItem.m_ItemType) && ((Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() >= 5) ) { -- cgit v1.2.3 From 8151c79a875a327e364def4960527514ee584136 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 01:44:20 +0200 Subject: 1.8: Fixed block entities. --- src/Protocol/Protocol18x.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index ba39bb3e6..4d74995db 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1403,9 +1403,7 @@ void cProtocol180::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x35); // Update tile entity packet - Pkt.WriteInt(a_BlockEntity.GetPosX()); - Pkt.WriteShort(a_BlockEntity.GetPosY()); - Pkt.WriteInt(a_BlockEntity.GetPosZ()); + Pkt.WritePosition(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), a_BlockEntity.GetPosZ()); Byte Action = 0; switch (a_BlockEntity.GetBlockType()) @@ -2995,11 +2993,7 @@ void cProtocol180::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt } Writer.Finish(); - - AString Compressed; - CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); - WriteShort((short)Compressed.size()); - WriteBuf(Compressed.data(), Compressed.size()); + WriteBuf(Writer.GetResult().data(), Writer.GetResult().size()); } -- cgit v1.2.3 From eb19eff5ac46515360b3af0647135c5460342ed7 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 02:00:28 +0200 Subject: 1.8: Added difficulty sending --- src/Protocol/Protocol18x.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 4d74995db..59852227c 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -665,6 +665,12 @@ void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) cPacketizer Pkt(*this, 0x05); // Spawn Position packet Pkt.WritePosition(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); } + + // Send the server difficulty: + { + cPacketizer Pkt(*this, 0x41); + Pkt.WriteChar(1); + } // Send player abilities: SendPlayerAbilities(); -- cgit v1.2.3 From 34bcd3dd589cca6d525633ad4445ec7700578995 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 02:42:04 +0200 Subject: 1.8: Fixed ReadItem() --- src/ByteBuffer.cpp | 2 +- src/Protocol/Protocol18x.cpp | 58 +++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index 94684afb8..851c63858 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -267,7 +267,7 @@ size_t cByteBuffer::GetReadableSpace(void) const } // Single readable space partition: ASSERT(m_WritePos >= m_ReadPos); - return m_WritePos - m_ReadPos ; + return m_WritePos - m_ReadPos; } diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 59852227c..9553dec1a 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1822,7 +1822,7 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) if (bb.GetReadableSpace() != 1) { // Read more or less than packet length, report as error - LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x, state %d. Read " SIZE_T_FMT " bytes, packet contained %u bytes", + LOGWARNING("Protocol 1.8: Wrong number of bytes read for packet 0x%x, state %d. Read " SIZE_T_FMT " bytes, packet contained %u bytes", PacketType, m_State, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen ); @@ -2594,8 +2594,11 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) // Read the metadata AString Metadata; - a_ByteBuffer.ReadAll(Metadata); - + if (a_ByteBuffer.ReadString(Metadata, a_ByteBuffer.GetReadableSpace() - 1)) + { + return false; + } + ParseItemMetadata(a_Item, Metadata); return true; } @@ -2781,37 +2784,54 @@ void cProtocol180::AddChatPartStyle(Json::Value & a_Value, const AString & a_Par cProtocol180::cPacketizer::~cPacketizer() { - AString DataToSend; - - // Send the packet length UInt32 PacketLen = (UInt32)m_Out.GetUsedSpace(); + AString PacketData, CompressedPacket; + m_Out.ReadAll(PacketData); + m_Out.CommitRead(); - if (m_Protocol.m_State == 3) + if ((m_Protocol.m_State == 3) && (PacketLen >= 256)) + { + if (!cProtocol180::CompressPacket(PacketData, CompressedPacket)) + { + return; + } + } + else if (m_Protocol.m_State == 3) { m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen + 1); m_Protocol.m_OutPacketLenBuffer.WriteVarInt(0); + + AString LengthData; + m_Protocol.m_OutPacketLenBuffer.ReadAll(LengthData); + m_Protocol.SendData(LengthData.data(), LengthData.size()); } else { m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen); + + AString LengthData; + m_Protocol.m_OutPacketLenBuffer.ReadAll(LengthData); + m_Protocol.SendData(LengthData.data(), LengthData.size()); } - m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend); - m_Protocol.SendData(DataToSend.data(), DataToSend.size()); - m_Protocol.m_OutPacketLenBuffer.CommitRead(); - - // Send the packet data: - m_Out.ReadAll(DataToSend); - m_Protocol.SendData(DataToSend.data(), DataToSend.size()); - m_Out.CommitRead(); - + + if (CompressedPacket.empty()) + { + m_Protocol.m_OutPacketLenBuffer.CommitRead(); + m_Protocol.SendData(PacketData.data(), PacketData.size()); + } + else + { + m_Protocol.SendData(CompressedPacket.data(), CompressedPacket.size()); + } + // Log the comm into logfile: if (g_ShouldLogCommOut) { AString Hex; - ASSERT(DataToSend.size() > 0); - CreateHexDump(Hex, DataToSend.data() + 1, DataToSend.size() - 1, 16); + ASSERT(PacketData.size() > 0); + CreateHexDump(Hex, PacketData.data() + 1, PacketData.size() - 1, 16); m_Protocol.m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload:\n%s\n", - DataToSend[0], DataToSend[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str() + PacketData[0], PacketData[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str() ); } } -- cgit v1.2.3 From 0d34fc9f31f6b4eabcc52236b7c2c0f6b9139041 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 13:01:23 +0200 Subject: Fixed wrong buffer length in the 1.8 protocol. --- src/Protocol/Protocol18x.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 9553dec1a..735700dda 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1753,7 +1753,7 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) m_ReceivedData.ResetRead(); break; } - cByteBuffer bb(PacketLen + 1); + cByteBuffer bb(PacketLen); VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); m_ReceivedData.CommitRead(); @@ -1819,7 +1819,7 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) return; } - if (bb.GetReadableSpace() != 1) + if (bb.GetReadableSpace() != 0) { // Read more or less than packet length, report as error LOGWARNING("Protocol 1.8: Wrong number of bytes read for packet 0x%x, state %d. Read " SIZE_T_FMT " bytes, packet contained %u bytes", @@ -2334,10 +2334,7 @@ void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); AString Data; - if (!a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1)) - { - return; - } + a_ByteBuffer.ReadAll(Data); m_Client->HandlePluginMessage(Channel, Data); } @@ -2594,10 +2591,7 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) // Read the metadata AString Metadata; - if (a_ByteBuffer.ReadString(Metadata, a_ByteBuffer.GetReadableSpace() - 1)) - { - return false; - } + a_ByteBuffer.ReadAll(Metadata); ParseItemMetadata(a_Item, Metadata); return true; -- cgit v1.2.3 From f2c5d8a7615ca46f1894ae5ad651a92cee421a18 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 12 Sep 2014 13:19:33 +0200 Subject: Fixed many right click issues. --- src/ClientHandle.cpp | 14 ++++++++++---- src/Items/ItemHoe.h | 10 +++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 2bffc3cb1..642a5246a 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1204,15 +1204,16 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e ); cWorld * World = m_Player->GetWorld(); + bool AreRealCoords = (Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() <= 5; if ( (a_BlockFace != BLOCK_FACE_NONE) && // The client is interacting with a specific block IsValidBlock(a_HeldItem.m_ItemType) && - ((Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() >= 5) + !AreRealCoords ) { AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - if ((a_BlockX >= 0) && (a_BlockY >= 0) && (a_BlockZ >= 0)) + if ((a_BlockX != -1) && (a_BlockY >= 0) && (a_BlockZ != -1)) { World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); if (a_BlockY < cChunkDef::Height - 1) @@ -1228,11 +1229,16 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e return; } + if (!AreRealCoords) + { + a_BlockFace = BLOCK_FACE_NONE; + } + cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); if (PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ)) { // A plugin doesn't agree with the action, replace the block on the client and quit: - if ((a_BlockX >= 0) && (a_BlockY >= 0) && (a_BlockZ >= 0)) + if (AreRealCoords) { cChunkInterface ChunkInterface(World->GetChunkMap()); BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); @@ -1278,7 +1284,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e return; } - if ((Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() <= 5) + if (AreRealCoords) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; diff --git a/src/Items/ItemHoe.h b/src/Items/ItemHoe.h index 8d0b71478..987357739 100644 --- a/src/Items/ItemHoe.h +++ b/src/Items/ItemHoe.h @@ -18,11 +18,15 @@ public: { } - virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override + virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override { - BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + if (a_Dir == BLOCK_FACE_NONE) + { + return false; + } - if ((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS)) + BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + if (IsBlockTypeOfDirt(Block)) { a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, 0); a_Player->UseEquippedItem(); -- cgit v1.2.3 From 7f42ba9fc117674635a840b860f0d3a6de818b99 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Fri, 12 Sep 2014 16:48:37 +0200 Subject: Fixed 1.8 Item stacking and block harvesting --- src/BlockID.h | 2 +- src/Items/ItemHandler.cpp | 68 ++++++++++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/BlockID.h b/src/BlockID.h index 5f2ff15cc..45e71d85d 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -385,7 +385,7 @@ enum ENUM_ITEM_ID E_ITEM_RAW_RABBIT = 411, E_ITEM_COOKED_RABBIT = 412, E_ITEM_RABBIT_STEW = 413, - E_ITEM_RABBITS_FOOD = 414, + E_ITEM_RABBITS_FOOT = 414, E_ITEM_RABBIT_HIDE = 415, E_ITEM_ARMOR_STAND = 416, E_ITEM_IRON_HORSE_ARMOR = 417, diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index df8bb6bfa..ec5283774 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -399,8 +399,12 @@ char cItemHandler::GetMaxStackSize(void) switch (m_ItemType) { + case E_ITEM_ACACIA_DOOR: return 64; + case E_ITEM_ARMOR_STAND: return 16; case E_ITEM_ARROW: return 64; case E_ITEM_BAKED_POTATO: return 64; + case E_ITEM_BANNER: return 16; + case E_ITEM_BIRCH_DOOR: return 64; case E_ITEM_BLAZE_POWDER: return 64; case E_ITEM_BLAZE_ROD: return 64; case E_ITEM_BONE: return 64; @@ -411,7 +415,6 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_BREWING_STAND: return 64; case E_ITEM_BUCKET: return 16; case E_ITEM_CARROT: return 64; - case E_ITEM_CAKE: return 1; case E_ITEM_CAULDRON: return 64; case E_ITEM_CLAY: return 64; case E_ITEM_CLAY_BRICK: return 64; @@ -422,7 +425,9 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_COOKED_CHICKEN: return 64; case E_ITEM_COOKED_FISH: return 64; case E_ITEM_COOKED_PORKCHOP: return 64; + case E_ITEM_COOKED_MUTTON: return 64; case E_ITEM_COOKIE: return 64; + case E_ITEM_DARK_OAK_DOOR: return 64; case E_ITEM_DIAMOND: return 64; case E_ITEM_DYE: return 64; case E_ITEM_EGG: return 16; @@ -446,6 +451,7 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_GOLD_NUGGET: return 64; case E_ITEM_GUNPOWDER: return 64; case E_ITEM_HEAD: return 64; + case E_ITEM_JUNGLE_DOOR: return 64; case E_ITEM_IRON: return 64; case E_ITEM_ITEM_FRAME: return 64; case E_ITEM_LEATHER: return 64; @@ -459,11 +465,16 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_PAPER: return 64; case E_ITEM_POISONOUS_POTATO: return 64; case E_ITEM_POTATO: return 64; + case E_ITEM_PRISMARINE_CRYSTALS: return 64; + case E_ITEM_PRISMARINE_SHARD: return 64; case E_ITEM_PUMPKIN_PIE: return 64; case E_ITEM_PUMPKIN_SEEDS: return 64; + case E_ITEM_RABBITS_FOOT: return 64; + case E_ITEM_RABBIT_HIDE: return 64; case E_ITEM_RAW_BEEF: return 64; case E_ITEM_RAW_CHICKEN: return 64; case E_ITEM_RAW_FISH: return 64; + case E_ITEM_RAW_MUTTON: return 64; case E_ITEM_RAW_PORKCHOP: return 64; case E_ITEM_RED_APPLE: return 64; case E_ITEM_REDSTONE_DUST: return 64; @@ -475,6 +486,7 @@ char cItemHandler::GetMaxStackSize(void) case E_ITEM_SNOWBALL: return 16; case E_ITEM_SPAWN_EGG: return 64; case E_ITEM_SPIDER_EYE: return 64; + case E_ITEM_SPRUCE_DOOR: return 64; case E_ITEM_STEAK: return 64; case E_ITEM_STICK: return 64; case E_ITEM_STRING: return 64; @@ -553,43 +565,49 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) switch (a_BlockType) { 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_END_STONE: - 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_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_STONE_BRICK_STAIRS: - case E_BLOCK_NETHER_BRICK_STAIRS: - case E_BLOCK_CAULDRON: - case E_BLOCK_OBSIDIAN: case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_DIAMOND_ORE: + case E_BLOCK_DOUBLE_STONE_SLAB: + case E_BLOCK_EMERALD_ORE: + case E_BLOCK_ENCHANTMENT_TABLE: + case E_BLOCK_END_STONE: + case E_BLOCK_FURNACE: 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: case E_BLOCK_IRON_BLOCK: case E_BLOCK_IRON_ORE: - case E_BLOCK_LAPIS_ORE: + case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_LAPIS_BLOCK: + case E_BLOCK_LAPIS_ORE: + case E_BLOCK_LIT_FURNACE: + case E_BLOCK_MOSSY_COBBLESTONE: + case E_BLOCK_NETHER_BRICK: + case E_BLOCK_NETHER_BRICK_STAIRS: + case E_BLOCK_NETHER_BRICK_FENCE: + 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: + case E_BLOCK_REDSTONE_ORE: + case E_BLOCK_REDSTONE_ORE_GLOWING: + case E_BLOCK_SANDSTONE_STAIRS: + case E_BLOCK_SANDSTONE: case E_BLOCK_SNOW: + case E_BLOCK_STONE: + case E_BLOCK_STONE_BRICKS: + case E_BLOCK_STONE_BRICK_STAIRS: + case E_BLOCK_STONE_PRESSURE_PLATE: + case E_BLOCK_STONE_SLAB: case E_BLOCK_VINES: - case E_BLOCK_PACKED_ICE: { return false; } -- cgit v1.2.3 From 5cf114da39e49353b422ac72c96724d3f6ff758e Mon Sep 17 00:00:00 2001 From: Masy98 Date: Fri, 12 Sep 2014 17:01:03 +0200 Subject: Added Sea Lantern drops --- src/Blocks/BlockHandler.cpp | 2 ++ src/Blocks/BlockSeaLantern.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/Blocks/BlockSeaLantern.h diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index a470e6b21..96ef3fbf8 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -67,6 +67,7 @@ #include "BlockTripwireHook.h" #include "BlockSand.h" #include "BlockSapling.h" +#include "BlockSeaLantern.h" #include "BlockSideways.h" #include "BlockSignPost.h" #include "BlockSlab.h" @@ -287,6 +288,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_SAND: return new cBlockSandHandler (a_BlockType); case E_BLOCK_SANDSTONE_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_SAPLING: return new cBlockSaplingHandler (a_BlockType); + case E_BLOCK_SEA_LANTERN: return new cBlockSeaLanternHandler (a_BlockType); case E_BLOCK_SIGN_POST: return new cBlockSignPostHandler (a_BlockType); case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType); case E_BLOCK_SPRUCE_DOOR: return new cBlockDoorHandler (a_BlockType); diff --git a/src/Blocks/BlockSeaLantern.h b/src/Blocks/BlockSeaLantern.h new file mode 100644 index 000000000..a9259d1d6 --- /dev/null +++ b/src/Blocks/BlockSeaLantern.h @@ -0,0 +1,30 @@ + +#pragma once + +#include "BlockHandler.h" + + + + + +class cBlockSeaLanternHandler : + public cBlockHandler +{ +public: + cBlockSeaLanternHandler(BLOCKTYPE a_BlockType) + : cBlockHandler(a_BlockType) + { + } + + + virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override + { + // Reset meta to 0 + cFastRandom Random; + a_Pickups.push_back(cItem(E_ITEM_PRISMARINE_CRYSTALS, (char)(2 + Random.NextInt(2)), 0)); + } +} ; + + + + -- cgit v1.2.3 From ad1c61c3dd7b3a2650e7e2b4f615a422f6af5ef4 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Fri, 12 Sep 2014 18:07:51 +0200 Subject: Added slime block to slime balls recipe --- MCServer/crafting.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/MCServer/crafting.txt b/MCServer/crafting.txt index 1236ab10e..8e68d5cb5 100644 --- a/MCServer/crafting.txt +++ b/MCServer/crafting.txt @@ -348,6 +348,7 @@ Emerald, 9 = EmeraldBlock, * RedstoneDust, 9 = RedstoneBlock, * Coal, 9 = CoalBlock, * Clay, 4 = ClayBlock, * +SlimeBall, 9 = SlimeBlock, * Painting = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Wool, 2:2 ItemFrame = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Leather, 2:2 -- cgit v1.2.3 From b462416e1fef58b3ddccc92f3dfe613fc27d5483 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 13 Sep 2014 02:20:04 +0200 Subject: 1.8: Fixed maps. --- src/ClientHandle.cpp | 8 ++++---- src/ClientHandle.h | 4 ++-- src/Map.cpp | 8 ++++---- src/Protocol/Protocol.h | 4 ++-- src/Protocol/Protocol125.cpp | 4 ++-- src/Protocol/Protocol125.h | 4 ++-- src/Protocol/Protocol17x.cpp | 5 ++--- src/Protocol/Protocol17x.h | 4 ++-- src/Protocol/Protocol18x.cpp | 31 +++++++++++++++---------------- src/Protocol/Protocol18x.h | 4 ++-- src/Protocol/ProtocolRecognizer.cpp | 8 ++++---- src/Protocol/ProtocolRecognizer.h | 4 ++-- 12 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 9b6151656..fa27664ef 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2337,18 +2337,18 @@ void cClientHandle::SendInventorySlot(char a_WindowID, short a_SlotNum, const cI -void cClientHandle::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) +void cClientHandle::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) { - m_Protocol->SendMapColumn(a_ID, a_X, a_Y, a_Colors, a_Length); + m_Protocol->SendMapColumn(a_ID, a_X, a_Y, a_Colors, a_Length, m_Scale); } -void cClientHandle::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators) +void cClientHandle::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) { - m_Protocol->SendMapDecorators(a_ID, a_Decorators); + m_Protocol->SendMapDecorators(a_ID, a_Decorators, m_Scale); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 7c5597b8b..27bfc756c 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -148,8 +148,8 @@ public: void SendGameMode (eGameMode a_GameMode); void SendHealth (void); void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item); - void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length); - void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators); + void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale); + 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); diff --git a/src/Map.cpp b/src/Map.cpp index 8f205a606..c106ccd83 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -432,7 +432,7 @@ void cMap::StreamNext(cMapClient & a_Client) // This is dangerous as the player object may have been destroyed before the decorator is erased from the list UpdateDecorators(); - Handle->SendMapDecorators(m_ID, m_Decorators); + Handle->SendMapDecorators(m_ID, m_Decorators, m_Scale); a_Client.m_NextDecoratorUpdate = 0; } @@ -444,7 +444,7 @@ void cMap::StreamNext(cMapClient & a_Client) const Byte * Colors = &m_Data[Y * m_Height]; - Handle->SendMapColumn(m_ID, Y, 0, Colors, m_Height); + Handle->SendMapColumn(m_ID, Y, 0, Colors, m_Height, m_Scale); } } @@ -595,10 +595,10 @@ void cMap::SendTo(cClientHandle & a_Client) { const Byte* Colors = &m_Data[i * m_Height]; - a_Client.SendMapColumn(m_ID, i, 0, Colors, m_Height); + a_Client.SendMapColumn(m_ID, i, 0, Colors, m_Height, m_Scale); } - a_Client.SendMapDecorators(m_ID, m_Decorators); + a_Client.SendMapDecorators(m_ID, m_Decorators, m_Scale); } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 8c9fadd1a..eceec4974 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -86,8 +86,8 @@ public: virtual void SendKeepAlive (int a_PingID) = 0; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) = 0; virtual void SendLoginSuccess (void) = 0; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) = 0; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) = 0; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) = 0; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) = 0; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) = 0; virtual void SendPaintingSpawn (const cPainting & a_Painting) = 0; virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 0c481024e..c785553a5 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -608,7 +608,7 @@ void cProtocol125::SendLoginSuccess(void) -void cProtocol125::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) +void cProtocol125::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) { cCSLock Lock(m_CSPacket); @@ -630,7 +630,7 @@ void cProtocol125::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colo -void cProtocol125::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators) +void cProtocol125::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) { cCSLock Lock(m_CSPacket); diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 262e1818d..4e140331a 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -57,8 +57,8 @@ public: virtual void SendKeepAlive (int a_PingID) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index eaf226841..f36ec5b49 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -715,7 +715,7 @@ void cProtocol172::SendPaintingSpawn(const cPainting & a_Painting) -void cProtocol172::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) +void cProtocol172::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) { ASSERT(m_State == 3); // In game mode? @@ -737,7 +737,7 @@ void cProtocol172::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colo -void cProtocol172::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators) +void cProtocol172::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) { ASSERT(m_State == 3); // In game mode? @@ -775,7 +775,6 @@ void cProtocol172::SendMapInfo(int a_ID, unsigned int a_Scale) - void cProtocol172::SendPickupSpawn(const cPickup & a_Pickup) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 60088a1b8..b37de1527 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -94,8 +94,8 @@ public: virtual void SendKeepAlive (int a_PingID) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 735700dda..b3cdcc7bc 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -728,18 +728,21 @@ void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) -void cProtocol180::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) +void cProtocol180::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x34); Pkt.WriteVarInt(a_ID); - Pkt.WriteShort (3 + a_Length); + Pkt.WriteByte(m_Scale); - Pkt.WriteByte(0); + Pkt.WriteVarInt(0); + Pkt.WriteByte(1); + Pkt.WriteByte(a_Length); Pkt.WriteByte(a_X); Pkt.WriteByte(a_Y); - + + Pkt.WriteVarInt(a_Length); for (unsigned int i = 0; i < a_Length; ++i) { Pkt.WriteByte(a_Colors[i]); @@ -750,22 +753,23 @@ void cProtocol180::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colo -void cProtocol180::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators) +void cProtocol180::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x34); Pkt.WriteVarInt(a_ID); - Pkt.WriteShort ((short)(1 + (3 * a_Decorators.size()))); + Pkt.WriteByte(m_Scale); + Pkt.WriteVarInt(a_Decorators.size()); - Pkt.WriteByte(1); - for (cMapDecoratorList::const_iterator it = a_Decorators.begin(); it != a_Decorators.end(); ++it) { Pkt.WriteByte((it->GetType() << 4) | (it->GetRot() & 0xf)); Pkt.WriteByte(it->GetPixelX()); Pkt.WriteByte(it->GetPixelZ()); } + + Pkt.WriteByte(0); } @@ -774,21 +778,16 @@ void cProtocol180::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decor void cProtocol180::SendMapInfo(int a_ID, unsigned int a_Scale) { - ASSERT(m_State == 3); // In game mode? - - cPacketizer Pkt(*this, 0x34); - Pkt.WriteVarInt(a_ID); - Pkt.WriteShort (2); + UNUSED(a_ID); + UNUSED(a_Scale); - Pkt.WriteByte(2); - Pkt.WriteByte(a_Scale); + // This packet was removed in 1.8 } - void cProtocol180::SendPickupSpawn(const cPickup & a_Pickup) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 97ab3e93c..70696d32d 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -89,8 +89,8 @@ public: virtual void SendKeepAlive (int a_PingID) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPickupSpawn (const cPickup & a_Pickup) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 28b2b9c4b..611ef6ce0 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -411,20 +411,20 @@ void cProtocolRecognizer::SendLoginSuccess(void) -void cProtocolRecognizer::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) +void cProtocolRecognizer::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) { ASSERT(m_Protocol != NULL); - m_Protocol->SendMapColumn(a_ID, a_X, a_Y, a_Colors, a_Length); + m_Protocol->SendMapColumn(a_ID, a_X, a_Y, a_Colors, a_Length, m_Scale); } -void cProtocolRecognizer::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators) +void cProtocolRecognizer::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) { ASSERT(m_Protocol != NULL); - m_Protocol->SendMapDecorators(a_ID, a_Decorators); + m_Protocol->SendMapDecorators(a_ID, a_Decorators, m_Scale); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index f73b0b92a..9a0169b97 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -93,8 +93,8 @@ public: virtual void SendKeepAlive (int a_PingID) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; -- cgit v1.2.3 From f323955099eb19f5ff3969d09db05f58a842b95b Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 13 Sep 2014 20:27:10 +0200 Subject: Moved chat json creating to the CompositeChat class. --- src/CompositeChat.cpp | 178 +++++++++++++++++++++++++++++++++++++++++++ src/CompositeChat.h | 6 ++ src/Protocol/Protocol17x.cpp | 173 +---------------------------------------- src/Protocol/Protocol17x.h | 4 +- src/Protocol/Protocol18x.cpp | 173 +---------------------------------------- src/Protocol/Protocol18x.h | 4 +- 6 files changed, 192 insertions(+), 346 deletions(-) diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp index 0d339021e..d1eb0b852 100644 --- a/src/CompositeChat.cpp +++ b/src/CompositeChat.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "CompositeChat.h" +#include "ClientHandle.h" @@ -399,6 +400,183 @@ void cCompositeChat::AddStyle(AString & a_Style, const AString & a_AddStyle) +AString cCompositeChat::CreateJsonString(bool a_ShouldUseChatPrefixes) const +{ + Json::Value msg; + msg["text"] = cClientHandle::FormatMessageType(a_ShouldUseChatPrefixes, GetMessageType(), GetAdditionalMessageTypeData()); // The client crashes without this field being present + const cCompositeChat::cParts & Parts = GetParts(); + for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) + { + Json::Value Part; + switch ((*itr)->m_PartType) + { + case cCompositeChat::ptText: + { + Part["text"] = (*itr)->m_Text; + AddChatPartStyle(Part, (*itr)->m_Style); + break; + } + + case cCompositeChat::ptClientTranslated: + { + const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr; + Part["translate"] = p.m_Text; + Json::Value With; + for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr) + { + With.append(*itrW); + } + if (!p.m_Parameters.empty()) + { + Part["with"] = With; + } + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptUrl: + { + const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Url; + Url["action"] = "open_url"; + Url["value"] = p.m_Url; + Part["clickEvent"] = Url; + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptSuggestCommand: + case cCompositeChat::ptRunCommand: + { + const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr; + Part["text"] = p.m_Text; + Json::Value Cmd; + Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command"; + Cmd["value"] = p.m_Command; + Part["clickEvent"] = Cmd; + AddChatPartStyle(Part, p.m_Style); + break; + } + + case cCompositeChat::ptShowAchievement: + { + const cCompositeChat::cShowAchievementPart & p = (const cCompositeChat::cShowAchievementPart &)**itr; + Part["translate"] = "chat.type.achievement"; + + Json::Value Ach; + Ach["action"] = "show_achievement"; + Ach["value"] = p.m_Text; + + Json::Value AchColourAndName; + AchColourAndName["color"] = "green"; + AchColourAndName["translate"] = p.m_Text; + AchColourAndName["hoverEvent"] = Ach; + + Json::Value Extra; + Extra.append(AchColourAndName); + + Json::Value Name; + Name["text"] = p.m_PlayerName; + + Json::Value With; + With.append(Name); + With.append(Extra); + + Part["with"] = With; + AddChatPartStyle(Part, p.m_Style); + break; + } + } + msg["extra"].append(Part); + } // for itr - Parts[] + + return msg.toStyledString(); +} + + + + + +void cCompositeChat::AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) const +{ + size_t len = a_PartStyle.length(); + for (size_t i = 0; i < len; i++) + { + switch (a_PartStyle[i]) + { + case 'b': + { + // bold + a_Value["bold"] = Json::Value(true); + break; + } + + case 'i': + { + // italic + a_Value["italic"] = Json::Value(true); + break; + } + + case 'u': + { + // Underlined + a_Value["underlined"] = Json::Value(true); + break; + } + + case 's': + { + // strikethrough + a_Value["strikethrough"] = Json::Value(true); + break; + } + + case 'o': + { + // obfuscated + a_Value["obfuscated"] = Json::Value(true); + break; + } + + case '@': + { + // Color, specified by the next char: + i++; + if (i >= len) + { + // String too short, didn't contain a color + break; + } + switch (a_PartStyle[i]) + { + case '0': a_Value["color"] = Json::Value("black"); break; + case '1': a_Value["color"] = Json::Value("dark_blue"); break; + case '2': a_Value["color"] = Json::Value("dark_green"); break; + case '3': a_Value["color"] = Json::Value("dark_aqua"); break; + case '4': a_Value["color"] = Json::Value("dark_red"); break; + case '5': a_Value["color"] = Json::Value("dark_purple"); break; + case '6': a_Value["color"] = Json::Value("gold"); break; + case '7': a_Value["color"] = Json::Value("gray"); break; + case '8': a_Value["color"] = Json::Value("dark_gray"); break; + case '9': a_Value["color"] = Json::Value("blue"); break; + case 'a': a_Value["color"] = Json::Value("green"); break; + case 'b': a_Value["color"] = Json::Value("aqua"); break; + case 'c': a_Value["color"] = Json::Value("red"); break; + case 'd': a_Value["color"] = Json::Value("light_purple"); break; + case 'e': a_Value["color"] = Json::Value("yellow"); break; + case 'f': a_Value["color"] = Json::Value("white"); break; + } // switch (color) + } // case '@' + } // switch (Style[i]) + } // for i - a_PartStyle[] +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cCompositeChat::cBasePart: diff --git a/src/CompositeChat.h b/src/CompositeChat.h index 2dc21b98f..369eed196 100644 --- a/src/CompositeChat.h +++ b/src/CompositeChat.h @@ -4,6 +4,7 @@ // Declares the cCompositeChat class used to wrap a chat message with multiple parts (text, url, cmd) #include "Defines.h" +#include "json/json.h" @@ -189,6 +190,8 @@ public: Used for older protocols that don't support composite chat and for console-logging. */ AString ExtractText(void) const; + + AString CreateJsonString(bool a_ShouldUseChatPrefixes = true) const; // tolua_end @@ -197,6 +200,9 @@ public: /** Converts the MessageType to a LogLevel value. Used by the logging bindings when logging a cCompositeChat object. */ static cLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType); + + /** Adds the chat part's style (represented by the part's stylestring) into the Json object. */ + void AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) const; protected: /** All the parts that */ diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f36ec5b49..f51f15ec2 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -239,101 +239,13 @@ void cProtocol172::SendChat(const AString & a_Message) void cProtocol172::SendChat(const cCompositeChat & a_Message) { ASSERT(m_State == 3); // In game mode? - - // Compose the complete Json string to send: - Json::Value msg; + cWorld * World = m_Client->GetPlayer()->GetWorld(); - msg["text"] = cClientHandle::FormatMessageType((World == NULL) ? false : World->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present - const cCompositeChat::cParts & Parts = a_Message.GetParts(); - for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) - { - Json::Value Part; - switch ((*itr)->m_PartType) - { - case cCompositeChat::ptText: - { - Part["text"] = (*itr)->m_Text; - AddChatPartStyle(Part, (*itr)->m_Style); - break; - } - - case cCompositeChat::ptClientTranslated: - { - const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr; - Part["translate"] = p.m_Text; - Json::Value With; - for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr) - { - With.append(*itrW); - } - if (!p.m_Parameters.empty()) - { - Part["with"] = With; - } - AddChatPartStyle(Part, p.m_Style); - break; - } - - case cCompositeChat::ptUrl: - { - const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr; - Part["text"] = p.m_Text; - Json::Value Url; - Url["action"] = "open_url"; - Url["value"] = p.m_Url; - Part["clickEvent"] = Url; - AddChatPartStyle(Part, p.m_Style); - break; - } - - case cCompositeChat::ptSuggestCommand: - case cCompositeChat::ptRunCommand: - { - const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr; - Part["text"] = p.m_Text; - Json::Value Cmd; - Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command"; - Cmd["value"] = p.m_Command; - Part["clickEvent"] = Cmd; - AddChatPartStyle(Part, p.m_Style); - break; - } + bool ShouldUseChatPrefixes = (World == NULL) ? false : World->ShouldUseChatPrefixes(); - case cCompositeChat::ptShowAchievement: - { - const cCompositeChat::cShowAchievementPart & p = (const cCompositeChat::cShowAchievementPart &)**itr; - Part["translate"] = "chat.type.achievement"; - - Json::Value Ach; - Ach["action"] = "show_achievement"; - Ach["value"] = p.m_Text; - - Json::Value AchColourAndName; - AchColourAndName["color"] = "green"; - AchColourAndName["translate"] = p.m_Text; - AchColourAndName["hoverEvent"] = Ach; - - Json::Value Extra; - Extra.append(AchColourAndName); - - Json::Value Name; - Name["text"] = p.m_PlayerName; - - Json::Value With; - With.append(Name); - With.append(Extra); - - Part["with"] = With; - AddChatPartStyle(Part, p.m_Style); - break; - } - } - msg["extra"].append(Part); - } // for itr - Parts[] - // Send the message to the client: cPacketizer Pkt(*this, 0x02); - Pkt.WriteString(msg.toStyledString()); + Pkt.WriteString(a_Message.CreateJsonString(ShouldUseChatPrefixes)); } @@ -2427,85 +2339,6 @@ void cProtocol172::StartEncryption(const Byte * a_Key) -void cProtocol172::AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) -{ - size_t len = a_PartStyle.length(); - for (size_t i = 0; i < len; i++) - { - switch (a_PartStyle[i]) - { - case 'b': - { - // bold - a_Value["bold"] = Json::Value(true); - break; - } - - case 'i': - { - // italic - a_Value["italic"] = Json::Value(true); - break; - } - - case 'u': - { - // Underlined - a_Value["underlined"] = Json::Value(true); - break; - } - - case 's': - { - // strikethrough - a_Value["strikethrough"] = Json::Value(true); - break; - } - - case 'o': - { - // obfuscated - a_Value["obfuscated"] = Json::Value(true); - break; - } - - case '@': - { - // Color, specified by the next char: - i++; - if (i >= len) - { - // String too short, didn't contain a color - break; - } - switch (a_PartStyle[i]) - { - case '0': a_Value["color"] = Json::Value("black"); break; - case '1': a_Value["color"] = Json::Value("dark_blue"); break; - case '2': a_Value["color"] = Json::Value("dark_green"); break; - case '3': a_Value["color"] = Json::Value("dark_aqua"); break; - case '4': a_Value["color"] = Json::Value("dark_red"); break; - case '5': a_Value["color"] = Json::Value("dark_purple"); break; - case '6': a_Value["color"] = Json::Value("gold"); break; - case '7': a_Value["color"] = Json::Value("gray"); break; - case '8': a_Value["color"] = Json::Value("dark_gray"); break; - case '9': a_Value["color"] = Json::Value("blue"); break; - case 'a': a_Value["color"] = Json::Value("green"); break; - case 'b': a_Value["color"] = Json::Value("aqua"); break; - case 'c': a_Value["color"] = Json::Value("red"); break; - case 'd': a_Value["color"] = Json::Value("light_purple"); break; - case 'e': a_Value["color"] = Json::Value("yellow"); break; - case 'f': a_Value["color"] = Json::Value("white"); break; - } // switch (color) - } // case '@' - } // switch (Style[i]) - } // for i - a_PartStyle[] -} - - - - - //////////////////////////////////////////////////////////////////////////////// // cProtocol172::cPacketizer: diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index b37de1527..6668d0a87 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -307,9 +307,7 @@ protected: void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); void StartEncryption(const Byte * a_Key); - - /** Adds the chat part's style (represented by the part's stylestring) into the Json object. */ - void AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle); + } ; diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index b3cdcc7bc..5023acf2d 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -231,101 +231,13 @@ void cProtocol180::SendChat(const AString & a_Message) void cProtocol180::SendChat(const cCompositeChat & a_Message) { ASSERT(m_State == 3); // In game mode? - - // Compose the complete Json string to send: - Json::Value msg; + cWorld * World = m_Client->GetPlayer()->GetWorld(); - msg["text"] = cClientHandle::FormatMessageType((World == NULL) ? false : World->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present - const cCompositeChat::cParts & Parts = a_Message.GetParts(); - for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) - { - Json::Value Part; - switch ((*itr)->m_PartType) - { - case cCompositeChat::ptText: - { - Part["text"] = (*itr)->m_Text; - AddChatPartStyle(Part, (*itr)->m_Style); - break; - } - - case cCompositeChat::ptClientTranslated: - { - const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr; - Part["translate"] = p.m_Text; - Json::Value With; - for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr) - { - With.append(*itrW); - } - if (!p.m_Parameters.empty()) - { - Part["with"] = With; - } - AddChatPartStyle(Part, p.m_Style); - break; - } - - case cCompositeChat::ptUrl: - { - const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr; - Part["text"] = p.m_Text; - Json::Value Url; - Url["action"] = "open_url"; - Url["value"] = p.m_Url; - Part["clickEvent"] = Url; - AddChatPartStyle(Part, p.m_Style); - break; - } - - case cCompositeChat::ptSuggestCommand: - case cCompositeChat::ptRunCommand: - { - const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr; - Part["text"] = p.m_Text; - Json::Value Cmd; - Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command"; - Cmd["value"] = p.m_Command; - Part["clickEvent"] = Cmd; - AddChatPartStyle(Part, p.m_Style); - break; - } + bool ShouldUseChatPrefixes = (World == NULL) ? false : World->ShouldUseChatPrefixes(); - case cCompositeChat::ptShowAchievement: - { - const cCompositeChat::cShowAchievementPart & p = (const cCompositeChat::cShowAchievementPart &)**itr; - Part["translate"] = "chat.type.achievement"; - - Json::Value Ach; - Ach["action"] = "show_achievement"; - Ach["value"] = p.m_Text; - - Json::Value AchColourAndName; - AchColourAndName["color"] = "green"; - AchColourAndName["translate"] = p.m_Text; - AchColourAndName["hoverEvent"] = Ach; - - Json::Value Extra; - Extra.append(AchColourAndName); - - Json::Value Name; - Name["text"] = p.m_PlayerName; - - Json::Value With; - With.append(Name); - With.append(Extra); - - Part["with"] = With; - AddChatPartStyle(Part, p.m_Style); - break; - } - } - msg["extra"].append(Part); - } // for itr - Parts[] - // Send the message to the client: cPacketizer Pkt(*this, 0x02); - Pkt.WriteString(msg.toStyledString()); + Pkt.WriteString(a_Message.CreateJsonString(ShouldUseChatPrefixes)); Pkt.WriteChar(0); } @@ -2693,85 +2605,6 @@ void cProtocol180::StartEncryption(const Byte * a_Key) -void cProtocol180::AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) -{ - size_t len = a_PartStyle.length(); - for (size_t i = 0; i < len; i++) - { - switch (a_PartStyle[i]) - { - case 'b': - { - // bold - a_Value["bold"] = Json::Value(true); - break; - } - - case 'i': - { - // italic - a_Value["italic"] = Json::Value(true); - break; - } - - case 'u': - { - // Underlined - a_Value["underlined"] = Json::Value(true); - break; - } - - case 's': - { - // strikethrough - a_Value["strikethrough"] = Json::Value(true); - break; - } - - case 'o': - { - // obfuscated - a_Value["obfuscated"] = Json::Value(true); - break; - } - - case '@': - { - // Color, specified by the next char: - i++; - if (i >= len) - { - // String too short, didn't contain a color - break; - } - switch (a_PartStyle[i]) - { - case '0': a_Value["color"] = Json::Value("black"); break; - case '1': a_Value["color"] = Json::Value("dark_blue"); break; - case '2': a_Value["color"] = Json::Value("dark_green"); break; - case '3': a_Value["color"] = Json::Value("dark_aqua"); break; - case '4': a_Value["color"] = Json::Value("dark_red"); break; - case '5': a_Value["color"] = Json::Value("dark_purple"); break; - case '6': a_Value["color"] = Json::Value("gold"); break; - case '7': a_Value["color"] = Json::Value("gray"); break; - case '8': a_Value["color"] = Json::Value("dark_gray"); break; - case '9': a_Value["color"] = Json::Value("blue"); break; - case 'a': a_Value["color"] = Json::Value("green"); break; - case 'b': a_Value["color"] = Json::Value("aqua"); break; - case 'c': a_Value["color"] = Json::Value("red"); break; - case 'd': a_Value["color"] = Json::Value("light_purple"); break; - case 'e': a_Value["color"] = Json::Value("yellow"); break; - case 'f': a_Value["color"] = Json::Value("white"); break; - } // switch (color) - } // case '@' - } // switch (Style[i]) - } // for i - a_PartStyle[] -} - - - - - //////////////////////////////////////////////////////////////////////////////// // cProtocol180::cPacketizer: diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 70696d32d..7ba2b92cd 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -324,9 +324,7 @@ protected: void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); void StartEncryption(const Byte * a_Key); - - /** Adds the chat part's style (represented by the part's stylestring) into the Json object. */ - void AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle); + } ; -- cgit v1.2.3 From 94d562502dd7abf65fa471666c46568609db1e7e Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 13 Sep 2014 21:48:16 +0200 Subject: 1.8: Updated scoreboard packets. --- src/Protocol/Protocol18x.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 5023acf2d..54dea049b 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1035,8 +1035,12 @@ void cProtocol180::SendScoreboardObjective(const AString & a_Name, const AString cPacketizer Pkt(*this, 0x3b); Pkt.WriteString(a_Name); - Pkt.WriteString(a_DisplayName); Pkt.WriteByte(a_Mode); + if ((a_Mode == 0) || (a_Mode == 2)) + { + Pkt.WriteString(a_DisplayName); + Pkt.WriteString("integer"); + } } @@ -1050,11 +1054,11 @@ void cProtocol180::SendScoreUpdate(const AString & a_Objective, const AString & cPacketizer Pkt(*this, 0x3c); Pkt.WriteString(a_Player); Pkt.WriteByte(a_Mode); + Pkt.WriteString(a_Objective); if (a_Mode != 1) { - Pkt.WriteString(a_Objective); - Pkt.WriteInt((int) a_Score); + Pkt.WriteVarInt((UInt32) a_Score); } } -- cgit v1.2.3 From 382a42b3d6a5b1808ad9c8bfe1494ad44676c14b Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 14 Sep 2014 14:24:28 +0200 Subject: Fixed warnings. --- src/Protocol/ChunkDataSerializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index 268cf4a9f..61df24c31 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -192,8 +192,8 @@ void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_Chu { BLOCKTYPE BlockType = m_BlockTypes[Index] & 0xFF; NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; - Blocks[LastOffset] = (BlockType << 4) | ((unsigned char)BlockMeta); - Blocks[LastOffset + 1] = (unsigned char)BlockType >> 4; + Blocks[LastOffset] = (unsigned char)(BlockType << 4) | BlockMeta; + Blocks[LastOffset + 1] = (unsigned char)(BlockType >> 4); LastOffset += 2; } @@ -215,7 +215,7 @@ void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_Chu Packet.WriteBEInt(a_ChunkX); Packet.WriteBEInt(a_ChunkZ); Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag - Packet.WriteBEShort(0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff + Packet.WriteBEShort((short) 0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff Packet.WriteVarInt(DataSize); // Chunk size Packet.WriteBuf(AllData, DataSize); // Chunk data -- cgit v1.2.3 From 63142a7eb151ef8ae3842406366f65ec67d3d0d2 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 14 Sep 2014 20:08:18 +0200 Subject: Simplified WriteUUID() --- src/Protocol/Protocol18x.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 54dea049b..837c8ec99 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1573,6 +1573,7 @@ int cProtocol180::GetParticleID(const AString & a_ParticleName) if (ParticleMap.find(ParticleName) == ParticleMap.end()) { LOGWARNING("Unknown particle: %s", a_ParticleName.c_str()); + ASSERT(!"Unknown particle"); return 0; } @@ -2672,20 +2673,19 @@ cProtocol180::cPacketizer::~cPacketizer() void cProtocol180::cPacketizer::WriteUUID(const AString & a_UUID) { - AString UUID_1 = a_UUID.substr(0, a_UUID.length() / 2); - AString UUID_2 = a_UUID.substr(a_UUID.length() / 2); + if (a_UUID.length() != 32) + { + LOGWARNING("Attempt to send a bad uuid (length isn't 32): %s", a_UUID.c_str()); + ASSERT(!"Wrong uuid length!"); + return; + } + AString UUID_1 = a_UUID.substr(0, 16); + AString UUID_2 = a_UUID.substr(16); Int64 Value_1, Value_2; sscanf(UUID_1.c_str(), "%llx", &Value_1); sscanf(UUID_2.c_str(), "%llx", &Value_2); - AString SValue_1, SValue_2; - Printf(SValue_1, "%lld", Value_1); - Printf(SValue_2, "%lld", Value_2); - - StringToInteger(SValue_1.c_str(), Value_1); - StringToInteger(SValue_2.c_str(), Value_2); - WriteInt64(Value_1); WriteInt64(Value_2); } -- cgit v1.2.3 From 33c843c6567f0fdf47fd7a6f604fdfcb143c75d2 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 14 Sep 2014 21:40:12 +0200 Subject: Fixed SQLiteCpp downgrade --- lib/SQLiteCpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SQLiteCpp b/lib/SQLiteCpp index 27b9d1118..203c2fb68 160000 --- a/lib/SQLiteCpp +++ b/lib/SQLiteCpp @@ -1 +1 @@ -Subproject commit 27b9d111818af3b05bcf4153bb6e380fe1dd6816 +Subproject commit 203c2fb68bbf871eaf4ca98756a113d74d620dea -- cgit v1.2.3 From 26a4845a995065f0ed24ef0e21e4c9bf44cef002 Mon Sep 17 00:00:00 2001 From: Tycho Date: Tue, 16 Sep 2014 20:29:31 +0100 Subject: IncrementalRedstoneSimulator now has no dependencies on cChunk --- src/Chunk.h | 11 +- src/Simulator/IncrementalRedstoneSimulator.cpp | 11 +- src/Simulator/IncrementalRedstoneSimulator.h | 312 +----------------- src/Simulator/IncrementalRedstoneSimulator.inc | 417 ++++++++++++++++++++++--- src/Simulator/RedstoneSimulator.h | 6 + src/World.cpp | 2 +- 6 files changed, 384 insertions(+), 375 deletions(-) diff --git a/src/Chunk.h b/src/Chunk.h index 9a0e96513..4e8404595 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -417,11 +417,6 @@ public: cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; } cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return &m_RedstoneSimulatorData; } - cRedstoneSimulatorChunkData * GetRedstoneSimulatorQueuedData(void) { return &m_RedstoneSimulatorQueuedData; } - cIncrementalRedstoneSimulator::PoweredBlocksList * GetRedstoneSimulatorPoweredBlocksList(void) { return &m_RedstoneSimulatorPoweredBlocksList; } - cIncrementalRedstoneSimulator::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; } - cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; } - cIncrementalRedstoneSimulator::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; } bool IsRedstoneDirty(void) const { return m_IsRedstoneDirty; } void SetIsRedstoneDirty(bool a_Flag) { m_IsRedstoneDirty = a_Flag; } @@ -507,11 +502,7 @@ private: cSandSimulatorChunkData m_SandSimulatorData; cRedstoneSimulatorChunkData m_RedstoneSimulatorData; - cRedstoneSimulatorChunkData m_RedstoneSimulatorQueuedData; - cIncrementalRedstoneSimulator::PoweredBlocksList m_RedstoneSimulatorPoweredBlocksList; - cIncrementalRedstoneSimulator::LinkedBlocksList m_RedstoneSimulatorLinkedBlocksList; - cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList m_RedstoneSimulatorSimulatedPlayerToggleableList; - cIncrementalRedstoneSimulator::RepeatersDelayList m_RedstoneSimulatorRepeatersDelayList; + /** Indicates if simulate-once blocks should be updated by the redstone simulator */ bool m_IsRedstoneDirty; diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 515d72457..55cc014f3 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -1,9 +1,6 @@ #include "Globals.h" -#ifndef SELF_TEST - -#include "IncrementalRedstoneSimulator.h" #include "IncrementalRedstoneSimulator.inc" @@ -18,6 +15,8 @@ #include "Blocks/BlockPiston.h" #include "BlockEntities/ChestEntity.h" -#pragma clang diagnostic ignored "-Wweak-template-vtables" -template class cIncrementalRedstoneSimulator; -#endif +cRedstoneSimulator * MakeIncrementalRedstoneSimulator(cWorld & a_World) +{ + return new cIncrementalRedstoneSimulator(a_World); +} + diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 0120a3208..5bd1ad95d 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -3,313 +3,7 @@ #include "RedstoneSimulator.h" -/// Per-chunk data for the simulator, specified individual chunks to simulate -typedef cCoordWithBlockAndBoolVector cRedstoneSimulatorChunkData; - -class cRedstonePoweredEntity; - -typedef cItemCallback cRedstonePoweredCallback; - - -template class GetHandlerCompileTime, class ChestType> -class cIncrementalRedstoneSimulator : - public cRedstoneSimulator -{ - typedef cRedstoneSimulator super; -public: - - cIncrementalRedstoneSimulator(WorldType & a_World); - ~cIncrementalRedstoneSimulator(); - - virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used - virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, ChunkType * a_Chunk) override; - virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); } - virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override; - - enum eRedstoneDirection - { - REDSTONE_NONE = 0, - REDSTONE_X_POS = 0x1, - REDSTONE_X_NEG = 0x2, - REDSTONE_Z_POS = 0x4, - REDSTONE_Z_NEG = 0x8, - }; - eRedstoneDirection GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ); - -private: - - #define MAX_POWER_LEVEL 15 - - struct sPoweredBlocks // Define structure of the directly powered blocks list - { - Vector3i a_BlockPos; // Position of powered block - Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos - unsigned char a_PowerLevel; - }; - - struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side) - { - Vector3i a_BlockPos; - Vector3i a_MiddlePos; // Position of block that is betwixt a source and the destination - Vector3i a_SourcePos; - unsigned char a_PowerLevel; - }; - - struct sSimulatedPlayerToggleableList // Define structure of the list containing simulate-on-update blocks (such as trapdoors that respond once to a block update, and can be toggled by a player) - { - Vector3i a_RelBlockPos; - bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate - }; - - struct sRepeatersDelayList // Define structure of list containing repeaters' delay states - { - Vector3i a_RelBlockPos; - unsigned char a_DelayTicks; // For how many ticks should the repeater delay - unsigned char a_ElapsedTicks; // How much of the previous has been elapsed? - bool ShouldPowerOn; // What happens when the delay time is fulfilled? - }; - -public: - - typedef std::vector PoweredBlocksList; - typedef std::vector LinkedBlocksList; - typedef std::vector SimulatedPlayerToggleableList; - typedef std::vector RepeatersDelayList; - -private: - - cRedstoneSimulatorChunkData * m_RedstoneSimulatorChunkData; - PoweredBlocksList * m_PoweredBlocks; - LinkedBlocksList * m_LinkedPoweredBlocks; - SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks; - RepeatersDelayList * m_RepeatersDelayList; - - virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); } - void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk, ChunkType * a_OtherChunk = NULL); - ChunkType * m_Chunk; - - // We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly - // In addition to being non-performant, it would stop the player from actually breaking said device - - /* ====== SOURCES ====== */ - /** Handles the redstone torch */ - void HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState); - /** Handles the redstone block */ - void HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles levers */ - void HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles buttons */ - void HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles daylight sensors */ - void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles pressure plates */ - void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType); - /** Handles tripwire hooks - Performs correct meta and power setting for self by going in the direction it faces and looking for a continous line of tripwire bounded by another oppositely facing hook - If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task - */ - void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles trapped chests */ - void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /* ==================== */ - - /* ====== CARRIERS ====== */ - /** Handles redstone wire */ - void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles repeaters */ - void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState); - /* ====================== */ - - /* ====== DEVICES ====== */ - /** Handles pistons */ - void HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles dispensers and droppers */ - void HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles TNT (exploding) */ - void HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles redstone lamps */ - void HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState); - /** Handles doords */ - void HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles command blocks */ - void HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles activator, detector, and powered rails */ - void HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType); - /** Handles trapdoors */ - void HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles fence gates */ - void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles noteblocks */ - void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Handles tripwires */ - void HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /* ===================== */ - - /* ====== Helper functions ====== */ - /** Marks a block as powered */ - void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL); - /** Marks a block as being powered through another block */ - void SetBlockLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL); - /** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */ - void SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered); - /** Marks the second block in a direction as linked powered */ - void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL); - /** Marks all blocks immediately surrounding a coordinate as powered */ - void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL); - /** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */ - bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn); - /** Removes a block from the Powered and LinkedPowered lists - Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests - */ - void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, ChunkType * a_Chunk, bool a_IsFirstCall = true); - - /** Returns if a coordinate is powered or linked powered */ - bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); } - /** Returns if a coordinate is in the directly powered blocks list */ - bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, ChunkType * a_Chunk); - /** Returns if a coordinate is in the indirectly powered blocks list */ - bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); - /** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */ - bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered); - /** Returns if a repeater is powered by testing for power sources behind the repeater */ - bool IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta); - /** Returns if a repeater is locked */ - bool IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta); - /** Returns if a piston is powered */ - bool IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta); - /** Returns if a wire is powered - The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */ - bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel); - /** Handles delayed updates to repeaters **/ - void HandleRedstoneRepeaterDelays(void); - - /** Returns if lever metadata marks it as emitting power */ - bool IsLeverOn(NIBBLETYPE a_BlockMeta); - /** Returns if button metadata marks it as emitting power */ - bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return IsLeverOn(a_BlockMeta); } - /* ============================== */ - - /* ====== Misc Functions ====== */ - /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */ - inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); } - - /** Returns if a block is a mechanism (something that accepts power and does something) - Used by torches to determine if they power a block whilst not standing on the ground - */ - inline static bool IsMechanism(BLOCKTYPE Block) - { - switch (Block) - { - case E_BLOCK_ACTIVATOR_RAIL: - case E_BLOCK_COMMAND_BLOCK: - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - case E_BLOCK_FENCE_GATE: - case E_BLOCK_HOPPER: - case E_BLOCK_NOTE_BLOCK: - case E_BLOCK_TNT: - case E_BLOCK_TRAPDOOR: - case E_BLOCK_REDSTONE_LAMP_OFF: - case E_BLOCK_REDSTONE_LAMP_ON: - case E_BLOCK_WOODEN_DOOR: - case E_BLOCK_IRON_DOOR: - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_POWERED_RAIL: - case E_BLOCK_REDSTONE_WIRE: - { - return true; - } - default: return false; - } - } - - /** Returns if a block has the potential to output power */ - inline static bool IsPotentialSource(BLOCKTYPE Block) - { - switch (Block) - { - case E_BLOCK_DETECTOR_RAIL: - case E_BLOCK_DAYLIGHT_SENSOR: - case E_BLOCK_WOODEN_BUTTON: - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_REDSTONE_WIRE: - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_LEVER: - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_BLOCK_OF_REDSTONE: - case E_BLOCK_ACTIVE_COMPARATOR: - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_STONE_PRESSURE_PLATE: - case E_BLOCK_WOODEN_PRESSURE_PLATE: - case E_BLOCK_TRAPPED_CHEST: - { - return true; - } - default: return false; - } - } - - /** Returns if a block is any sort of redstone device */ - inline static bool IsRedstone(BLOCKTYPE Block) - { - switch (Block) - { - // All redstone devices, please alpha sort - case E_BLOCK_ACTIVATOR_RAIL: - case E_BLOCK_ACTIVE_COMPARATOR: - case E_BLOCK_BLOCK_OF_REDSTONE: - case E_BLOCK_COMMAND_BLOCK: - case E_BLOCK_DETECTOR_RAIL: - case E_BLOCK_DISPENSER: - case E_BLOCK_DAYLIGHT_SENSOR: - case E_BLOCK_DROPPER: - case E_BLOCK_FENCE_GATE: - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_HOPPER: - case E_BLOCK_INACTIVE_COMPARATOR: - case E_BLOCK_IRON_DOOR: - case E_BLOCK_LEVER: - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_NOTE_BLOCK: - case E_BLOCK_POWERED_RAIL: - case E_BLOCK_REDSTONE_LAMP_OFF: - case E_BLOCK_REDSTONE_LAMP_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_TORCH_OFF: - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_REDSTONE_WIRE: - case E_BLOCK_STICKY_PISTON: - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_STONE_PRESSURE_PLATE: - case E_BLOCK_TNT: - case E_BLOCK_TRAPDOOR: - case E_BLOCK_TRAPPED_CHEST: - case E_BLOCK_TRIPWIRE_HOOK: - case E_BLOCK_TRIPWIRE: - case E_BLOCK_WOODEN_BUTTON: - case E_BLOCK_WOODEN_DOOR: - case E_BLOCK_WOODEN_PRESSURE_PLATE: - case E_BLOCK_PISTON: - { - return true; - } - default: return false; - } - } - - inline static bool AreCoordsOnChunkBoundary(int a_BlockX, int a_BlockY, int a_BlockZ) - { - return ( // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks - ((a_BlockX % cChunkDef::Width) <= 1) || - ((a_BlockX % cChunkDef::Width) >= 14) || - ((a_BlockZ % cChunkDef::Width) <= 1) || - ((a_BlockZ % cChunkDef::Width) >= 14) - ); - } -}; +class cWorld; +class cChunk; +cRedstoneSimulator * MakeIncrementalRedstoneSimulator(cWorld & a_World); diff --git a/src/Simulator/IncrementalRedstoneSimulator.inc b/src/Simulator/IncrementalRedstoneSimulator.inc index 6d1f7b0ae..e3c856328 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.inc +++ b/src/Simulator/IncrementalRedstoneSimulator.inc @@ -3,20 +3,334 @@ #include "BoundingBox.h" #include "BlockEntities/RedstonePoweredEntity.h" #include "Blocks/ChunkInterface.h" +#include "RedstoneSimulator.h" + + + +typedef cItemCallback cRedstonePoweredCallback; + + template class GetHandlerCompileTime, class ChestType> -cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(WorldType & a_World) : - super(a_World), - m_RedstoneSimulatorChunkData(), - m_PoweredBlocks(), - m_LinkedPoweredBlocks(), - m_SimulatedPlayerToggleableBlocks(), - m_RepeatersDelayList(), - m_Chunk() +class cIncrementalRedstoneSimulator : + public cRedstoneSimulator { -} + typedef cRedstoneSimulator super; +public: + + cIncrementalRedstoneSimulator(WorldType & a_World) + : cRedstoneSimulator(a_World) + { + } + ~cIncrementalRedstoneSimulator(); + + virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used + virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, ChunkType * a_Chunk) override; + virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); } + virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override; + + enum eRedstoneDirection + { + REDSTONE_NONE = 0, + REDSTONE_X_POS = 0x1, + REDSTONE_X_NEG = 0x2, + REDSTONE_Z_POS = 0x4, + REDSTONE_Z_NEG = 0x8, + }; + eRedstoneDirection GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ); + +private: + + #define MAX_POWER_LEVEL 15 + + struct sPoweredBlocks // Define structure of the directly powered blocks list + { + Vector3i a_BlockPos; // Position of powered block + Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos + unsigned char a_PowerLevel; + }; + + struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side) + { + Vector3i a_BlockPos; + Vector3i a_MiddlePos; // Position of block that is betwixt a source and the destination + Vector3i a_SourcePos; + unsigned char a_PowerLevel; + }; + + struct sSimulatedPlayerToggleableList // Define structure of the list containing simulate-on-update blocks (such as trapdoors that respond once to a block update, and can be toggled by a player) + { + Vector3i a_RelBlockPos; + bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate + }; + + struct sRepeatersDelayList // Define structure of list containing repeaters' delay states + { + Vector3i a_RelBlockPos; + unsigned char a_DelayTicks; // For how many ticks should the repeater delay + unsigned char a_ElapsedTicks; // How much of the previous has been elapsed? + bool ShouldPowerOn; // What happens when the delay time is fulfilled? + }; + + class cIncrementalRedstoneSimulatorChunkData : + cRedstoneSimulatorChunkData + { + public: + /// Per-chunk data for the simulator, specified individual chunks to simulate + cCoordWithBlockAndBoolVector m_ChunkData; + cCoordWithBlockAndBoolVector m_QueuedChunkData; + std::vector m_PoweredBlocks; + std::vector m_LinkedBlocks; + std::vector m_SimulatedPlayerToggleableBlocks; + std::vector m_RepeatersDelayList; + }; + +public: + + typedef std::vector PoweredBlocksList; + typedef std::vector LinkedBlocksList; + typedef std::vector SimulatedPlayerToggleableList; + typedef std::vector RepeatersDelayList; + +private: + + cIncrementalRedstoneSimulatorChunkData * m_RedstoneSimulatorChunkData; + PoweredBlocksList * m_PoweredBlocks; + LinkedBlocksList * m_LinkedPoweredBlocks; + SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks; + RepeatersDelayList * m_RepeatersDelayList; + + virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); } + void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk, ChunkType * a_OtherChunk = NULL); + ChunkType * m_Chunk; + + // We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly + // In addition to being non-performant, it would stop the player from actually breaking said device + + /* ====== SOURCES ====== */ + /** Handles the redstone torch */ + void HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState); + /** Handles the redstone block */ + void HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles levers */ + void HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles buttons */ + void HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles daylight sensors */ + void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles pressure plates */ + void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType); + /** Handles tripwire hooks + Performs correct meta and power setting for self by going in the direction it faces and looking for a continous line of tripwire bounded by another oppositely facing hook + If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task + */ + void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles trapped chests */ + void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /* ==================== */ + + /* ====== CARRIERS ====== */ + /** Handles redstone wire */ + void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles repeaters */ + void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState); + /* ====================== */ + + /* ====== DEVICES ====== */ + /** Handles pistons */ + void HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles dispensers and droppers */ + void HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles TNT (exploding) */ + void HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles redstone lamps */ + void HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState); + /** Handles doords */ + void HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles command blocks */ + void HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles activator, detector, and powered rails */ + void HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType); + /** Handles trapdoors */ + void HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles fence gates */ + void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles noteblocks */ + void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Handles tripwires */ + void HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /* ===================== */ + + /* ====== Helper functions ====== */ + /** Marks a block as powered */ + void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL); + /** Marks a block as being powered through another block */ + void SetBlockLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL); + /** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */ + void SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered); + /** Marks the second block in a direction as linked powered */ + void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL); + /** Marks all blocks immediately surrounding a coordinate as powered */ + void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL); + /** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */ + bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn); + /** Removes a block from the Powered and LinkedPowered lists + Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests + */ + void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, ChunkType * a_Chunk, bool a_IsFirstCall = true); + + /** Returns if a coordinate is powered or linked powered */ + bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); } + /** Returns if a coordinate is in the directly powered blocks list */ + bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, ChunkType * a_Chunk); + /** Returns if a coordinate is in the indirectly powered blocks list */ + bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ); + /** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */ + bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered); + /** Returns if a repeater is powered by testing for power sources behind the repeater */ + bool IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta); + /** Returns if a repeater is locked */ + bool IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta); + /** Returns if a piston is powered */ + bool IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta); + /** Returns if a wire is powered + The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */ + bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel); + /** Handles delayed updates to repeaters **/ + void HandleRedstoneRepeaterDelays(void); + + /** Returns if lever metadata marks it as emitting power */ + bool IsLeverOn(NIBBLETYPE a_BlockMeta); + /** Returns if button metadata marks it as emitting power */ + bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return IsLeverOn(a_BlockMeta); } + /* ============================== */ + + /* ====== Misc Functions ====== */ + /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */ + inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); } + + /** Returns if a block is a mechanism (something that accepts power and does something) + Used by torches to determine if they power a block whilst not standing on the ground + */ + inline static bool IsMechanism(BLOCKTYPE Block) + { + switch (Block) + { + case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_COMMAND_BLOCK: + case E_BLOCK_PISTON: + case E_BLOCK_STICKY_PISTON: + case E_BLOCK_DISPENSER: + case E_BLOCK_DROPPER: + case E_BLOCK_FENCE_GATE: + case E_BLOCK_HOPPER: + case E_BLOCK_NOTE_BLOCK: + case E_BLOCK_TNT: + case E_BLOCK_TRAPDOOR: + case E_BLOCK_REDSTONE_LAMP_OFF: + case E_BLOCK_REDSTONE_LAMP_ON: + case E_BLOCK_WOODEN_DOOR: + case E_BLOCK_IRON_DOOR: + case E_BLOCK_REDSTONE_REPEATER_OFF: + case E_BLOCK_REDSTONE_REPEATER_ON: + case E_BLOCK_POWERED_RAIL: + case E_BLOCK_REDSTONE_WIRE: + { + return true; + } + default: return false; + } + } + + /** Returns if a block has the potential to output power */ + inline static bool IsPotentialSource(BLOCKTYPE Block) + { + switch (Block) + { + case E_BLOCK_DETECTOR_RAIL: + case E_BLOCK_DAYLIGHT_SENSOR: + case E_BLOCK_WOODEN_BUTTON: + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_REDSTONE_WIRE: + case E_BLOCK_REDSTONE_TORCH_ON: + case E_BLOCK_LEVER: + case E_BLOCK_REDSTONE_REPEATER_ON: + case E_BLOCK_BLOCK_OF_REDSTONE: + case E_BLOCK_ACTIVE_COMPARATOR: + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_STONE_PRESSURE_PLATE: + case E_BLOCK_WOODEN_PRESSURE_PLATE: + case E_BLOCK_TRAPPED_CHEST: + { + return true; + } + default: return false; + } + } + + /** Returns if a block is any sort of redstone device */ + inline static bool IsRedstone(BLOCKTYPE Block) + { + switch (Block) + { + // All redstone devices, please alpha sort + case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_ACTIVE_COMPARATOR: + case E_BLOCK_BLOCK_OF_REDSTONE: + case E_BLOCK_COMMAND_BLOCK: + case E_BLOCK_DETECTOR_RAIL: + case E_BLOCK_DISPENSER: + case E_BLOCK_DAYLIGHT_SENSOR: + case E_BLOCK_DROPPER: + case E_BLOCK_FENCE_GATE: + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_HOPPER: + case E_BLOCK_INACTIVE_COMPARATOR: + case E_BLOCK_IRON_DOOR: + case E_BLOCK_LEVER: + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_NOTE_BLOCK: + case E_BLOCK_POWERED_RAIL: + case E_BLOCK_REDSTONE_LAMP_OFF: + case E_BLOCK_REDSTONE_LAMP_ON: + case E_BLOCK_REDSTONE_REPEATER_OFF: + case E_BLOCK_REDSTONE_REPEATER_ON: + case E_BLOCK_REDSTONE_TORCH_OFF: + case E_BLOCK_REDSTONE_TORCH_ON: + case E_BLOCK_REDSTONE_WIRE: + case E_BLOCK_STICKY_PISTON: + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_STONE_PRESSURE_PLATE: + case E_BLOCK_TNT: + case E_BLOCK_TRAPDOOR: + case E_BLOCK_TRAPPED_CHEST: + case E_BLOCK_TRIPWIRE_HOOK: + case E_BLOCK_TRIPWIRE: + case E_BLOCK_WOODEN_BUTTON: + case E_BLOCK_WOODEN_DOOR: + case E_BLOCK_WOODEN_PRESSURE_PLATE: + case E_BLOCK_PISTON: + { + return true; + } + default: return false; + } + } + + inline static bool AreCoordsOnChunkBoundary(int a_BlockX, int a_BlockY, int a_BlockZ) + { + return ( // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks + ((a_BlockX % cChunkDef::Width) <= 1) || + ((a_BlockX % cChunkDef::Width) >= 14) || + ((a_BlockZ % cChunkDef::Width) <= 1) || + ((a_BlockZ % cChunkDef::Width) >= 14) + ); + } +}; + @@ -70,8 +384,8 @@ void cIncrementalRedstoneSimulatorGetRedstoneSimulatorPoweredBlocksList(); - for (typename PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end();) + PoweredBlocksList & PoweredBlocks = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks; + for (typename PoweredBlocksList::iterator itr = PoweredBlocks.begin(); itr != PoweredBlocks.end();) { if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -82,7 +396,7 @@ void cIncrementalRedstoneSimulatora_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = PoweredBlocks->erase(itr); + itr = PoweredBlocks.erase(itr); continue; } else if ( @@ -95,22 +409,22 @@ void cIncrementalRedstoneSimulatora_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = PoweredBlocks->erase(itr); + itr = PoweredBlocks.erase(itr); continue; } ++itr; } - LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); + LinkedBlocksList & LinkedPoweredBlocks = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks; // We loop through all values (insteading of breaking out at the first) to make sure everything is gone, as there can be multiple SourceBlock entries for one AddBlock coordinate - for (typename LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end();) + for (typename LinkedBlocksList::iterator itr = LinkedPoweredBlocks.begin(); itr != LinkedPoweredBlocks.end();) { if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { if (!IsPotentialSource(Block)) { LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = LinkedPoweredBlocks->erase(itr); + itr = LinkedPoweredBlocks.erase(itr); continue; } else if ( @@ -121,7 +435,7 @@ void cIncrementalRedstoneSimulatora_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = LinkedPoweredBlocks->erase(itr); + itr = LinkedPoweredBlocks.erase(itr); continue; } } @@ -130,15 +444,15 @@ void cIncrementalRedstoneSimulatora_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = LinkedPoweredBlocks->erase(itr); + itr = LinkedPoweredBlocks.erase(itr); continue; } } ++itr; } - SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); - for (typename SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks->begin(); itr != SimulatedPlayerToggleableBlocks->end(); ++itr) + SimulatedPlayerToggleableList & SimulatedPlayerToggleableBlocks = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks; + for (typename SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks.begin(); itr != SimulatedPlayerToggleableBlocks.end(); ++itr) { if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ))) { @@ -148,13 +462,13 @@ void cIncrementalRedstoneSimulatora_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z); - SimulatedPlayerToggleableBlocks->erase(itr); + SimulatedPlayerToggleableBlocks.erase(itr); break; } } - RepeatersDelayList * RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); - for (typename RepeatersDelayList::iterator itr = RepeatersDelayList->begin(); itr != RepeatersDelayList->end(); ++itr) + RepeatersDelayList & RepeatersDelayList = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_RepeatersDelayList; + for (typename RepeatersDelayList::iterator itr = RepeatersDelayList.begin(); itr != RepeatersDelayList.end(); ++itr) { if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ))) { @@ -163,7 +477,7 @@ void cIncrementalRedstoneSimulatorerase(itr); + RepeatersDelayList.erase(itr); break; } } @@ -174,8 +488,8 @@ void cIncrementalRedstoneSimulatorGetRedstoneSimulatorData(); - for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr) + cCoordWithBlockAndBoolVector & RedstoneSimulatorChunkData = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_ChunkData; + for (cCoordWithBlockAndBoolVector::iterator itr = RedstoneSimulatorChunkData.begin(); itr != RedstoneSimulatorChunkData.end(); ++itr) { if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block { @@ -197,7 +511,8 @@ void cIncrementalRedstoneSimulatorGetRedstoneSimulatorQueuedData()->begin(); itr != a_Chunk->GetRedstoneSimulatorQueuedData()->end(); ++itr) + cCoordWithBlockAndBoolVector & QueuedData = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData; + for (cCoordWithBlockAndBoolVector::iterator itr = QueuedData.begin(); itr != QueuedData.end(); ++itr) { if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) { @@ -205,7 +520,7 @@ void cIncrementalRedstoneSimulatorGetRedstoneSimulatorQueuedData()->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); + QueuedData.push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); } @@ -214,19 +529,23 @@ void cIncrementalRedstoneSimulator class GetHandlerCompileTime, class ChestType> void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, ChunkType * a_Chunk) { - m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); - if (m_RedstoneSimulatorChunkData->empty() && a_Chunk->GetRedstoneSimulatorQueuedData()->empty()) + m_RedstoneSimulatorChunkData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData(); + if (m_RedstoneSimulatorChunkData->m_ChunkData.empty() && ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData.empty()) { return; } - m_RedstoneSimulatorChunkData->insert(m_RedstoneSimulatorChunkData->end(), a_Chunk->GetRedstoneSimulatorQueuedData()->begin(), a_Chunk->GetRedstoneSimulatorQueuedData()->end()); - a_Chunk->GetRedstoneSimulatorQueuedData()->clear(); + m_RedstoneSimulatorChunkData->m_ChunkData.insert( + m_RedstoneSimulatorChunkData->m_ChunkData.end(), + m_RedstoneSimulatorChunkData ->m_QueuedChunkData.begin(), + m_RedstoneSimulatorChunkData ->m_QueuedChunkData.end()); + + m_RedstoneSimulatorChunkData->m_QueuedChunkData.clear(); - m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); - m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); - m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); - m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); + m_PoweredBlocks = &m_RedstoneSimulatorChunkData->m_PoweredBlocks; + m_RepeatersDelayList = &m_RedstoneSimulatorChunkData->m_RepeatersDelayList; + m_SimulatedPlayerToggleableBlocks = &m_RedstoneSimulatorChunkData->m_SimulatedPlayerToggleableBlocks; + m_LinkedPoweredBlocks = &m_RedstoneSimulatorChunkData->m_LinkedBlocks; m_Chunk = a_Chunk; bool ShouldUpdateSimulateOnceBlocks = false; @@ -240,11 +559,11 @@ void cIncrementalRedstoneSimulatorbegin(); dataitr != m_RedstoneSimulatorChunkData->end();) + for (cCoordWithBlockAndBoolVector::iterator dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.begin(); dataitr != m_RedstoneSimulatorChunkData->m_ChunkData.end();) { if (dataitr->DataTwo) { - dataitr = m_RedstoneSimulatorChunkData->erase(dataitr); + dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr); continue; } @@ -1497,7 +1816,7 @@ bool cIncrementalRedstoneSimulatorGetPosX() * cChunkDef::Width) + a_RelBlockX; int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; - for (typename PoweredBlocksList::const_iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end(); ++itr) // Check powered list + for (typename PoweredBlocksList::const_iterator itr = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.begin(); itr != ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.end(); ++itr) // Check powered list { if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { @@ -1904,8 +2223,8 @@ void cIncrementalRedstoneSimulatorGetRedstoneSimulatorPoweredBlocksList(); // We need to insert the value into the chunk who owns the block position - for (typename PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) + PoweredBlocksList & Powered = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position + for (typename PoweredBlocksList::iterator itr = Powered.begin(); itr != Powered.end(); ++itr) { if ( itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && @@ -1952,7 +2271,7 @@ void cIncrementalRedstoneSimulatorpush_back(RC); + Powered.push_back(RC); Neighbour->SetIsRedstoneDirty(true); m_Chunk->SetIsRedstoneDirty(true); } @@ -1986,8 +2305,8 @@ void cIncrementalRedstoneSimulatorGetRedstoneSimulatorLinkedBlocksList(); - for (typename LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list + LinkedBlocksList & Linked = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_LinkedBlocks; + for (typename LinkedBlocksList::iterator itr = Linked.begin(); itr != Linked.end(); ++itr) // Check linked powered list { if ( itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) && @@ -2006,7 +2325,7 @@ void cIncrementalRedstoneSimulatorpush_back(RC); + Linked.push_back(RC); Neighbour->SetIsRedstoneDirty(true); m_Chunk->SetIsRedstoneDirty(true); } @@ -2096,21 +2415,21 @@ void cIncrementalRedstoneSimulatorGetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end();) + for (typename PoweredBlocksList::iterator itr = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.begin(); itr != ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.end();) { if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))) { - itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->erase(itr); + itr = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.erase(itr); a_Chunk->SetIsRedstoneDirty(true); continue; } ++itr; } - for (typename LinkedBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->end();) + for (typename LinkedBlocksList::iterator itr = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks.begin(); itr != ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks.end();) { if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))) { - itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->erase(itr); + itr = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks.erase(itr); a_Chunk->SetIsRedstoneDirty(true); continue; } diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h index 56843e37f..0e3dd495d 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -4,6 +4,12 @@ #include "Simulator.h" +class cRedstoneSimulatorChunkData +{ +public: + virtual ~cRedstoneSimulatorChunkData() {} +} ; + template class cRedstoneSimulator : diff --git a/src/World.cpp b/src/World.cpp index 732c9f14c..ded42f093 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -3272,7 +3272,7 @@ cRedstoneSimulator * cWorld::InitializeRedstoneSimulator(cIniFil if (NoCaseCompare(SimulatorName, "Incremental") == 0) { - res = new cIncrementalRedstoneSimulator(*this); + res = MakeIncrementalRedstoneSimulator(*this); } else if (NoCaseCompare(SimulatorName, "noop") == 0) { -- cgit v1.2.3 From 3ee211bbbaa4673b2f38846fadb1d2bfba93b1a3 Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 17 Sep 2014 17:53:42 +0200 Subject: Use xofts ReadPosition() code. --- src/ByteBuffer.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index 851c63858..262e0e3b5 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -497,9 +497,12 @@ bool cByteBuffer::ReadPosition(int & a_BlockX, int & a_BlockY, int & a_BlockZ) return false; } - a_BlockX = Value >> 38; - a_BlockY = Value << 26 >> 52; - a_BlockZ = Value << 38 >> 38; + UInt32 BlockXRaw = (Value >> 38) & 0x3ffffff; + UInt32 BlockYRaw = (Value >> 26) & 0xfff; + UInt32 BlockZRaw = (Value & 0x3ffffff); + a_BlockX = ((BlockXRaw & 0x2000000) == 0) ? BlockXRaw : (~(BlockXRaw & 0x1ffffff)) + 1; + a_BlockY = ((BlockYRaw & 0x800) == 0) ? BlockYRaw : (~(BlockXRaw & 0x7ff)) + 1; + a_BlockZ = ((BlockZRaw & 0x2000000) == 0) ? BlockZRaw : (~(BlockZRaw & 0x1ffffff)) + 1; return true; } -- cgit v1.2.3 From 6e7c0e33b5dd6d86d66ac2eb1a07a33652a708fd Mon Sep 17 00:00:00 2001 From: Tycho Date: Wed, 17 Sep 2014 18:40:10 +0100 Subject: Added first test to show the object can be created --- src/Bindings/CMakeLists.txt | 2 + src/BlockEntities/DispenserEntity.cpp | 2 +- src/BlockID.cpp | 56 ++++----- src/BlockInfo.cpp | 42 ------- src/BlockInfo.h | 31 ++++- src/Blocks/BlockMobHead.h | 4 +- src/Blocks/BlockPiston.h | 2 +- src/Blocks/BlockPortal.h | 2 +- src/Blocks/BlockPumpkin.h | 6 +- src/Blocks/ChunkInterface.cpp | 66 ++++++++++ src/Blocks/ChunkInterface.h | 63 ++-------- src/Blocks/WorldInterface.h | 7 +- src/Entities/Entity.cpp | 20 +-- src/Entities/EntityEffect.cpp | 4 +- src/Entities/Player.cpp | 4 +- src/Entities/ThrownEggEntity.cpp | 10 +- src/Entities/ThrownSnowballEntity.cpp | 4 +- src/Generating/FinishGen.cpp | 1 + src/Globals.h | 21 ++++ src/Items/ItemSpawnEgg.h | 56 ++++----- src/MobSpawner.cpp | 100 +++++++-------- src/MobSpawner.h | 12 +- src/Mobs/AggressiveMonster.cpp | 2 +- src/Mobs/AggressiveMonster.h | 2 +- src/Mobs/Monster.cpp | 116 +++++++++--------- src/Mobs/Monster.h | 54 ++------- src/Mobs/MonsterTypes.h | 41 +++++++ src/Mobs/Mooshroom.cpp | 2 +- src/Mobs/PassiveAggressiveMonster.cpp | 2 +- src/Mobs/PassiveAggressiveMonster.h | 2 +- src/Mobs/PassiveMonster.cpp | 2 +- src/Mobs/PassiveMonster.h | 2 +- src/Protocol/Protocol125.cpp | 32 ++--- src/Protocol/Protocol17x.cpp | 30 ++--- src/Simulator/IncrementalRedstoneSimulator.cpp | 4 +- src/Simulator/IncrementalRedstoneSimulator.inc | 55 +++++---- src/Simulator/SandSimulator.cpp | 1 + src/Simulator/Simulator.cpp | 5 + src/Simulator/Simulator.h | 1 - src/Simulator/Simulator.inc | 4 - src/World.cpp | 6 +- src/World.h | 4 +- src/WorldStorage/NBTChunkSerializer.cpp | 82 ++++++------- tests/CMakeLists.txt | 1 + tests/Redstone/CMakeLists.txt | 10 ++ tests/Redstone/creatable.cpp | 162 +++++++++++++++++++++++++ 46 files changed, 681 insertions(+), 456 deletions(-) create mode 100644 src/Mobs/MonsterTypes.h create mode 100644 tests/Redstone/CMakeLists.txt create mode 100644 tests/Redstone/creatable.cpp diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt index 7a1769e9a..930ee9771 100644 --- a/src/Bindings/CMakeLists.txt +++ b/src/Bindings/CMakeLists.txt @@ -129,6 +129,8 @@ set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.cpp PROPER set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.h PROPERTIES GENERATED TRUE) set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/LuaState_Call.inc PROPERTIES GENERATED TRUE) +set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.cpp PROPERTIES COMPILE_FLAGS -Wno-error) + if(NOT MSVC) add_library(Bindings ${SRCS} ${HDRS}) diff --git a/src/BlockEntities/DispenserEntity.cpp b/src/BlockEntities/DispenserEntity.cpp index c02c68afa..d3c06653f 100644 --- a/src/BlockEntities/DispenserEntity.cpp +++ b/src/BlockEntities/DispenserEntity.cpp @@ -109,7 +109,7 @@ void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) { double MobX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width); double MobZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width); - if (m_World->SpawnMob(MobX, DispY, MobZ, (cMonster::eType)m_Contents.GetSlot(a_SlotNum).m_ItemDamage) >= 0) + if (m_World->SpawnMob(MobX, DispY, MobZ, (eMonsterType)m_Contents.GetSlot(a_SlotNum).m_ItemDamage) >= 0) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } diff --git a/src/BlockID.cpp b/src/BlockID.cpp index 07a1fc9e5..9026d81f2 100644 --- a/src/BlockID.cpp +++ b/src/BlockID.cpp @@ -261,34 +261,34 @@ int StringToMobType(const AString & a_MobString) const char * m_String; } MobMap [] = { - {cMonster::mtCreeper, "Creeper"}, - {cMonster::mtSkeleton, "Skeleton"}, - {cMonster::mtSpider, "Spider"}, - {cMonster::mtGiant, "Giant"}, - {cMonster::mtZombie, "Zombie"}, - {cMonster::mtSlime, "Slime"}, - {cMonster::mtGhast, "Ghast"}, - {cMonster::mtZombiePigman, "ZombiePigman"}, - {cMonster::mtEnderman, "Enderman"}, - {cMonster::mtCaveSpider, "CaveSpider"}, - {cMonster::mtSilverfish, "SilverFish"}, - {cMonster::mtBlaze, "Blaze"}, - {cMonster::mtMagmaCube, "MagmaCube"}, - {cMonster::mtEnderDragon, "EnderDragon"}, - {cMonster::mtWither, "Wither"}, - {cMonster::mtBat, "Bat"}, - {cMonster::mtWitch, "Witch"}, - {cMonster::mtPig, "Pig"}, - {cMonster::mtSheep, "Sheep"}, - {cMonster::mtCow, "Cow"}, - {cMonster::mtChicken, "Chicken"}, - {cMonster::mtSquid, "Squid"}, - {cMonster::mtWolf, "Wolf"}, - {cMonster::mtMooshroom, "Mooshroom"}, - {cMonster::mtSnowGolem, "SnowGolem"}, - {cMonster::mtOcelot, "Ocelot"}, - {cMonster::mtIronGolem, "IronGolem"}, - {cMonster::mtVillager, "Villager"}, + {mtCreeper, "Creeper"}, + {mtSkeleton, "Skeleton"}, + {mtSpider, "Spider"}, + {mtGiant, "Giant"}, + {mtZombie, "Zombie"}, + {mtSlime, "Slime"}, + {mtGhast, "Ghast"}, + {mtZombiePigman, "ZombiePigman"}, + {mtEnderman, "Enderman"}, + {mtCaveSpider, "CaveSpider"}, + {mtSilverfish, "SilverFish"}, + {mtBlaze, "Blaze"}, + {mtMagmaCube, "MagmaCube"}, + {mtEnderDragon, "EnderDragon"}, + {mtWither, "Wither"}, + {mtBat, "Bat"}, + {mtWitch, "Witch"}, + {mtPig, "Pig"}, + {mtSheep, "Sheep"}, + {mtCow, "Cow"}, + {mtChicken, "Chicken"}, + {mtSquid, "Squid"}, + {mtWolf, "Wolf"}, + {mtMooshroom, "Mooshroom"}, + {mtSnowGolem, "SnowGolem"}, + {mtOcelot, "Ocelot"}, + {mtIronGolem, "IronGolem"}, + {mtVillager, "Villager"}, }; for (size_t i = 0; i < ARRAYCOUNT(MobMap); i++) { diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index 9ac66d35d..12eeceba2 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -6,26 +6,6 @@ - - -cBlockInfo::cBlockInfo() - : m_LightValue(0x00) - , m_SpreadLightFalloff(0x0f) - , m_Transparent(false) - , m_OneHitDig(false) - , m_PistonBreakable(false) - , m_IsSnowable(false) - , m_IsSolid(true) - , m_FullyOccupiesVoxel(false) - , m_CanBeTerraformed(false) - , m_PlaceSound("") - , m_Handler(NULL) -{} - - - - - cBlockInfo::~cBlockInfo() { delete m_Handler; @@ -33,28 +13,6 @@ cBlockInfo::~cBlockInfo() } - - - -/** This accessor makes sure that the cBlockInfo structures are properly initialized exactly once. -It does so by using the C++ singleton approximation - storing the actual singleton as the function's static variable. -It works only if it is called for the first time before the app spawns other threads. */ -cBlockInfo & cBlockInfo::Get(BLOCKTYPE a_Type) -{ - static cBlockInfo ms_Info[256]; - static bool IsBlockInfoInitialized = false; - if (!IsBlockInfoInitialized) - { - cBlockInfo::Initialize(ms_Info); - IsBlockInfoInitialized = true; - } - return ms_Info[a_Type]; -} - - - - - void cBlockInfo::Initialize(cBlockInfoArray & a_Info) { for (unsigned int i = 0; i < 256; ++i) diff --git a/src/BlockInfo.h b/src/BlockInfo.h index 567070a7f..bfa62a132 100644 --- a/src/BlockInfo.h +++ b/src/BlockInfo.h @@ -11,14 +11,27 @@ class cBlockHandler; - // tolua_begin class cBlockInfo { public: /** Returns the associated BlockInfo structure for the specified block type. */ - static cBlockInfo & Get(BLOCKTYPE a_Type); + + /** This accessor makes sure that the cBlockInfo structures are properly initialized exactly once. +It does so by using the C++ singleton approximation - storing the actual singleton as the function's static variable. +It works only if it is called for the first time before the app spawns other threads. */ + static cBlockInfo & Get(BLOCKTYPE a_Type) + { + static cBlockInfo ms_Info[256]; + static bool IsBlockInfoInitialized = false; + if (!IsBlockInfoInitialized) + { + cBlockInfo::Initialize(ms_Info); + IsBlockInfoInitialized = true; + } + return ms_Info[a_Type]; + } /** How much light do the blocks emit on their own? */ @@ -78,7 +91,19 @@ protected: typedef cBlockInfo cBlockInfoArray[256]; /** Creates a default BlockInfo structure, initializes all values to their defaults */ - cBlockInfo(); + cBlockInfo() + : m_LightValue(0x00) + , m_SpreadLightFalloff(0x0f) + , m_Transparent(false) + , m_OneHitDig(false) + , m_PistonBreakable(false) + , m_IsSnowable(false) + , m_IsSolid(true) + , m_FullyOccupiesVoxel(false) + , m_CanBeTerraformed(false) + , m_PlaceSound("") + , m_Handler(NULL) + {} /** Cleans up the stored values */ ~cBlockInfo(); diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h index ff1ef97bf..f19c78694 100644 --- a/src/Blocks/BlockMobHead.h +++ b/src/Blocks/BlockMobHead.h @@ -151,7 +151,7 @@ public: a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX - 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); // Spawn the wither: - a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither); + a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtWither); // Award Achievement a_WorldInterface.ForEachPlayer(PlayerCallback); @@ -181,7 +181,7 @@ public: a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ - 1, E_BLOCK_AIR, 0); // Spawn the wither: - a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither); + a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtWither); // Award Achievement a_WorldInterface.ForEachPlayer(PlayerCallback); diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h index 0bec603e3..78959595b 100644 --- a/src/Blocks/BlockPiston.h +++ b/src/Blocks/BlockPiston.h @@ -4,7 +4,7 @@ #include "BlockHandler.h" - +class cWorld; class cBlockPistonHandler : diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h index 8fac2a126..97ba26ee3 100644 --- a/src/Blocks/BlockPortal.h +++ b/src/Blocks/BlockPortal.h @@ -50,7 +50,7 @@ public: int PosX = a_Chunk.GetPosX() * cChunkDef::Width + a_RelX; int PosZ = a_Chunk.GetPosZ() * cChunkDef::Width + a_RelZ; - a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, cMonster::mtZombiePigman); + a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, mtZombiePigman); } virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override diff --git a/src/Blocks/BlockPumpkin.h b/src/Blocks/BlockPumpkin.h index 15ac80fd7..275d1422a 100644 --- a/src/Blocks/BlockPumpkin.h +++ b/src/Blocks/BlockPumpkin.h @@ -36,7 +36,7 @@ public: a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0); - a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtSnowGolem); + a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtSnowGolem); return; } @@ -61,7 +61,7 @@ public: a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0); // Spawn the golem: - a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtIronGolem); + a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtIronGolem); } else if ( (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1) == E_BLOCK_IRON_BLOCK) && @@ -76,7 +76,7 @@ public: a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0); // Spawn the golem: - a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtIronGolem); + a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtIronGolem); } } diff --git a/src/Blocks/ChunkInterface.cpp b/src/Blocks/ChunkInterface.cpp index 540581ae7..809c24635 100644 --- a/src/Blocks/ChunkInterface.cpp +++ b/src/Blocks/ChunkInterface.cpp @@ -2,8 +2,74 @@ #include "Globals.h" #include "ChunkInterface.h" +#include "ChunkMap.h" #include "BlockHandler.h" +BLOCKTYPE cChunkInterface::GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + return m_ChunkMap->GetBlock(a_BlockX, a_BlockY, a_BlockZ); +} +BLOCKTYPE cChunkInterface::GetBlock(const Vector3i & a_Pos) +{ + return GetBlock(a_Pos.x, a_Pos.y, a_Pos.z); +} +NIBBLETYPE cChunkInterface::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + return m_ChunkMap->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); +} + +bool cChunkInterface::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) +{ + return m_ChunkMap->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); +} + +/** Sets the block at the specified coords to the specified value. +Full processing, incl. updating neighbors, is performed. +*/ +void cChunkInterface::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) +{ + m_ChunkMap->SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); +} + +void cChunkInterface::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData) +{ + m_ChunkMap->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_MetaData); +} + +void cChunkInterface::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_TickDelay, BLOCKTYPE a_PreviousBlockType, cWorldInterface & a_WorldInterface) +{ + m_ChunkMap->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_WorldInterface.GetWorldAge() + a_TickDelay, a_PreviousBlockType); +} + +/** Sets the block at the specified coords to the specified value. +The replacement doesn't trigger block updates. +The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block) +*/ +void cChunkInterface::FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) +{ + m_ChunkMap->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); +} + +void cChunkInterface::FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) +{ + FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta); +} + +void cChunkInterface::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) +{ + m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); +} + +bool cChunkInterface::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) +{ + return m_ChunkMap->ForEachChunkInRect(a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ, a_Callback); +} + +bool cChunkInterface::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) +{ + return m_ChunkMap->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); +} + bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, int a_X, int a_Y, int a_Z) { cBlockHandler * Handler = cBlockInfo::GetHandler(GetBlock(a_X, a_Y, a_Z)); diff --git a/src/Blocks/ChunkInterface.h b/src/Blocks/ChunkInterface.h index dea9d7c7e..dff30a6ee 100644 --- a/src/Blocks/ChunkInterface.h +++ b/src/Blocks/ChunkInterface.h @@ -1,13 +1,12 @@ #pragma once -#include "../ChunkMap.h" #include "../ForEachChunkProvider.h" #include "WorldInterface.h" - +class cChunkMap; class cChunkInterface: public cForEachChunkProvider @@ -16,70 +15,34 @@ public: cChunkInterface(cChunkMap * a_ChunkMap) : m_ChunkMap(a_ChunkMap) {} - BLOCKTYPE GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ) - { - return m_ChunkMap->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - } - BLOCKTYPE GetBlock(const Vector3i & a_Pos) - { - return GetBlock(a_Pos.x, a_Pos.y, a_Pos.z); - } - NIBBLETYPE GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ) - { - return m_ChunkMap->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); - } + BLOCKTYPE GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ); + BLOCKTYPE GetBlock(const Vector3i & a_Pos); + NIBBLETYPE GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ); - bool GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) - { - return m_ChunkMap->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); - } + bool GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta); /** Sets the block at the specified coords to the specified value. Full processing, incl. updating neighbors, is performed. */ - void SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) - { - m_ChunkMap->SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); - } + void SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); - void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData) - { - m_ChunkMap->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_MetaData); - } + void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData); - void QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_TickDelay, BLOCKTYPE a_PreviousBlockType, cWorldInterface & a_WorldInterface) - { - m_ChunkMap->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_WorldInterface.GetWorldAge() + a_TickDelay, a_PreviousBlockType); - } + void QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_TickDelay, BLOCKTYPE a_PreviousBlockType, cWorldInterface & a_WorldInterface); /** Sets the block at the specified coords to the specified value. The replacement doesn't trigger block updates. The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block) */ - void FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) - { - m_ChunkMap->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); - } + void FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); - void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) - { - FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta); - } + void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); - void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) - { - m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); - } + void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ); - virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override - { - return m_ChunkMap->ForEachChunkInRect(a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ, a_Callback); - } + virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override; - virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override - { - return m_ChunkMap->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); - } + virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override; bool DigBlock(cWorldInterface & a_WorldInterface, int a_X, int a_Y, int a_Z); diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index b43d011d8..27e06fff3 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -2,14 +2,15 @@ #pragma once #include "BroadcastInterface.h" -#include "../Mobs/Monster.h" +#include "../Mobs/MonsterTypes.h" class cItems; typedef cItemCallback cBlockEntityCallback; - +class cMonster; +class cPlayer; class cWorldInterface @@ -33,7 +34,7 @@ public: virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false) = 0; /** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */ - virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) = 0; + virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) = 0; /** 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) = 0; diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 9bcdcffeb..4581eeda8 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -334,10 +334,10 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) cMonster * Monster = (cMonster *)this; switch (Monster->GetMobType()) { - case cMonster::mtSkeleton: - case cMonster::mtZombie: - case cMonster::mtWither: - case cMonster::mtZombiePigman: + case mtSkeleton: + case mtZombie: + case mtWither: + case mtZombiePigman: { a_TDI.FinalDamage += (int)ceil(2.5 * SmiteLevel); break; @@ -352,9 +352,9 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) cMonster * Monster = (cMonster *)this; switch (Monster->GetMobType()) { - case cMonster::mtSpider: - case cMonster::mtCaveSpider: - case cMonster::mtSilverfish: + case mtSpider: + case mtCaveSpider: + case mtSilverfish: { a_TDI.RawDamage += (int)ceil(2.5 * BaneOfArthropodsLevel); // TODO: Add slowness effect @@ -384,9 +384,9 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) cMonster * Monster = (cMonster *)this; switch (Monster->GetMobType()) { - case cMonster::mtGhast: - case cMonster::mtZombiePigman: - case cMonster::mtMagmaCube: + case mtGhast: + case mtZombiePigman: + case mtMagmaCube: { break; }; diff --git a/src/Entities/EntityEffect.cpp b/src/Entities/EntityEffect.cpp index f08755674..8235275a6 100644 --- a/src/Entities/EntityEffect.cpp +++ b/src/Entities/EntityEffect.cpp @@ -349,8 +349,8 @@ void cEntityEffectPoison::OnTick(cPawn & a_Target) // Doesn't effect undead mobs, spiders if ( Target.IsUndead() || - (Target.GetMobType() == cMonster::mtSpider) || - (Target.GetMobType() == cMonster::mtCaveSpider) + (Target.GetMobType() == mtSpider) || + (Target.GetMobType() == mtCaveSpider) ) { return; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index b0da6965a..4458cd32f 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -2003,8 +2003,8 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos) cMonster * Monster = (cMonster *)m_AttachedTo; switch (Monster->GetMobType()) { - case cMonster::mtPig: m_Stats.AddValue(statDistPig, Value); break; - case cMonster::mtHorse: m_Stats.AddValue(statDistHorse, Value); break; + case mtPig: m_Stats.AddValue(statDistPig, Value); break; + case mtHorse: m_Stats.AddValue(statDistHorse, Value); break; default: break; } break; diff --git a/src/Entities/ThrownEggEntity.cpp b/src/Entities/ThrownEggEntity.cpp index 456083108..5ae85bee8 100644 --- a/src/Entities/ThrownEggEntity.cpp +++ b/src/Entities/ThrownEggEntity.cpp @@ -48,13 +48,13 @@ void cThrownEggEntity::TrySpawnChicken(const Vector3d & a_HitPos) { if (m_World->GetTickRandomNumber(7) == 1) { - m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, cMonster::mtChicken); + m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken); } else if (m_World->GetTickRandomNumber(32) == 1) { - m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, cMonster::mtChicken); - m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, cMonster::mtChicken); - m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, cMonster::mtChicken); - m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, cMonster::mtChicken); + m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken); + m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken); + m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken); + m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken); } } diff --git a/src/Entities/ThrownSnowballEntity.cpp b/src/Entities/ThrownSnowballEntity.cpp index d94e75898..496397100 100644 --- a/src/Entities/ThrownSnowballEntity.cpp +++ b/src/Entities/ThrownSnowballEntity.cpp @@ -32,8 +32,8 @@ void cThrownSnowballEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & int TotalDamage = 0; if (a_EntityHit.IsMob()) { - cMonster::eType MobType = ((cMonster &) a_EntityHit).GetMobType(); - if (MobType == cMonster::mtBlaze) + eMonsterType MobType = ((cMonster &) a_EntityHit).GetMobType(); + if (MobType == mtBlaze) { TotalDamage = 3; } diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index eb57a5faa..96e3dc26b 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -15,6 +15,7 @@ #include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway() #include "../Simulator/FireSimulator.h" #include "../World.h" +#include "inifile/iniFile.h" diff --git a/src/Globals.h b/src/Globals.h index de1024010..c75c4e99b 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -261,6 +261,27 @@ void inline LOGERROR(const char* a_Format, ...) vprintf(a_Format, argList); va_end(argList); } + +void inline LOGWARNING(const char* a_Format, ...) FORMATSTRING(1, 2); + +void inline LOGWARNING(const char* a_Format, ...) +{ + va_list argList; + va_start(argList, a_Format); + vprintf(a_Format, argList); + va_end(argList); +} + +void inline LOGD(const char* a_Format, ...) FORMATSTRING(1, 2); + +void inline LOGD(const char* a_Format, ...) +{ + va_list argList; + va_start(argList, a_Format); + vprintf(a_Format, argList); + va_end(argList); +} + #endif diff --git a/src/Items/ItemSpawnEgg.h b/src/Items/ItemSpawnEgg.h index bba97afa1..617ecd808 100644 --- a/src/Items/ItemSpawnEgg.h +++ b/src/Items/ItemSpawnEgg.h @@ -33,9 +33,9 @@ public: a_BlockY--; } - cMonster::eType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage); + eMonsterType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage); if ( - (MonsterType != cMonster::mtInvalidType) && // Valid monster type + (MonsterType != mtInvalidType) && // Valid monster type (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) >= 0)) // Spawning succeeded { if (!a_Player->IsGameModeCreative()) @@ -52,36 +52,36 @@ public: /** Converts the Spawn egg item damage to the monster type to spawn. Returns mtInvalidType for invalid damage values. */ - static cMonster::eType ItemDamageToMonsterType(short a_ItemDamage) + static eMonsterType ItemDamageToMonsterType(short a_ItemDamage) { switch (a_ItemDamage) { - case E_META_SPAWN_EGG_BAT: return cMonster::mtBat; - case E_META_SPAWN_EGG_BLAZE: return cMonster::mtBlaze; - case E_META_SPAWN_EGG_CAVE_SPIDER: return cMonster::mtCaveSpider; - case E_META_SPAWN_EGG_CHICKEN: return cMonster::mtChicken; - case E_META_SPAWN_EGG_COW: return cMonster::mtCow; - case E_META_SPAWN_EGG_CREEPER: return cMonster::mtCreeper; - case E_META_SPAWN_EGG_ENDERMAN: return cMonster::mtEnderman; - case E_META_SPAWN_EGG_GHAST: return cMonster::mtGhast; - case E_META_SPAWN_EGG_HORSE: return cMonster::mtHorse; - case E_META_SPAWN_EGG_MAGMA_CUBE: return cMonster::mtMagmaCube; - case E_META_SPAWN_EGG_MOOSHROOM: return cMonster::mtMooshroom; - case E_META_SPAWN_EGG_OCELOT: return cMonster::mtOcelot; - case E_META_SPAWN_EGG_PIG: return cMonster::mtPig; - case E_META_SPAWN_EGG_SHEEP: return cMonster::mtSheep; - case E_META_SPAWN_EGG_SILVERFISH: return cMonster::mtSilverfish; - case E_META_SPAWN_EGG_SKELETON: return cMonster::mtSkeleton; - case E_META_SPAWN_EGG_SLIME: return cMonster::mtSlime; - case E_META_SPAWN_EGG_SPIDER: return cMonster::mtSpider; - case E_META_SPAWN_EGG_SQUID: return cMonster::mtSquid; - case E_META_SPAWN_EGG_VILLAGER: return cMonster::mtVillager; - case E_META_SPAWN_EGG_WITCH: return cMonster::mtWitch; - case E_META_SPAWN_EGG_WOLF: return cMonster::mtWolf; - case E_META_SPAWN_EGG_ZOMBIE: return cMonster::mtZombie; - case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return cMonster::mtZombiePigman; + case E_META_SPAWN_EGG_BAT: return mtBat; + case E_META_SPAWN_EGG_BLAZE: return mtBlaze; + case E_META_SPAWN_EGG_CAVE_SPIDER: return mtCaveSpider; + case E_META_SPAWN_EGG_CHICKEN: return mtChicken; + case E_META_SPAWN_EGG_COW: return mtCow; + case E_META_SPAWN_EGG_CREEPER: return mtCreeper; + case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman; + case E_META_SPAWN_EGG_GHAST: return mtGhast; + case E_META_SPAWN_EGG_HORSE: return mtHorse; + case E_META_SPAWN_EGG_MAGMA_CUBE: return mtMagmaCube; + case E_META_SPAWN_EGG_MOOSHROOM: return mtMooshroom; + case E_META_SPAWN_EGG_OCELOT: return mtOcelot; + case E_META_SPAWN_EGG_PIG: return mtPig; + case E_META_SPAWN_EGG_SHEEP: return mtSheep; + case E_META_SPAWN_EGG_SILVERFISH: return mtSilverfish; + case E_META_SPAWN_EGG_SKELETON: return mtSkeleton; + case E_META_SPAWN_EGG_SLIME: return mtSlime; + case E_META_SPAWN_EGG_SPIDER: return mtSpider; + case E_META_SPAWN_EGG_SQUID: return mtSquid; + case E_META_SPAWN_EGG_VILLAGER: return mtVillager; + case E_META_SPAWN_EGG_WITCH: return mtWitch; + case E_META_SPAWN_EGG_WOLF: return mtWolf; + case E_META_SPAWN_EGG_ZOMBIE: return mtZombie; + case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return mtZombiePigman; } - return cMonster::mtInvalidType; + return mtInvalidType; } } ; diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp index db05b70af..ea3fe8c72 100644 --- a/src/MobSpawner.cpp +++ b/src/MobSpawner.cpp @@ -8,12 +8,12 @@ -cMobSpawner::cMobSpawner(cMonster::eFamily a_MonsterFamily, const std::set& a_AllowedTypes) : +cMobSpawner::cMobSpawner(cMonster::eFamily a_MonsterFamily, const std::set& a_AllowedTypes) : m_MonsterFamily(a_MonsterFamily), m_NewPack(true), - m_MobType(cMonster::mtInvalidType) + m_MobType(mtInvalidType) { - for (std::set::const_iterator itr = a_AllowedTypes.begin(); itr != a_AllowedTypes.end(); ++itr) + for (std::set::const_iterator itr = a_AllowedTypes.begin(); itr != a_AllowedTypes.end(); ++itr) { if (cMonster::FamilyFromType(*itr) == a_MonsterFamily) { @@ -44,9 +44,9 @@ bool cMobSpawner::CheckPackCenter(BLOCKTYPE a_BlockType) -void cMobSpawner::addIfAllowed(cMonster::eType toAdd, std::set& toAddIn) +void cMobSpawner::addIfAllowed(eMonsterType toAdd, std::set& toAddIn) { - std::set::iterator itr = m_AllowedTypes.find(toAdd); + std::set::iterator itr = m_AllowedTypes.find(toAdd); if (itr != m_AllowedTypes.end()) { toAddIn.insert(toAdd); @@ -57,49 +57,49 @@ void cMobSpawner::addIfAllowed(cMonster::eType toAdd, std::set& -cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) +eMonsterType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) { - std::set allowedMobs; + std::set allowedMobs; if (a_Biome == biMushroomIsland || a_Biome == biMushroomShore) { - addIfAllowed(cMonster::mtMooshroom, allowedMobs); + addIfAllowed(mtMooshroom, allowedMobs); } else if (a_Biome == biNether) { - addIfAllowed(cMonster::mtGhast, allowedMobs); - addIfAllowed(cMonster::mtZombiePigman, allowedMobs); - addIfAllowed(cMonster::mtMagmaCube, allowedMobs); + addIfAllowed(mtGhast, allowedMobs); + addIfAllowed(mtZombiePigman, allowedMobs); + addIfAllowed(mtMagmaCube, allowedMobs); } else if (a_Biome == biEnd) { - addIfAllowed(cMonster::mtEnderman, allowedMobs); + addIfAllowed(mtEnderman, allowedMobs); } else { - addIfAllowed(cMonster::mtBat, allowedMobs); - addIfAllowed(cMonster::mtSpider, allowedMobs); - addIfAllowed(cMonster::mtZombie, allowedMobs); - addIfAllowed(cMonster::mtSkeleton, allowedMobs); - addIfAllowed(cMonster::mtCreeper, allowedMobs); - addIfAllowed(cMonster::mtSquid, allowedMobs); + addIfAllowed(mtBat, allowedMobs); + addIfAllowed(mtSpider, allowedMobs); + addIfAllowed(mtZombie, allowedMobs); + addIfAllowed(mtSkeleton, allowedMobs); + addIfAllowed(mtCreeper, allowedMobs); + addIfAllowed(mtSquid, allowedMobs); if (a_Biome != biDesert && a_Biome != biBeach && a_Biome != biOcean) { - addIfAllowed(cMonster::mtSheep, allowedMobs); - addIfAllowed(cMonster::mtPig, allowedMobs); - addIfAllowed(cMonster::mtCow, allowedMobs); - addIfAllowed(cMonster::mtChicken, allowedMobs); - addIfAllowed(cMonster::mtEnderman, allowedMobs); - addIfAllowed(cMonster::mtSlime, allowedMobs); // MG TODO : much more complicated rule + addIfAllowed(mtSheep, allowedMobs); + addIfAllowed(mtPig, allowedMobs); + addIfAllowed(mtCow, allowedMobs); + addIfAllowed(mtChicken, allowedMobs); + addIfAllowed(mtEnderman, allowedMobs); + addIfAllowed(mtSlime, allowedMobs); // MG TODO : much more complicated rule if (a_Biome == biForest || a_Biome == biForestHills || a_Biome == biTaiga || a_Biome == biTaigaHills) { - addIfAllowed(cMonster::mtWolf, allowedMobs); + addIfAllowed(mtWolf, allowedMobs); } else if (a_Biome == biJungle || a_Biome == biJungleHills) { - addIfAllowed(cMonster::mtOcelot, allowedMobs); + addIfAllowed(mtOcelot, allowedMobs); } } } @@ -107,7 +107,7 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) size_t allowedMobsSize = allowedMobs.size(); if (allowedMobsSize > 0) { - std::set::iterator itr = allowedMobs.begin(); + std::set::iterator itr = allowedMobs.begin(); int iRandom = m_Random.NextInt((int)allowedMobsSize, a_Biome); for (int i = 0; i < iRandom; i++) @@ -117,14 +117,14 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) return *itr; } - return cMonster::mtInvalidType; + return mtInvalidType; } -bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome) +bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, eMonsterType a_MobType, EMCSBiome a_Biome) { BLOCKTYPE TargetBlock = E_BLOCK_AIR; if (m_AllowedTypes.find(a_MobType) != m_AllowedTypes.end() && a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, TargetBlock)) @@ -143,21 +143,21 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R switch (a_MobType) { - case cMonster::mtSquid: + case mtSquid: { return IsBlockWater(TargetBlock) && (a_RelY >= 45) && (a_RelY <= 62); } - case cMonster::mtBat: + case mtBat: { return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4) && (TargetBlock == E_BLOCK_AIR) && !cBlockInfo::IsTransparent(BlockAbove); } - case cMonster::mtChicken: - case cMonster::mtCow: - case cMonster::mtPig: - case cMonster::mtHorse: - case cMonster::mtSheep: + case mtChicken: + case mtCow: + case mtPig: + case mtHorse: + case mtSheep: { return ( (TargetBlock == E_BLOCK_AIR) && @@ -168,7 +168,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R ); } - case cMonster::mtOcelot: + case mtOcelot: { return ( (TargetBlock == E_BLOCK_AIR) && @@ -181,7 +181,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R ); } - case cMonster::mtEnderman: + case mtEnderman: { if (a_RelY < 250) { @@ -202,7 +202,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R break; } - case cMonster::mtSpider: + case mtSpider: { bool CanSpawn = true; bool HasFloor = false; @@ -228,9 +228,9 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R return CanSpawn && HasFloor && (SkyLight <= 7) && (BlockLight <= 7); } - case cMonster::mtCreeper: - case cMonster::mtSkeleton: - case cMonster::mtZombie: + case mtCreeper: + case mtSkeleton: + case mtZombie: { return ( (TargetBlock == E_BLOCK_AIR) && @@ -242,8 +242,8 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R ); } - case cMonster::mtMagmaCube: - case cMonster::mtSlime: + case mtMagmaCube: + case mtSlime: { return ( (TargetBlock == E_BLOCK_AIR) && @@ -255,8 +255,8 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R ); } - case cMonster::mtGhast: - case cMonster::mtZombiePigman: + case mtGhast: + case mtZombiePigman: { return ( (TargetBlock == E_BLOCK_AIR) && @@ -266,7 +266,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R ); } - case cMonster::mtWolf: + case mtWolf: { return ( (TargetBlock == E_BLOCK_GRASS) && @@ -305,15 +305,15 @@ cMonster* cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, if (m_NewPack) { m_MobType = ChooseMobType(a_Biome); - if (m_MobType == cMonster::mtInvalidType) + if (m_MobType == mtInvalidType) { return toReturn; } - if (m_MobType == cMonster::mtWolf) + if (m_MobType == mtWolf) { a_MaxPackSize = 8; } - else if (m_MobType == cMonster::mtGhast) + else if (m_MobType == mtGhast) { a_MaxPackSize = 1; } diff --git a/src/MobSpawner.h b/src/MobSpawner.h index f3c56fe2d..6b3a913ec 100644 --- a/src/MobSpawner.h +++ b/src/MobSpawner.h @@ -30,7 +30,7 @@ public : // a_AllowedTypes is the set of types allowed for mobs it will spawn. Empty set // would result in no spawn at all // Allowed mobs thah are not of the right Family will not be include (no warning) - cMobSpawner(cMonster::eFamily MobFamily, const std::set & a_AllowedTypes); + cMobSpawner(cMonster::eFamily MobFamily, const std::set & a_AllowedTypes); /// Check if specified block can be a Pack center for this spawner bool CheckPackCenter(BLOCKTYPE a_BlockType); @@ -53,20 +53,20 @@ public : protected : // return true if specified type of mob can spawn on specified block - bool CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome); + bool CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, eMonsterType a_MobType, EMCSBiome a_Biome); // return a random type that can spawn on specified biome. // returns E_ENTITY_TYPE_DONOTUSE if none is possible - cMonster::eType ChooseMobType(EMCSBiome a_Biome); + eMonsterType ChooseMobType(EMCSBiome a_Biome); // add toAdd inside toAddIn, if toAdd is in m_AllowedTypes - void addIfAllowed(cMonster::eType toAdd, std::set & toAddIn); + void addIfAllowed(eMonsterType toAdd, std::set & toAddIn); protected : cMonster::eFamily m_MonsterFamily; - std::set m_AllowedTypes; + std::set m_AllowedTypes; bool m_NewPack; - cMonster::eType m_MobType; + eMonsterType m_MobType; std::set m_Spawned; cFastRandom m_Random; } ; diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp index 5f5b1853d..be2f71f7a 100644 --- a/src/Mobs/AggressiveMonster.cpp +++ b/src/Mobs/AggressiveMonster.cpp @@ -11,7 +11,7 @@ -cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : +cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height) { m_EMPersonality = AGGRESSIVE; diff --git a/src/Mobs/AggressiveMonster.h b/src/Mobs/AggressiveMonster.h index d70ff04a3..2549ba2d3 100644 --- a/src/Mobs/AggressiveMonster.h +++ b/src/Mobs/AggressiveMonster.h @@ -14,7 +14,7 @@ class cAggressiveMonster : public: - cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); virtual void Tick (float a_Dt, cChunk & a_Chunk) override; virtual void InStateChasing(float a_Dt) override; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index f7ee0b0c0..b6e22c0ee 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -24,38 +24,38 @@ The strings need to be lowercase (for more efficient comparisons in StringToMobT */ static const struct { - cMonster::eType m_Type; + eMonsterType m_Type; const char * m_lcName; } g_MobTypeNames[] = { - {cMonster::mtBat, "bat"}, - {cMonster::mtBlaze, "blaze"}, - {cMonster::mtCaveSpider, "cavespider"}, - {cMonster::mtChicken, "chicken"}, - {cMonster::mtCow, "cow"}, - {cMonster::mtCreeper, "creeper"}, - {cMonster::mtEnderman, "enderman"}, - {cMonster::mtEnderDragon, "enderdragon"}, - {cMonster::mtGhast, "ghast"}, - {cMonster::mtHorse, "horse"}, - {cMonster::mtIronGolem, "irongolem"}, - {cMonster::mtMagmaCube, "magmacube"}, - {cMonster::mtMooshroom, "mooshroom"}, - {cMonster::mtOcelot, "ocelot"}, - {cMonster::mtPig, "pig"}, - {cMonster::mtSheep, "sheep"}, - {cMonster::mtSilverfish, "silverfish"}, - {cMonster::mtSkeleton, "skeleton"}, - {cMonster::mtSlime, "slime"}, - {cMonster::mtSnowGolem, "snowgolem"}, - {cMonster::mtSpider, "spider"}, - {cMonster::mtSquid, "squid"}, - {cMonster::mtVillager, "villager"}, - {cMonster::mtWitch, "witch"}, - {cMonster::mtWither, "wither"}, - {cMonster::mtWolf, "wolf"}, - {cMonster::mtZombie, "zombie"}, - {cMonster::mtZombiePigman, "zombiepigman"}, + {mtBat, "bat"}, + {mtBlaze, "blaze"}, + {mtCaveSpider, "cavespider"}, + {mtChicken, "chicken"}, + {mtCow, "cow"}, + {mtCreeper, "creeper"}, + {mtEnderman, "enderman"}, + {mtEnderDragon, "enderdragon"}, + {mtGhast, "ghast"}, + {mtHorse, "horse"}, + {mtIronGolem, "irongolem"}, + {mtMagmaCube, "magmacube"}, + {mtMooshroom, "mooshroom"}, + {mtOcelot, "ocelot"}, + {mtPig, "pig"}, + {mtSheep, "sheep"}, + {mtSilverfish, "silverfish"}, + {mtSkeleton, "skeleton"}, + {mtSlime, "slime"}, + {mtSnowGolem, "snowgolem"}, + {mtSpider, "spider"}, + {mtSquid, "squid"}, + {mtVillager, "villager"}, + {mtWitch, "witch"}, + {mtWither, "wither"}, + {mtWolf, "wolf"}, + {mtZombie, "zombie"}, + {mtZombiePigman, "zombiepigman"}, } ; @@ -65,7 +65,7 @@ static const struct //////////////////////////////////////////////////////////////////////////////// // cMonster: -cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) +cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(etMonster, a_Width, a_Height) , m_EMState(IDLE) , m_EMPersonality(AGGRESSIVE) @@ -485,50 +485,50 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI) switch (m_MobType) { // Animals - case cMonster::mtChicken: - case cMonster::mtCow: - case cMonster::mtHorse: - case cMonster::mtPig: - case cMonster::mtSheep: - case cMonster::mtSquid: - case cMonster::mtMooshroom: - case cMonster::mtOcelot: - case cMonster::mtWolf: + case mtChicken: + case mtCow: + case mtHorse: + case mtPig: + case mtSheep: + case mtSquid: + case mtMooshroom: + case mtOcelot: + case mtWolf: { Reward = m_World->GetTickRandomNumber(2) + 1; break; } // Monsters - case cMonster::mtCaveSpider: - case cMonster::mtCreeper: - case cMonster::mtEnderman: - case cMonster::mtGhast: - case cMonster::mtSilverfish: - case cMonster::mtSkeleton: - case cMonster::mtSpider: - case cMonster::mtWitch: - case cMonster::mtZombie: - case cMonster::mtZombiePigman: - case cMonster::mtSlime: - case cMonster::mtMagmaCube: + case mtCaveSpider: + case mtCreeper: + case mtEnderman: + case mtGhast: + case mtSilverfish: + case mtSkeleton: + case mtSpider: + case mtWitch: + case mtZombie: + case mtZombiePigman: + case mtSlime: + case mtMagmaCube: { Reward = 6 + (m_World->GetTickRandomNumber(2)); break; } - case cMonster::mtBlaze: + case mtBlaze: { Reward = 10; break; } // Bosses - case cMonster::mtEnderDragon: + case mtEnderDragon: { Reward = 12000; break; } - case cMonster::mtWither: + case mtWither: { Reward = 50; break; @@ -697,7 +697,7 @@ bool cMonster::IsUndead(void) -AString cMonster::MobTypeToString(cMonster::eType a_MobType) +AString cMonster::MobTypeToString(eMonsterType a_MobType) { // Mob types aren't sorted, so we need to search linearly: for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) @@ -716,7 +716,7 @@ AString cMonster::MobTypeToString(cMonster::eType a_MobType) -cMonster::eType cMonster::StringToMobType(const AString & a_Name) +eMonsterType cMonster::StringToMobType(const AString & a_Name) { AString lcName = StrToLower(a_Name); @@ -757,7 +757,7 @@ cMonster::eType cMonster::StringToMobType(const AString & a_Name) -cMonster::eFamily cMonster::FamilyFromType(eType a_Type) +cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type) { // Passive-agressive mobs are counted in mob spawning code as passive @@ -822,7 +822,7 @@ int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) -cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType) +cMonster * cMonster::NewMonsterFromType(eMonsterType a_MobType) { cFastRandom Random; cMonster * toReturn = NULL; diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index cdbd26c09..60bf36c7a 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -6,6 +6,7 @@ #include "../BlockID.h" #include "../Item.h" #include "../Enchantments.h" +#include "MonsterTypes.h" @@ -15,50 +16,13 @@ class cClientHandle; class cWorld; - - // tolua_begin class cMonster : public cPawn { typedef cPawn super; public: - /// This identifies individual monster type, as well as their network type-ID - enum eType - { - mtInvalidType = -1, - - mtBat = E_META_SPAWN_EGG_BAT, - mtBlaze = E_META_SPAWN_EGG_BLAZE, - mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER, - mtChicken = E_META_SPAWN_EGG_CHICKEN, - mtCow = E_META_SPAWN_EGG_COW, - mtCreeper = E_META_SPAWN_EGG_CREEPER, - mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON, - mtEnderman = E_META_SPAWN_EGG_ENDERMAN, - mtGhast = E_META_SPAWN_EGG_GHAST, - mtGiant = E_META_SPAWN_EGG_GIANT, - mtHorse = E_META_SPAWN_EGG_HORSE, - mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, - mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, - mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM, - mtOcelot = E_META_SPAWN_EGG_OCELOT, - mtPig = E_META_SPAWN_EGG_PIG, - mtSheep = E_META_SPAWN_EGG_SHEEP, - mtSilverfish = E_META_SPAWN_EGG_SILVERFISH, - mtSkeleton = E_META_SPAWN_EGG_SKELETON, - mtSlime = E_META_SPAWN_EGG_SLIME, - mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM, - mtSpider = E_META_SPAWN_EGG_SPIDER, - mtSquid = E_META_SPAWN_EGG_SQUID, - mtVillager = E_META_SPAWN_EGG_VILLAGER, - mtWitch = E_META_SPAWN_EGG_WITCH, - mtWither = E_META_SPAWN_EGG_WITHER, - mtWolf = E_META_SPAWN_EGG_WOLF, - mtZombie = E_META_SPAWN_EGG_ZOMBIE, - mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN, - } ; - + enum eFamily { mfHostile = 0, // Spider, Zombies ... @@ -80,7 +44,7 @@ public: a_MobType is the type of the mob (also used in the protocol ( http://wiki.vg/Entities#Mobs 2012_12_22)) a_SoundHurt and a_SoundDeath are assigned into m_SoundHurt and m_SoundDeath, respectively */ - cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); CLASS_PROTODEF(cMonster) @@ -96,7 +60,7 @@ public: virtual bool ReachedDestination(void); // tolua_begin - eType GetMobType(void) const {return m_MobType; } + eMonsterType GetMobType(void) const {return m_MobType; } eFamily GetMobFamily(void) const; // tolua_end @@ -146,13 +110,13 @@ public: // tolua_begin /// Translates MobType enum to a string, empty string if unknown - static AString MobTypeToString(eType a_MobType); + static AString MobTypeToString(eMonsterType a_MobType); /// Translates MobType string to the enum, mtInvalidType if not recognized - static eType StringToMobType(const AString & a_MobTypeName); + static eMonsterType StringToMobType(const AString & a_MobTypeName); /// Returns the mob family based on the type - static eFamily FamilyFromType(eType a_MobType); + static eFamily FamilyFromType(eMonsterType a_MobType); /// Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family static int GetSpawnDelay(cMonster::eFamily a_MobFamily); @@ -163,7 +127,7 @@ public: a_MobType is the type of the mob to be created Asserts and returns null if mob type is not specified */ - static cMonster * NewMonsterFromType(eType a_MobType); + static cMonster * NewMonsterFromType(eMonsterType a_MobType); protected: @@ -227,7 +191,7 @@ protected: float m_IdleInterval; float m_DestroyTimer; - eType m_MobType; + eMonsterType m_MobType; AString m_SoundHurt; AString m_SoundDeath; diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h new file mode 100644 index 000000000..7a73e99f4 --- /dev/null +++ b/src/Mobs/MonsterTypes.h @@ -0,0 +1,41 @@ + +#pragma once + +/// This identifies individual monster type, as well as their network type-ID +// tolua_begin +enum eMonsterType +{ + mtInvalidType = -1, + + mtBat = E_META_SPAWN_EGG_BAT, + mtBlaze = E_META_SPAWN_EGG_BLAZE, + mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER, + mtChicken = E_META_SPAWN_EGG_CHICKEN, + mtCow = E_META_SPAWN_EGG_COW, + mtCreeper = E_META_SPAWN_EGG_CREEPER, + mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON, + mtEnderman = E_META_SPAWN_EGG_ENDERMAN, + mtGhast = E_META_SPAWN_EGG_GHAST, + mtGiant = E_META_SPAWN_EGG_GIANT, + mtHorse = E_META_SPAWN_EGG_HORSE, + mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, + mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, + mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM, + mtOcelot = E_META_SPAWN_EGG_OCELOT, + mtPig = E_META_SPAWN_EGG_PIG, + mtSheep = E_META_SPAWN_EGG_SHEEP, + mtSilverfish = E_META_SPAWN_EGG_SILVERFISH, + mtSkeleton = E_META_SPAWN_EGG_SKELETON, + mtSlime = E_META_SPAWN_EGG_SLIME, + mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM, + mtSpider = E_META_SPAWN_EGG_SPIDER, + mtSquid = E_META_SPAWN_EGG_SQUID, + mtVillager = E_META_SPAWN_EGG_VILLAGER, + mtWitch = E_META_SPAWN_EGG_WITCH, + mtWither = E_META_SPAWN_EGG_WITHER, + mtWolf = E_META_SPAWN_EGG_WOLF, + mtZombie = E_META_SPAWN_EGG_ZOMBIE, + mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN, +} ; +// tolua_end + diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp index 81bd3e3b4..99958720f 100644 --- a/src/Mobs/Mooshroom.cpp +++ b/src/Mobs/Mooshroom.cpp @@ -67,7 +67,7 @@ void cMooshroom::OnRightClicked(cPlayer & a_Player) cItems Drops; Drops.push_back(cItem(E_BLOCK_RED_MUSHROOM, 5, 0)); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); - m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), cMonster::mtCow); + m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtCow); Destroy(); } break; } diff --git a/src/Mobs/PassiveAggressiveMonster.cpp b/src/Mobs/PassiveAggressiveMonster.cpp index 24501b1ba..e0cc2fd21 100644 --- a/src/Mobs/PassiveAggressiveMonster.cpp +++ b/src/Mobs/PassiveAggressiveMonster.cpp @@ -9,7 +9,7 @@ -cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : +cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height) { m_EMPersonality = PASSIVE; diff --git a/src/Mobs/PassiveAggressiveMonster.h b/src/Mobs/PassiveAggressiveMonster.h index a0da50e8e..72f472281 100644 --- a/src/Mobs/PassiveAggressiveMonster.h +++ b/src/Mobs/PassiveAggressiveMonster.h @@ -13,7 +13,7 @@ class cPassiveAggressiveMonster : typedef cAggressiveMonster super; public: - cPassiveAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cPassiveAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; } ; diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp index 2861d7314..be3043e3d 100644 --- a/src/Mobs/PassiveMonster.cpp +++ b/src/Mobs/PassiveMonster.cpp @@ -8,7 +8,7 @@ -cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : +cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height) { m_EMPersonality = PASSIVE; diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h index 70574585a..9221d9a6e 100644 --- a/src/Mobs/PassiveMonster.h +++ b/src/Mobs/PassiveMonster.h @@ -13,7 +13,7 @@ class cPassiveMonster : typedef cMonster super; public: - cPassiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); virtual void Tick(float a_Dt, cChunk & a_Chunk) override; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index a66c64309..4a69bc1ac 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -1946,7 +1946,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) { switch (a_Mob.GetMobType()) { - case cMonster::mtCreeper: + case mtCreeper: { WriteByte(0x10); WriteChar(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up? @@ -1954,25 +1954,25 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged? break; } - case cMonster::mtBat: + case mtBat: { WriteByte(0x10); WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? break; } - case cMonster::mtPig: + case mtPig: { WriteByte(0x10); WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? break; } - case cMonster::mtVillager: + case mtVillager: { WriteByte(0x50); WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? break; } - case cMonster::mtZombie: + case mtZombie: { WriteByte(0xC); WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Baby zombie? @@ -1982,13 +1982,13 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? break; } - case cMonster::mtGhast: + case mtGhast: { WriteByte(0x10); WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to spit a flameball? break; } - case cMonster::mtWolf: + case mtWolf: { Byte WolfStatus = 0; if (((const cWolf &)a_Mob).IsSitting()) @@ -2012,7 +2012,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode? break; } - case cMonster::mtSheep: + case mtSheep: { // [1](1111) // [] = Is sheared? () = Color, from 0 to 15 @@ -2028,7 +2028,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(SheepMetadata); break; } - case cMonster::mtEnderman: + case mtEnderman: { WriteByte(0x10); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house @@ -2038,19 +2038,19 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face? break; } - case cMonster::mtSkeleton: + case mtSkeleton: { WriteByte(0xD); WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not break; } - case cMonster::mtWitch: + case mtWitch: { WriteByte(0x15); WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything break; } - case cMonster::mtWither: + case mtWither: { WriteByte(0x54); // Int at index 20 WriteInt((Int32)((const cWither &)a_Mob).GetWitherInvulnerableTicks()); @@ -2058,11 +2058,11 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteFloat((float)(a_Mob.GetHealth())); break; } - case cMonster::mtSlime: - case cMonster::mtMagmaCube: + case mtSlime: + case mtMagmaCube: { WriteByte(0x10); - if (a_Mob.GetMobType() == cMonster::mtSlime) + if (a_Mob.GetMobType() == mtSlime) { WriteByte((Byte)((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME } @@ -2072,7 +2072,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) } break; } - case cMonster::mtHorse: + case mtHorse: { int Flags = 0; if (((const cHorse &)a_Mob).IsTame()) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f24ef320d..ac7a180d4 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2839,7 +2839,7 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) { switch (a_Mob.GetMobType()) { - case cMonster::mtCreeper: + case mtCreeper: { WriteByte(0x10); WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); @@ -2848,28 +2848,28 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) break; } - case cMonster::mtBat: + case mtBat: { WriteByte(0x10); WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); break; } - case cMonster::mtPig: + case mtPig: { WriteByte(0x10); WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); break; } - case cMonster::mtVillager: + case mtVillager: { WriteByte(0x50); WriteInt(((const cVillager &)a_Mob).GetVilType()); break; } - case cMonster::mtZombie: + case mtZombie: { WriteByte(0x0c); WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); @@ -2880,14 +2880,14 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) break; } - case cMonster::mtGhast: + case mtGhast: { WriteByte(0x10); WriteByte(((const cGhast &)a_Mob).IsCharging()); break; } - case cMonster::mtWolf: + case mtWolf: { const cWolf & Wolf = (const cWolf &)a_Mob; Byte WolfStatus = 0; @@ -2915,7 +2915,7 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) break; } - case cMonster::mtSheep: + case mtSheep: { WriteByte(0x10); Byte SheepMetadata = 0; @@ -2928,7 +2928,7 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) break; } - case cMonster::mtEnderman: + case mtEnderman: { WriteByte(0x10); WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); @@ -2939,21 +2939,21 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) break; } - case cMonster::mtSkeleton: + case mtSkeleton: { WriteByte(0x0d); WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); break; } - case cMonster::mtWitch: + case mtWitch: { WriteByte(0x15); WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); break; } - case cMonster::mtWither: + case mtWither: { WriteByte(0x54); // Int at index 20 WriteInt(((const cWither &)a_Mob).GetWitherInvulnerableTicks()); @@ -2962,21 +2962,21 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) break; } - case cMonster::mtSlime: + case mtSlime: { WriteByte(0x10); WriteByte(((const cSlime &)a_Mob).GetSize()); break; } - case cMonster::mtMagmaCube: + case mtMagmaCube: { WriteByte(0x10); WriteByte(((const cMagmaCube &)a_Mob).GetSize()); break; } - case cMonster::mtHorse: + case mtHorse: { const cHorse & Horse = (const cHorse &)a_Mob; int Flags = 0; diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 55cc014f3..df05a9fee 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -1,6 +1,9 @@ #include "Globals.h" +#include "BlockEntities/ChestEntity.h" + +typedef cItemCallback cChestCallback; #include "IncrementalRedstoneSimulator.inc" @@ -13,7 +16,6 @@ #include "Blocks/BlockTripwireHook.h" #include "Blocks/BlockDoor.h" #include "Blocks/BlockPiston.h" -#include "BlockEntities/ChestEntity.h" cRedstoneSimulator * MakeIncrementalRedstoneSimulator(cWorld & a_World) { diff --git a/src/Simulator/IncrementalRedstoneSimulator.inc b/src/Simulator/IncrementalRedstoneSimulator.inc index e3c856328..eee2daa7c 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.inc +++ b/src/Simulator/IncrementalRedstoneSimulator.inc @@ -6,6 +6,8 @@ #include "RedstoneSimulator.h" +typedef cItemCallback cEntityCallback; + @@ -1630,7 +1632,7 @@ void cIncrementalRedstoneSimulator +class cGetTrappedChestPlayers : + public cItemCallback +{ +public: + cGetTrappedChestPlayers(void) : + m_NumberOfPlayers(0) + { + } + virtual ~cGetTrappedChestPlayers() + { + } + virtual bool Item(ChestType * a_Chest) override + { + ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST); + m_NumberOfPlayers = a_Chest->GetNumberOfPlayers(); + return (m_NumberOfPlayers <= 0); + } -template class GetHandlerCompileTime, class ChestType> -void cIncrementalRedstoneSimulator::HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) -{ - class cGetTrappedChestPlayers : - public cChestCallback + unsigned char GetPowerLevel(void) const { - public: - cGetTrappedChestPlayers(void) : - m_NumberOfPlayers(0) - { - } + return std::min(m_NumberOfPlayers, MAX_POWER_LEVEL); + } - virtual bool Item(ChestType * a_Chest) override - { - ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST); - m_NumberOfPlayers = a_Chest->GetNumberOfPlayers(); - return (m_NumberOfPlayers <= 0); - } +private: + int m_NumberOfPlayers; - unsigned char GetPowerLevel(void) const - { - return std::min(m_NumberOfPlayers, MAX_POWER_LEVEL); - } +}; - private: - int m_NumberOfPlayers; - } GTCP; +template class GetHandlerCompileTime, class ChestType> +void cIncrementalRedstoneSimulator::HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + cGetTrappedChestPlayers GTCP; int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; diff --git a/src/Simulator/SandSimulator.cpp b/src/Simulator/SandSimulator.cpp index 1380f8841..e8887ce59 100644 --- a/src/Simulator/SandSimulator.cpp +++ b/src/Simulator/SandSimulator.cpp @@ -7,6 +7,7 @@ #include "../Defines.h" #include "../Entities/FallingBlock.h" #include "../Chunk.h" +#include "inifile/iniFile.h" diff --git a/src/Simulator/Simulator.cpp b/src/Simulator/Simulator.cpp index 7b944382b..d26702166 100644 --- a/src/Simulator/Simulator.cpp +++ b/src/Simulator/Simulator.cpp @@ -1,6 +1,11 @@ #include "Globals.h" +#include "../World.h" +#include "../BlockID.h" +#include "../Defines.h" +#include "../Chunk.h" + #include "Simulator.inc" #pragma clang diagnostic ignored "-Wweak-template-vtables" diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h index ff53b17e1..7cc2f1344 100644 --- a/src/Simulator/Simulator.h +++ b/src/Simulator/Simulator.h @@ -2,7 +2,6 @@ #pragma once #include "../Vector3.h" -#include "inifile/iniFile.h" diff --git a/src/Simulator/Simulator.inc b/src/Simulator/Simulator.inc index 1599ea60f..511a6b4c2 100644 --- a/src/Simulator/Simulator.inc +++ b/src/Simulator/Simulator.inc @@ -1,10 +1,6 @@ #include "Simulator.h" -#include "../World.h" -#include "../BlockID.h" -#include "../Defines.h" -#include "../Chunk.h" diff --git a/src/World.cpp b/src/World.cpp index ded42f093..43f7faf94 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -791,8 +791,8 @@ void cWorld::InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile) AStringVector SplitList = StringSplitAndTrim(AllMonsters, ","); for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr) { - cMonster::eType ToAdd = cMonster::StringToMobType(*itr); - if (ToAdd != cMonster::mtInvalidType) + eMonsterType ToAdd = cMonster::StringToMobType(*itr); + if (ToAdd != mtInvalidType) { m_AllowedMobs.insert(ToAdd); LOGD("Allowed mob: %s", itr->c_str()); @@ -3126,7 +3126,7 @@ bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ) -int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) +int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) { cMonster * Monster = NULL; diff --git a/src/World.h b/src/World.h index e4fe2965f..44bf13b03 100644 --- a/src/World.h +++ b/src/World.h @@ -768,7 +768,7 @@ public: bool IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export /** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */ - virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) override; // tolua_export + virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) override; // tolua_export int SpawnMobFinalize(cMonster* a_Monster); /** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise @@ -923,7 +923,7 @@ private: cChunkMap * m_ChunkMap; bool m_bAnimals; - std::set m_AllowedMobs; + std::set m_AllowedMobs; eWeather m_Weather; int m_WeatherInterval; diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 68e541eba..92d754d3f 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -458,35 +458,35 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) const char * EntityClass = NULL; switch (a_Monster->GetMobType()) { - case cMonster::mtBat: EntityClass = "Bat"; break; - case cMonster::mtBlaze: EntityClass = "Blaze"; break; - case cMonster::mtCaveSpider: EntityClass = "CaveSpider"; break; - case cMonster::mtChicken: EntityClass = "Chicken"; break; - case cMonster::mtCow: EntityClass = "Cow"; break; - case cMonster::mtCreeper: EntityClass = "Creeper"; break; - case cMonster::mtEnderDragon: EntityClass = "EnderDragon"; break; - case cMonster::mtEnderman: EntityClass = "Enderman"; break; - case cMonster::mtGhast: EntityClass = "Ghast"; break; - case cMonster::mtGiant: EntityClass = "Giant"; break; - case cMonster::mtHorse: EntityClass = "Horse"; break; - case cMonster::mtIronGolem: EntityClass = "VillagerGolem"; break; - case cMonster::mtMagmaCube: EntityClass = "LavaSlime"; break; - case cMonster::mtMooshroom: EntityClass = "MushroomCow"; break; - case cMonster::mtOcelot: EntityClass = "Ozelot"; break; - case cMonster::mtPig: EntityClass = "Pig"; break; - case cMonster::mtSheep: EntityClass = "Sheep"; break; - case cMonster::mtSilverfish: EntityClass = "Silverfish"; break; - case cMonster::mtSkeleton: EntityClass = "Skeleton"; break; - case cMonster::mtSlime: EntityClass = "Slime"; break; - case cMonster::mtSnowGolem: EntityClass = "SnowMan"; break; - case cMonster::mtSpider: EntityClass = "Spider"; break; - case cMonster::mtSquid: EntityClass = "Squid"; break; - case cMonster::mtVillager: EntityClass = "Villager"; break; - case cMonster::mtWitch: EntityClass = "Witch"; break; - case cMonster::mtWither: EntityClass = "WitherBoss"; break; - case cMonster::mtWolf: EntityClass = "Wolf"; break; - case cMonster::mtZombie: EntityClass = "Zombie"; break; - case cMonster::mtZombiePigman: EntityClass = "PigZombie"; break; + case mtBat: EntityClass = "Bat"; break; + case mtBlaze: EntityClass = "Blaze"; break; + case mtCaveSpider: EntityClass = "CaveSpider"; break; + case mtChicken: EntityClass = "Chicken"; break; + case mtCow: EntityClass = "Cow"; break; + case mtCreeper: EntityClass = "Creeper"; break; + case mtEnderDragon: EntityClass = "EnderDragon"; break; + case mtEnderman: EntityClass = "Enderman"; break; + case mtGhast: EntityClass = "Ghast"; break; + case mtGiant: EntityClass = "Giant"; break; + case mtHorse: EntityClass = "Horse"; break; + case mtIronGolem: EntityClass = "VillagerGolem"; break; + case mtMagmaCube: EntityClass = "LavaSlime"; break; + case mtMooshroom: EntityClass = "MushroomCow"; break; + case mtOcelot: EntityClass = "Ozelot"; break; + case mtPig: EntityClass = "Pig"; break; + case mtSheep: EntityClass = "Sheep"; break; + case mtSilverfish: EntityClass = "Silverfish"; break; + case mtSkeleton: EntityClass = "Skeleton"; break; + case mtSlime: EntityClass = "Slime"; break; + case mtSnowGolem: EntityClass = "SnowMan"; break; + case mtSpider: EntityClass = "Spider"; break; + case mtSquid: EntityClass = "Squid"; break; + case mtVillager: EntityClass = "Villager"; break; + case mtWitch: EntityClass = "Witch"; break; + case mtWither: EntityClass = "WitherBoss"; break; + case mtWolf: EntityClass = "Wolf"; break; + case mtZombie: EntityClass = "Zombie"; break; + case mtZombiePigman: EntityClass = "PigZombie"; break; default: { ASSERT(!"Unhandled monster type"); @@ -506,24 +506,24 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) m_Writer.AddByte("CanPickUpLoot", (char)a_Monster->CanPickUpLoot()); switch (a_Monster->GetMobType()) { - case cMonster::mtBat: + case mtBat: { m_Writer.AddByte("BatFlags", ((const cBat *)a_Monster)->IsHanging()); break; } - case cMonster::mtCreeper: + case mtCreeper: { m_Writer.AddByte("powered", ((const cCreeper *)a_Monster)->IsCharged()); m_Writer.AddByte("ignited", ((const cCreeper *)a_Monster)->IsBlowing()); break; } - case cMonster::mtEnderman: + case mtEnderman: { m_Writer.AddShort("carried", (Int16)((const cEnderman *)a_Monster)->GetCarriedBlock()); m_Writer.AddShort("carriedData", (Int16)((const cEnderman *)a_Monster)->GetCarriedMeta()); break; } - case cMonster::mtHorse: + case mtHorse: { const cHorse & Horse = *((const cHorse *)a_Monster); m_Writer.AddByte("ChestedHorse", Horse.IsChested()); @@ -536,38 +536,38 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) m_Writer.AddByte("Saddle", Horse.IsSaddled()); break; } - case cMonster::mtMagmaCube: + case mtMagmaCube: { m_Writer.AddInt("Size", ((const cMagmaCube *)a_Monster)->GetSize()); break; } - case cMonster::mtSheep: + case mtSheep: { m_Writer.AddByte("Sheared", ((const cSheep *)a_Monster)->IsSheared()); m_Writer.AddByte("Color", ((const cSheep *)a_Monster)->GetFurColor()); break; } - case cMonster::mtSlime: + case mtSlime: { m_Writer.AddInt("Size", ((const cSlime *)a_Monster)->GetSize()); break; } - case cMonster::mtSkeleton: + case mtSkeleton: { m_Writer.AddByte("SkeletonType", (((const cSkeleton *)a_Monster)->IsWither() ? 1 : 0)); break; } - case cMonster::mtVillager: + case mtVillager: { m_Writer.AddInt("Profession", ((const cVillager *)a_Monster)->GetVilType()); break; } - case cMonster::mtWither: + case mtWither: { m_Writer.AddInt("Invul", ((const cWither *)a_Monster)->GetWitherInvulnerableTicks()); break; } - case cMonster::mtWolf: + case mtWolf: { const cWolf & Wolf = *((cWolf *)a_Monster); if (!Wolf.GetOwnerName().empty()) @@ -583,7 +583,7 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) m_Writer.AddInt("CollarColor", Wolf.GetCollarColor()); break; } - case cMonster::mtZombie: + case mtZombie: { m_Writer.AddByte("IsVillager", (((const cZombie *)a_Monster)->IsVillagerZombie() ? 1 : 0)); m_Writer.AddByte("IsBaby", (((const cZombie *)a_Monster)->IsBaby() ? 1 : 0)); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1fbd88f04..7e21ff94f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,3 +5,4 @@ enable_testing() include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(ChunkData) +add_subdirectory(Redstone) diff --git a/tests/Redstone/CMakeLists.txt b/tests/Redstone/CMakeLists.txt new file mode 100644 index 000000000..ee4a7a64f --- /dev/null +++ b/tests/Redstone/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required (VERSION 2.6) + +enable_testing() + +include_directories(${CMAKE_SOURCE_DIR}/src/) + +add_definitions(-DTEST_GLOBALS=1) + +add_executable(Redstone-creatable-exe creatable.cpp ../../src/BoundingBox.cpp) +add_test(NAME creatable-test COMMAND Redstone-creatable-exe) diff --git a/tests/Redstone/creatable.cpp b/tests/Redstone/creatable.cpp new file mode 100644 index 000000000..07b800f9b --- /dev/null +++ b/tests/Redstone/creatable.cpp @@ -0,0 +1,162 @@ + +#include "Globals.h" + +class MockChest; +typedef cItemCallback cChestCallback; + +AString ItemToFullString(const cItem & a_Item) +{ +return ""; +} + +class cEntity +{ +public: + const Vector3d & GetPosition (void) const { return m_pos;} + double GetWidth (void) const { return 0; } + double GetHeight (void) const { return 0; } + static const Vector3d m_pos; +}; + +const Vector3d cEntity::m_pos = Vector3d(0,0,0); + +class cItem +{ +public: + cItem(BLOCKTYPE val) {} +}; + +void cBlockInfo::Initialize(cBlockInfoArray & a_Info) {} +cBlockInfo::~cBlockInfo () {} + +#include "Blocks/ChunkInterface.h" + +bool cChunkInterface::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) +{ + return false; +} + +bool cChunkInterface::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) +{ + return false; +} + +#include "Simulator/Simulator.inc" + +#include "Simulator/IncrementalRedstoneSimulator.inc" + +class MockWorld; + + +class MockHandler +{ +public: + static eBlockFace MetadataToDirection(NIBBLETYPE a_MetaData) { return BLOCK_FACE_NONE; } + static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData) { return BLOCK_FACE_NONE; } + static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_MetaData) { return BLOCK_FACE_NONE; } + static NIBBLETYPE IsOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) { return 0; } + static void ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ, MockWorld * a_World) {} + static void RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ, MockWorld * a_World) {} + static void SetOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open) {} + +}; + +template +class MockHandlerFetcher +{ +public: + typedef MockHandler type; +}; + +class MockWorld +{ +public: + bool IsChunkLighted(int a_ChunkX, int a_ChunkZ) { return false; } + bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback) { return false; } + + void QueueLightChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback = NULL) {} + + + NIBBLETYPE GetBlockSkyLight (int a_BlockX, int a_BlockY, int a_BlockZ) { return 0; } + + cPlayer * FindClosestPlayer(const Vector3d & a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true) { return NULL; } + + + void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ) {} + + void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec = 80, double a_InitialVelocityCoeff = 1) {} + + + bool SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open) {return false; } + + + cChunkMap * GetChunkMap (void) { return NULL; } + +}; + + +class MockChunk +{ +public: + cRedstoneSimulatorChunkData * GetRedstoneSimulatorData() { return NULL; } + bool IsRedstoneDirty() { return true; } + void SetIsRedstoneDirty(bool a_Param) {} + + void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) {} + + void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients = true) {} + void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) {} + + int GetPosX(void) const { return 0; } + int GetPosZ(void) const { return 0; } + + MockChunk * GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) const { return NULL; } + + + BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const { return 0; } + BLOCKTYPE GetBlock(const Vector3i & a_RelCoords) const { return 0; } + + NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const { return 0; } + void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) {} + + + bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { return false; } + + bool UnboundedRelGetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType) const { return false; } + + MockChunk * GetNeighborChunk(int a_BlockX, int a_BlockZ) { return NULL; } + + MockChunk * GetRelNeighborChunk(int a_RelX, int a_RelZ) { return NULL; } + + bool IsValid(void) const { return false; } + + NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const { return 0; } + + void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL) {} + void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL) {} + + bool DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cRedstonePoweredCallback & a_Callback) { return false; } + + template + bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, T & a_Callback) + { + return false; + } + +}; + +int main(int argc, char** argv) +{ + + class MockChest + { + public: + BLOCKTYPE GetBlockType(void) const { return 0; } + int GetNumberOfPlayers(void) const { return 0; } + }; + + MockWorld World; + + cIncrementalRedstoneSimulator Simulator(World); + return 0; +} -- cgit v1.2.3 From 73dfe1fe81a4b60dc8b67a0caaba16d83c56e136 Mon Sep 17 00:00:00 2001 From: Tycho Date: Wed, 17 Sep 2014 18:59:45 +0100 Subject: Fix accedental c++11 --- tests/Redstone/creatable.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/Redstone/creatable.cpp b/tests/Redstone/creatable.cpp index 07b800f9b..f26ebe85c 100644 --- a/tests/Redstone/creatable.cpp +++ b/tests/Redstone/creatable.cpp @@ -144,16 +144,17 @@ public: } }; +class MockChest +{ +public: + BLOCKTYPE GetBlockType(void) const { return 0; } + int GetNumberOfPlayers(void) const { return 0; } +}; int main(int argc, char** argv) { - class MockChest - { - public: - BLOCKTYPE GetBlockType(void) const { return 0; } - int GetNumberOfPlayers(void) const { return 0; } - }; + MockWorld World; -- cgit v1.2.3 From be6d4a5912abcfe36a1f0fcee9d76e050a58c0ce Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 18 Sep 2014 16:04:03 +0200 Subject: 1.8: Simplified item metadata reading. --- src/ByteBuffer.cpp | 17 ----------------- src/ByteBuffer.h | 3 --- src/Protocol/Protocol18x.cpp | 10 +++------- 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index 262e0e3b5..17e8091c7 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -822,23 +822,6 @@ bool cByteBuffer::SkipRead(size_t a_Count) -bool cByteBuffer::ReverseRead(size_t a_Count) -{ - CHECK_THREAD; - CheckValid(); - if (m_ReadPos < a_Count) - { - return false; - } - - m_ReadPos -= a_Count; - return true; -} - - - - - void cByteBuffer::ReadAll(AString & a_Data) { CHECK_THREAD; diff --git a/src/ByteBuffer.h b/src/ByteBuffer.h index e200d2a7b..c1c71d8c4 100644 --- a/src/ByteBuffer.h +++ b/src/ByteBuffer.h @@ -107,9 +107,6 @@ public: /** Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer */ bool SkipRead(size_t a_Count); - - /** Reverse reading by a_Count bytes; returns false if not enough readed bytes in the ringbuffer */ - bool ReverseRead(size_t a_Count); /** Reads all available data into a_Data */ void ReadAll(AString & a_Data); diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 837c8ec99..a258d9585 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -2497,17 +2497,13 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) a_Item.Empty(); } - HANDLE_PACKET_READ(a_ByteBuffer, ReadChar, char, FirstChar); - if (FirstChar == 0) + AString Metadata; + a_ByteBuffer.ReadAll(Metadata); + if ((Metadata.size() == 0) || (Metadata[0] == 0)) { // No metadata return true; } - a_ByteBuffer.ReverseRead(1); - - // Read the metadata - AString Metadata; - a_ByteBuffer.ReadAll(Metadata); ParseItemMetadata(a_Item, Metadata); return true; -- cgit v1.2.3 From 400ce1f9e0956d373e4326fd9eaa4a9558b4e9b3 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 18 Sep 2014 16:37:34 +0200 Subject: Added german language support --- MCServer/items.ini | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/MCServer/items.ini b/MCServer/items.ini index 380c13e02..df878cdf4 100644 --- a/MCServer/items.ini +++ b/MCServer/items.ini @@ -7,7 +7,6 @@ diorite=1:3 polisheddiorite=1:4 andesite=1:5 polishedandesite=1:6 -stone=1 grass=2 dirt=3 coarseddirt=3:1 @@ -410,7 +409,7 @@ lightgraystainedclay=159:8 lightgreystainedclay=159:8 ltgraystainedclay=159:8 ltgreystainedclay=159:8 -silvertsainedclay=159:8 +silvertstainedclay=159:8 cyanstainedclay=159:9 purplestainedclay=159:10 violetstainedclay=159:10 @@ -471,6 +470,7 @@ darkoakwoodstairs=164 bigoakwoodstiars=164 roofedoakwoodstairs=164 slimeblock=165 +barrier=166 irontrapdoor=167 prismarine=168 prismarinebricks=168:1 @@ -525,7 +525,8 @@ redsandstone=179 chiseledredsandstone=179:1 smoothredsandstone=179:2 redsandstonestairs=180 -redsandstoneslab=182 +newstoneslab=182 +redsandstoneslab=182:0 sprucefencegate=183 coniferfencegate=183 pinefencegate=183 @@ -698,7 +699,11 @@ lightdust=348 glowdust=348 fish=349 rawfish=349 +rawsalmon=349:1 +clownfish=349:2 +pufferfish=349:3 cookedfish=350 +cookedsalmon=350:1 dye=351 inksac=351:0 blackdye=351:0 -- cgit v1.2.3 From b3de0e104fbb7654871926266984905026bdc587 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 18 Sep 2014 17:39:32 +0200 Subject: Added german language support, now really --- MCServer/lang/items_de.ini | 603 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 603 insertions(+) create mode 100644 MCServer/lang/items_de.ini diff --git a/MCServer/lang/items_de.ini b/MCServer/lang/items_de.ini new file mode 100644 index 000000000..3c2ab87d1 --- /dev/null +++ b/MCServer/lang/items_de.ini @@ -0,0 +1,603 @@ +[Items] +luft=0 +stein=1 +granit=1:1 +poliertergranit=1:2 +diorit=1:3 +polierterdiorit=1:4 +andesit=1:5 +polierterandesit=1:6 +grasblock=2 +erde=3 +grobeerde=3:1 +podsol=3:2 +bruchstein=4 +holzbretter=5 +eichenholzbretter=5:0 +fichtenholzbretter=5:1 +birkenholzbretter=5:2 +tropenholzbretter=5:3 +akazienholzbretter=5:4 +schwarzeichenholzbretter=5:5 +setzling=6 +eichensetzling=6:0 +fichtensetzling=6:1 +birkensetzling=6:2 +tropensetzling=6:3 +akaziensetzling=6:4 +schwarzeichensetzling=6:5 +grundgestein=7 +wasser=8 +fliessendeswasser=8 +stehendeswasser=9 +stilleswasser=9 +swasser=9 +lava=10 +fliessendelava=10 +stehendelava=11 +stillelava=11 +slava=11 +sand=12 +rotersand=12:1 +kies=13 +golderz=14 +eisenerz=15 +kohleerz=16 +stamm=17 +eichenholz=17:0 +fichtenholz=17:1 +birkenholz=17:2 +tropenholz=17:3 +laub=18 +eichenlaub=18:0 +fichtenlaub=18:1 +birkenlaub=18:2 +tropenlaub=18:3 +schwamm=19 +nasserschwamm=19:1 +glas=20 +lapislazulierz=21 +lapislazuliblock=22 +werfer=23 +sandstein=24 +normalersandstein=24:0 +gemeisseltersandstein=24:1 +glattersandstein=24:2 +notenblock=25 +bettblock=26 +antriebsschiene=27 +sensorschiene=28 +klebrigerkolben=29 +spinnenweben=30 +gras=31 +gras=31:1 +farn=31:2 +toterbusch=32 +kolben=33 +kolbenkopf=34 +wolle=35 +weissewolle=35:0 +orangenewolle=35:1 +magentawolle=35:2 +hellblauewolle=35:3 +gelbewolle=35:4 +hellgruene=35:5 +rosawolle=35:6 +grauwool=35:7 +greywool=35:7 +grauewolle=35:7 +hellgrauewolle=35:8 +tuerkisewolle=35:9 +violettewolle=35:10 +blauewolle=35:11 +braunewolle=35:12 +gruenewolle=35:13 +rotewolle=35:14 +schwarzewolle=35:15 +loewenzahn=37 +blume=38 +mohn=38:0 +blaueorchidee=38:1 +sternlauch=38:2 +porzellansternchen=38:3 +rotetulpe=38:4 +orangenetulpe=38:5 +weissetulpe=38:6 +rosatulpe=38:7 +margerite=38:8 +braunerpilz=39 +roterpilz=40 +goldblock=41 +eisenblock=42 +doppelstufe=43 +doppelsteinstufe=43:0 +doppelsandsteinstufe=43:1 +doppelholzstufe=43:2 +doppelbruchsteinstufe=43:3 +doppelziegelstufe=43:4 +doppelsteinziegelstufe=43:5 +doppelnetherziegelstufe=43:6 +doppelquarzstufe=43:7 +stufe=44 +steinstufe=44:0 +sandsteinstufe=44:1 +holzstufe=44:2 +bruchsteinstufe=44:3 +ziegelstufe=44:4 +steinziegelstufe=44:5 +netherziegelstufe=44:6 +quarzstufe=44:7 +ziegelsteine=45 +tnt=46 +buecherregal=47 +bemoosterbruchstein=48 +obsidian=49 +fackel=50 +feuer=51 +monsterspawner=52 +eichenholztreppe=53 +kiste=54 +rotstonekabel=55 +diamanterz=56 +diamantblock=57 +werkbank=58 +ernte=59 +farmland=60 +ofen=61 +brennenderofen=62 +schildblock=63 +holztuerblock=64 +leiter=65 +schiene=66 +bruchsteintreppe=67 +wandschild=68 +schalter=69 +steindruckplatte=70 +eisentuerblock=71 +holzdruckplatte=72 +rotstoneerz=73 +leuchtendesrotstoneerz=74 +erloschenerotstonefackel=75 +rotstonefackel=76 +setinknopf=77 +schnee=78 +eis=79 +schneeblock=80 +kaktus=81 +ton=82 +zuckerrohrblock=83 +plattenspieler=84 +eichenholzzaun=85 +kuerbis=86 +netherstein=87 +selensand=88 +leuchtstein=89 +portal=90 +kürbislaterne=91 +kuchenlock=92 +weissesglas=95 +orangenesglas=95:1 +magentaglas=95:2 +hellblauesglas=95:3 +gelbesglas=95:4 +hellgruenesglas=95:5 +rosagerfaerbtglas=95:6 +grauesglas=95:7 +hellgrauesglas=95:8 +tuerkisesglas=95:9 +violettesglas=95:10 +blauesglas=95:11 +braunesglas=95:12 +gruenesglas=95:13 +rotesglas=95:14 +schwarzesglas=95:15 +falltuer=96 +silberfischblock=97 +steinziegel=98 +bemoostesteinziegel=98:1 +rissigesteinziegel=98:2 +gemeisseltesteinziegel=98:3 +braunerpilzblock=99 +roterpilzblock=100 +eisengitter=101 +glasscheibe=102 +melone=103 +kuerbispflanze=104 +melonenpflanze=105 +ranken=106 +eichenholzzauntor=107 +ziegeltreppe=108 +steinziegeltreppe=109 +myzel=110 +seerosenblatt=111 +netherziegel=112 +netherziegelzaun=113 +netherziegeltreppe=114 +netherwarzenblock=115 +zaubertisch=116 +braustandblock=117 +kesselblock=118 +endportal=119 +endportalrahmen=120 +endstein=121 +drachenei=122 +redstonelampe=123 +erlosscheneredstonelampe=124 +doppelholzstufe=125 +doppeleichenholzstufe=125:0 +doppelfichtenholzstufe=125:1 +doppelbirkenholzstufe=125:2 +doppeltropenholzstufe=125:3 +doppelakazienholzstufe=125:4 +doppelschwarzeichenstufe=125:5 +holzstufe=126 +eichenholzstufe=126:0 +fichtenholzstufe=126:1 +birkenholzstufe=126:2 +tropenholzstufe=126:3 +akazienholzstufe=126:4 +schwarzeichenholzstufe=126:5 +kakaobohnen=127 +sandsteintreppe=128 +smaragderz=129 +endertruhe=130 +haken=131 +stolperdraht=132 +smaragdblock=133 +fichtenholztreppe=134 +birkenholztreppe=135 +tropenholztreppe=136 +kommandoblock=137 +leuchtfeuer=138 +bruchsteinmauer=139 +bemoostebruchsteinmauer=139:1 +blumentopfblock=140 +karottenpflanze=141 +kartoffelpflanze=142 +knopf=143 +skelettschaedel=144 +witherskelettschaedel=144:1 +zombieschaedel=144:2 +schaedel=144:3 +creeperschaedel=144:4 +amboss=145 +redstonetruhe=146 +waegeplatteniedrigegewichte=147 # WTF, that names are so stupid... +waegeplattehohegewichte=148 +inaktiverkomparator=149 +aktiverkomparator=150 +tageslichtsensor=151 +redstoneblock=152 +netherquarzerz=153 +trichter=154 +quarzblock=155 +gemeisselterquarzblock=155:1 +quarzsaeule=155:2 +quarztreppe=156 +aktivierungsschiene=157 +spender=158 +weissgerfaerbterton=159 +orangegerfaerbterton=159:1 +magentagerfaerbterton=159:2 +hellblaugerfaerbterton=159:3 +gelbgerfaerbterton=159:4 +hellgruengerfaerbterton=159:5 +rosagerfaerbterton=159:6 +graugerfaerbterton=159:7 +hellgraugefaerbterton=159:8 +tuerkisgerfaerbterton=159:9 +purplegerfaerbterton=159:10 +violettegerfaerbterton=159:10 +blaugerfaerbterton=159:11 +braungerfaerbterton=159:12 +gruengerfaerbterton=159:13 +rotgerfaerbterton=159:14 +schwarzgerfaerbterton=159:15 +weisseglasscheibe=160 +orangeneglasscheibe=160:1 +magentaglasscheibe=160:2 +hellblaueglasscheibe=160:3 +gelbeglasscheibe=160:4 +hellgrueneglasscheibe=160:5 +rosaglasscheibe=160:6 +graueglasscheibe=160:7 +hellgraueglasscheibe=160:8 +tuerkiseglasscheibe=160:9 +violetteglasscheibe=160:10 +blaueglasscheibe=160:11 +brauneglasscheibe=160:12 +grueneglasscheibe=160:13 +roteglasscheibe=160:14 +schwarzeglasscheibe=160:15 +neueslaub=161 +akazienlaub=161:0 +schwarzeichenlaub=161:1 +neuestaemme=162 +akazienholz=162:0 +schwarzeichenholz=162:1 +akazientreppe=163 +schwarzeichentreppe=164 +schleimblock=165 +bartriere=166 +eisenfalltür=167 +prismarin=168 +prismarinziegel=168:1 +dunklerprismarin=168:2 +seelaterne=169 +strohballen=170 +teppich=171 +weisserteppich=171:0 +orangenerteppich=171:1 +magentateppich=171:2 +hellblauerteppich=171:3 +gelberteppich=171:4 +hellgruenerteppich=171:5 +rosateppich=171:6 +grauerteppich=171:7 +hellgrauerteppich=171:8 +tuerkiserteppich=171:9 +violetterteppich=171:10 +blauerteppich=171:11 +braunerteppich=171:12 +gruenerteppich=171:13 +roterteppich=171:14 +schwarzerteppich=171:15 +gebrannterton=172 +kohleblock=173 +packeis=174 +doppelpflanze=175 +sonnenblume=175:0 +Flieder=175:1 +hohesgras=175:2 +grosserfarn=175:3 +rosenstrauch=175:4 +pfingstrose=175:5 +rotersandstein=179 +gemeisselterrotersandstein=179:1 +glatterrotersandstein=179:2 +rotesandsteintreppe=180 +neuesteinstufe=182 +rotesandsteinstufe=182:0 +fichtenzauntor=183 +birkenzauntor=184 +tropenzauntor=185 +schwarzeichenzauntor=186 +akazienzauntor=187 +fichtenzaun=188 +birkenzaun=189 +tropenzaun=190 +schwarzeichenzaun=191 +akazienzaun=192 +eisenschaufel=256 +eisenspitzhacke=257 +eisenaxt=258 +feuerzeug=259 +apfel=260 +bogen=261 +pfeil=262 +kohle=263 +holzkohle=263:1 +diamant=264 +eisenbarren=265 +goldbarren=266 +eisenschwert=267 +holzschwert=268 +holzschaufel=269 +holzspitzhacke=270 +holzaxt=271 +steinschwert=272 +steinschaufel=273 +steinspitzhacke=274 +steinaxt=275 +diamantschwert=276 +diamantschaufel=277 +diamantspitzhacke=278 +diamantaxt=279 +stock=280 +schuessel=281 +pilzsuppe=282 +goldschwert=283 +goldschaufel=284 +goldspitzhacke=285 +goldaxt=286 +faden=287 +feder=288 +schwarzpulver=289 +holzhacke=290 +steinhacke=291 +eisenhacke=292 +diamanthacke=293 +goldhacke=294 +samen=295 +weizen=296 +brot=297 +lederkappe=298 +lederjacke=299 +lederhose=300 +lederstiefel=301 +kettenhaube=302 +kettenhemd=303 +kettenhose=304 +kettenstiefel=305 +eisenhelm=306 +eisenbrustplatte=307 +eisenbeinschutz=308 +eisenstiefel=309 +diamanthelm=310 +diamantbrustplatte=311 +diamantbeinschutz=312 +diamantstiefel=313 +goldhelm=314 +goldharnisch=315 +goldbeinschutz=316 +goldstiefel=317 +goldboots=317 +feuerstein=318 +rohesschweinefleisch=319 +gebratenesschweinefleisch=320 +gemaelde=321 +goldenerapfel=322 +goldenerapfel=322:1 +schild=323 +eichenholztuer=324 +eimer=325 +wassereimer=326 +lavaeimer=327 +lore=328 +sattel=329 +eisentuer=330 +redstone=331 +schneeballl=332 +boot=333 +leder=334 +milcht=335 +ziegel=336 +ton=337 +zuckercane=338 +papier=339 +buch=340 +schleimball=341 +gueterlore=342 +angetriebenelore=343 +ei=344 +kompass=345 +angel=346 +uhr=347 +glowstonestaub=348 +fisch=349 +roherfisch=349 +roherlachs=349:1 +clownfisch=349:2 +kugelfisch=349:3 +gebratenerfisch=350 +gebratenerlachs=350:1 +farbe=351 +tintenbeutel=351:0 +rosenrot=351:1 +kaktusgruen=351:2 +kakaobohnen=351:3 +lapislazuli=351:4 +violetterfarbstoff=351:5 +tuerkiserfarbstoff=351:6 +hellgrauerfarbstoff=351:7 +grauerfarbstoff=351:8 +rosafarbstoff=351:9 +hellgruenerfarbstoff=351:10 +gelberfarbstoff=351:11 +hellblauerfarbstoff=351:12 +magentafarbstoff=351:13 +orangenerfarbstoff=351:14 +knochenmehl=351:15 +knochen=352 +zucker=353 +kuchen=354 +bett=355 +redstoneverstaerker=356 +keks=357 +karte=358 +schere=359 +melone=360 +kürbiskerne=361 +melonenkerne=362 +rohesrindfleisch=363 +steak=364 +roheshühnchen=365 +gebrateneshühnchen=366 +verrottetesfleisch=367 +enderperle=368 +lohenrute=369 +ghasttraene=370 +goldnugget=371 +netherwarze=372 +trank=373 +glasflasche=374 +spinnenauge=375 +fermentiertesspinnenauge=376 +lohenstaub=377 +magmacreme=378 +braustand=379 +kessel=380 +enderauge=381 +glitzerndemelone=382 +spawnei=383 +erfahrungsfläschchen=384 +feuerkugel=385 +buchundfeder=386 +beschriebenesbuch=387 +smaragd=388 +rahmen=389 +blumentopf=390 +karotte=391 +kartoffel=392 +ofenkartoffel=393 +giftigekartoffel=394 +leerekarte=395 +goldenekarotte=396 +skelettschaedel=397 +witherschaedel=397:1 +zombieschaedel=397:2 +kopf=397:3 +creeperschaedel=397:4 +karottenrute=398 +netherstern=399 +kuerbiskuchen=400 +feuerwerksrakete=401 +feuerwerksstern=402 +verzauberungsbuch=403 +redstonekomparator=404 +netherziegelitem=405 +netherquarz=406 +tntlore=407 +trichterlore=408 +prismarinscherbe=409 +prismarinkristalle=410 +roheskaninchen=411 +gebrateneskaninchen=412 +kaninchenragout=413 +hasenpfote=414 +kaninchenfell=415 +ruestungsstaender=416 +eisernepferderuestung=417 +goldenepferderuestung=418 +diamantenepferderuestung=419 +leine=420 +namensschild=421 +kommandoblocklore=422 +roheshammelfleisch=423 +gebrateneshammelfleisch=424 +banner=425 +schwarzesbanner=415:0 +rotesbanner=415:1 +gruenesbanner=415:2 +braunbanner=415:3 +blauesbanner=415:4 +violettesbanner=415:5 +tuerkisesbanner=415:6 +hellgrauesbanner=415:7 +grauesbanner=415:8 +rosabanner=415:9 +hellgruenesbanner=415:10 +gelbesbanner=415:11 +hellblauesbanner=415:12 +magentabanner=415:13 +orangenesbanner=415:14 +weissesbanner=415:15 +fichtenholztuer=427 +birkenholztuer=428 +tropentuer=429 +akazientuer=430 +schwarzeichentuer=431 +goldeneschallplatte=2256 +grueneschallplatte=2257 +blocksschallplatte=2258 +chirpschallplatte=2259 +farschallplatte=2260 +mallschallplatte=2261 +mellohischallplatte=2262 +stalschallplatte=2263 +stradschallplatte=2264 +wardschallplatte=2265 +11schallplatte=2266 + + + -- cgit v1.2.3 From 43ed690520d3c3b47ed7ff6f48f868e8011565e0 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 18 Sep 2014 18:50:17 +0200 Subject: Exported player list states to extra functions. --- src/ClientHandle.cpp | 48 ++++++++++-- src/ClientHandle.h | 138 +++++++++++++++++----------------- src/Entities/Player.cpp | 4 +- src/Protocol/Protocol.h | 144 ++++++++++++++++++------------------ src/Protocol/Protocol125.cpp | 71 ++++++++++++++---- src/Protocol/Protocol125.h | 144 ++++++++++++++++++------------------ src/Protocol/Protocol17x.cpp | 66 +++++++++++++++-- src/Protocol/Protocol17x.h | 144 ++++++++++++++++++------------------ src/Protocol/Protocol18x.cpp | 141 +++++++++++++++++++++-------------- src/Protocol/Protocol18x.h | 144 ++++++++++++++++++------------------ src/Protocol/ProtocolRecognizer.cpp | 44 ++++++++++- src/Protocol/ProtocolRecognizer.h | 144 ++++++++++++++++++------------------ src/World.cpp | 78 ++++++++++++++++++- src/World.h | 58 ++++++++------- 14 files changed, 837 insertions(+), 531 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index df6847767..487ef3867 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -127,7 +127,7 @@ cClientHandle::~cClientHandle() if (!m_Username.empty() && (World != NULL)) { // Send the Offline PlayerList packet: - World->BroadcastPlayerListItem(*m_Player, 4, this); + World->BroadcastPlayerListRemovePlayer(*m_Player, this); } if (World != NULL) { @@ -364,10 +364,10 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID, m_Player->SendExperience(); // Send player list items - SendPlayerListItem(*m_Player, 0); - World->BroadcastPlayerListItem(*m_Player, 0); + SendPlayerListAddPlayer(*m_Player); + World->BroadcastPlayerListAddPlayer(*m_Player); World->SendPlayerList(m_Player); - + m_Player->Initialize(*World); m_State = csAuthenticated; @@ -2408,9 +2408,45 @@ void cClientHandle::SendPlayerAbilities() -void cClientHandle::SendPlayerListItem(const cPlayer & a_Player, char a_Action) +void cClientHandle::SendPlayerListAddPlayer(const cPlayer & a_Player) +{ + m_Protocol->SendPlayerListAddPlayer(a_Player); +} + + + + + +void cClientHandle::SendPlayerListRemovePlayer(const cPlayer & a_Player) +{ + m_Protocol->SendPlayerListRemovePlayer(a_Player); +} + + + + + +void cClientHandle::SendPlayerListUpdateGameMode(const cPlayer & a_Player) +{ + m_Protocol->SendPlayerListUpdateGameMode(a_Player); +} + + + + + +void cClientHandle::SendPlayerListUpdatePing(const cPlayer & a_Player) +{ + m_Protocol->SendPlayerListUpdatePing(a_Player); +} + + + + + +void cClientHandle::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) { - m_Protocol->SendPlayerListItem(a_Player, a_Action); + m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_OldListName); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 27bfc756c..05d05e052 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -122,73 +122,77 @@ public: // The following functions send the various packets: // (Please keep these alpha-sorted) - void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle); - void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType); - void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage); - void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export - void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes); - void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); - void SendChat (const cCompositeChat & a_Message); - void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer); - void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player); - void SendDestroyEntity (const cEntity & a_Entity); - void SendDisconnect (const AString & a_Reason); - void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ); - 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); - void SendEntityLook (const cEntity & a_Entity); - void SendEntityMetadata (const cEntity & a_Entity); - void SendEntityProperties (const cEntity & a_Entity); - void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ); - 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 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); - void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item); - void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale); - 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 SendPlayerAbilities (void); - void SendPlayerListItem (const cPlayer & a_Player, char a_Action); - void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+) - void SendPlayerMoveLook (void); - void SendPlayerPosition (void); - void SendPlayerSpawn (const cPlayer & a_Player); - 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 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); - void SendSpawnMob (const cMonster & a_Mob); - void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch); - void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType = 0); - void SendStatistics (const cStatManager & a_Manager); - void SendTabCompletionResults(const AStringVector & a_Results); - void SendTeleportEntity (const cEntity & a_Entity); - void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ); - void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle); // tolua_export - void SendUnloadChunk (int a_ChunkX, int a_ChunkZ); - void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity); - void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); - void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ); - void SendWeather (eWeather a_Weather); - void SendWholeInventory (const cWindow & a_Window); - void SendWindowClose (const cWindow & a_Window); - void SendWindowOpen (const cWindow & a_Window); - void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value); + void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle); + void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType); + void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage); + void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export + void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes); + void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); + void SendChat (const cCompositeChat & a_Message); + void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer); + void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player); + void SendDestroyEntity (const cEntity & a_Entity); + void SendDisconnect (const AString & a_Reason); + void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ); + 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); + void SendEntityLook (const cEntity & a_Entity); + void SendEntityMetadata (const cEntity & a_Entity); + void SendEntityProperties (const cEntity & a_Entity); + void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ); + 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 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); + void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item); + void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale); + 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 SendPlayerAbilities (void); + void SendPlayerListAddPlayer (const cPlayer & a_Player); + void SendPlayerListRemovePlayer (const cPlayer & a_Player); + void SendPlayerListUpdateGameMode (const cPlayer & a_Player); + void SendPlayerListUpdatePing (const cPlayer & a_Player); + void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName); + void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+) + void SendPlayerMoveLook (void); + void SendPlayerPosition (void); + void SendPlayerSpawn (const cPlayer & a_Player); + 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 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); + void SendSpawnMob (const cMonster & a_Mob); + void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch); + void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType = 0); + void SendStatistics (const cStatManager & a_Manager); + void SendTabCompletionResults (const AStringVector & a_Results); + void SendTeleportEntity (const cEntity & a_Entity); + void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ); + void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle); // tolua_export + void SendUnloadChunk (int a_ChunkX, int a_ChunkZ); + void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity); + void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); + void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ); + void SendWeather (eWeather a_Weather); + void SendWholeInventory (const cWindow & a_Window); + void SendWindowClose (const cWindow & a_Window); + void SendWindowOpen (const cWindow & a_Window); + void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value); // tolua_begin const AString & GetUsername(void) const; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 826e0786f..36d8307b0 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -266,7 +266,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) cTimer t1; if (m_LastPlayerListTime + PLAYER_LIST_TIME_MS <= t1.GetNowTime()) { - m_World->BroadcastPlayerListItem(*this, 2); + // m_World->BroadcastPlayerListUpdatePing(*this); m_LastPlayerListTime = t1.GetNowTime(); } @@ -1164,7 +1164,7 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) SetCanFly(false); } - m_World->BroadcastPlayerListItem(*this, 1); + m_World->BroadcastPlayerListUpdateGameMode(*this); } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index eceec4974..f351ee4b9 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -57,76 +57,80 @@ public: virtual void DataReceived(const char * a_Data, size_t a_Size) = 0; // Sending stuff to clients (alphabetically sorted): - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) = 0; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) = 0; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0; - virtual void SendChat (const AString & a_Message) = 0; - virtual void SendChat (const cCompositeChat & a_Message) = 0; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0; - virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) = 0; - virtual void SendDestroyEntity (const cEntity & a_Entity) = 0; - virtual void SendDisconnect (const AString & a_Reason) = 0; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) = 0; - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0; - virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0; - virtual void SendEntityLook (const cEntity & a_Entity) = 0; - virtual void SendEntityMetadata (const cEntity & a_Entity) = 0; - virtual void SendEntityProperties (const cEntity & a_Entity) = 0; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0; - virtual void SendEntityVelocity (const cEntity & a_Entity) = 0; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0; - virtual void SendGameMode (eGameMode a_GameMode) = 0; - virtual void SendHealth (void) = 0; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) = 0; - virtual void SendKeepAlive (int a_PingID) = 0; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) = 0; - virtual void SendLoginSuccess (void) = 0; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) = 0; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) = 0; - virtual void SendMapInfo (int a_ID, unsigned int a_Scale) = 0; - virtual void SendPaintingSpawn (const cPainting & a_Painting) = 0; - virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0; - virtual void SendPlayerAbilities (void) = 0; - virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0; - virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) = 0; - virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) = 0; - virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+) - virtual void SendPlayerMoveLook (void) = 0; - virtual void SendPlayerPosition (void) = 0; - virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; - virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0; - virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0; - virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) = 0; - virtual void SendExperience (void) = 0; - virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; - virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; - virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) = 0; - virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0; - virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) = 0; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0; - virtual void SendSpawnMob (const cMonster & a_Mob) = 0; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) = 0; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) = 0; - virtual void SendStatistics (const cStatManager & a_Manager) = 0; - virtual void SendTabCompletionResults(const AStringVector & a_Results) = 0; - virtual void SendTeleportEntity (const cEntity & a_Entity) = 0; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) = 0; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0; - virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0; - virtual void SendWeather (eWeather a_Weather) = 0; - virtual void SendWholeInventory (const cWindow & a_Window) = 0; - virtual void SendWindowClose (const cWindow & a_Window) = 0; - virtual void SendWindowOpen (const cWindow & a_Window) = 0; - virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) = 0; + virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) = 0; + virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0; + virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) = 0; + virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; + virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0; + virtual void SendChat (const AString & a_Message) = 0; + virtual void SendChat (const cCompositeChat & a_Message) = 0; + virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0; + virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) = 0; + virtual void SendDestroyEntity (const cEntity & a_Entity) = 0; + virtual void SendDisconnect (const AString & a_Reason) = 0; + virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+) + virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) = 0; + virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0; + virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0; + virtual void SendEntityLook (const cEntity & a_Entity) = 0; + virtual void SendEntityMetadata (const cEntity & a_Entity) = 0; + virtual void SendEntityProperties (const cEntity & a_Entity) = 0; + virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; + virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; + virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0; + virtual void SendEntityVelocity (const cEntity & a_Entity) = 0; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0; + virtual void SendGameMode (eGameMode a_GameMode) = 0; + virtual void SendHealth (void) = 0; + virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) = 0; + virtual void SendKeepAlive (int a_PingID) = 0; + virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) = 0; + virtual void SendLoginSuccess (void) = 0; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) = 0; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) = 0; + virtual void SendMapInfo (int a_ID, unsigned int a_Scale) = 0; + virtual void SendPaintingSpawn (const cPainting & a_Painting) = 0; + virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0; + virtual void SendPlayerAbilities (void) = 0; + virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0; + virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) = 0; + virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) = 0; + virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) = 0; + virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) = 0; + virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) = 0; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) = 0; + virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+) + virtual void SendPlayerMoveLook (void) = 0; + virtual void SendPlayerPosition (void) = 0; + virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; + virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0; + virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) = 0; + virtual void SendExperience (void) = 0; + virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) = 0; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0; + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) = 0; + virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0; + virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0; + virtual void SendSpawnMob (const cMonster & a_Mob) = 0; + virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) = 0; + virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) = 0; + virtual void SendStatistics (const cStatManager & a_Manager) = 0; + virtual void SendTabCompletionResults (const AStringVector & a_Results) = 0; + virtual void SendTeleportEntity (const cEntity & a_Entity) = 0; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) = 0; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0; + virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0; + virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0; + virtual void SendWeather (eWeather a_Weather) = 0; + virtual void SendWholeInventory (const cWindow & a_Window) = 0; + virtual void SendWindowClose (const cWindow & a_Window) = 0; + virtual void SendWindowOpen (const cWindow & a_Window) = 0; + virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) = 0; /// Returns the ServerID used for authentication through session.minecraft.net virtual AString GetAuthServerID(void) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index c785553a5..4378ef466 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -719,28 +719,73 @@ void cProtocol125::SendPaintingSpawn(const cPainting & a_Painting) -void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, char a_Action) +void cProtocol125::SendPlayerListAddPlayer(const cPlayer & a_Player) { cCSLock Lock(m_CSPacket); - if (a_Action == 1) + WriteByte (PACKET_PLAYER_LIST_ITEM); + WriteString(a_Player.GetName()); + WriteBool (true); + WriteShort (a_Player.GetClientHandle()->GetPing()); + Flush(); +} + + + + + +void cProtocol125::SendPlayerListRemovePlayer(const cPlayer & a_Player) +{ + cCSLock Lock(m_CSPacket); + WriteByte (PACKET_PLAYER_LIST_ITEM); + WriteString(a_Player.GetName()); + WriteBool (false); + WriteShort (0); + Flush(); +} + + + + + +void cProtocol125::SendPlayerListUpdateGameMode(const cPlayer & a_Player) +{ + // Not implemented in this protocol version + UNUSED(a_Player); +} + + + + + +void cProtocol125::SendPlayerListUpdatePing(const cPlayer & a_Player) +{ + // It is a simple add player packet in this protocol. + SendPlayerListAddPlayer(a_Player); +} + + + + + +void cProtocol125::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +{ + if (a_OldListName == a_Player.GetName()) { - // Ignore gamemode update return; } - AString PlayerName(a_Player.GetColor()); - PlayerName.append(a_Player.GetName()); - if (PlayerName.length() > 14) + cCSLock Lock(m_CSPacket); + + // Remove the old name from the tablist: { - PlayerName.erase(14); + WriteByte (PACKET_PLAYER_LIST_ITEM); + WriteString(a_OldListName); + WriteBool (false); + WriteShort (0); + Flush(); } - PlayerName += cChatColor::White; - WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM); - WriteString(PlayerName); - WriteBool (a_Action != 4); - WriteShort ((a_Action == 4) ? 0 : a_Player.GetClientHandle()->GetPing()); - Flush(); + SendPlayerListAddPlayer(a_Player); } diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 4e140331a..4241c1fd4 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -28,76 +28,80 @@ public: virtual void DataReceived(const char * a_Data, size_t a_Size) override; /// Sending stuff to clients (alphabetically sorted): - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat (const AString & a_Message) override; - virtual void SendChat (const cCompositeChat & a_Message) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendDisconnect (const AString & a_Reason) override; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityHeadLook (const cEntity & a_Entity) override; - virtual void SendEntityLook (const cEntity & a_Entity) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityProperties (const cEntity & a_Entity) override; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; - virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHealth (void) override; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; - virtual void SendKeepAlive (int a_PingID) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; - virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; - virtual void SendPaintingSpawn (const cPainting & a_Painting) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override; - virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message - virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerPosition (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; - virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; - virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; - virtual void SendExperience (void) override; - virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; - virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; - virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override {} // This protocol doesn't support such message - virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override {} // This protocol doesn't support such message - virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; - virtual void SendStatistics (const cStatManager & a_Manager) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendTeleportEntity (const cEntity & a_Entity) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override {} - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; - virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; + virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; + virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; + virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; + virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; + virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; + virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; + virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; + virtual void SendDestroyEntity (const cEntity & a_Entity) override; + virtual void SendDisconnect (const AString & a_Reason) override; + virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) + virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; + virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; + virtual void SendEntityHeadLook (const cEntity & a_Entity) override; + virtual void SendEntityLook (const cEntity & a_Entity) override; + virtual void SendEntityMetadata (const cEntity & a_Entity) override; + virtual void SendEntityProperties (const cEntity & a_Entity) override; + virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; + virtual void SendEntityVelocity (const cEntity & a_Entity) override; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; + virtual void SendGameMode (eGameMode a_GameMode) override; + virtual void SendHealth (void) override; + virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; + virtual void SendKeepAlive (int a_PingID) override; + virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; + virtual void SendLoginSuccess (void) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; + virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; + virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendPickupSpawn (const cPickup & a_Pickup) override; + virtual void SendPlayerAbilities (void) override {} // This protocol doesn't support such message + virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; + virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerMaxSpeed (void) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerPosition (void) override; + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; + virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; + virtual void SendExperience (void) override; + virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override {} // This protocol doesn't support such message + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override {} // This protocol doesn't support such message + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; + virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; + virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; + virtual void SendSpawnMob (const cMonster & a_Mob) override; + virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; + virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; + virtual void SendStatistics (const cStatManager & a_Manager) override; + virtual void SendTabCompletionResults (const AStringVector & a_Results) override; + virtual void SendTeleportEntity (const cEntity & a_Entity) override; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; + virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override {} + virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendWeather (eWeather a_Weather) override; + virtual void SendWholeInventory (const cWindow & a_Window) override; + virtual void SendWindowClose (const cWindow & a_Window) override; + virtual void SendWindowOpen (const cWindow & a_Window) override; + virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; virtual AString GetAuthServerID(void) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f51f15ec2..05935fbe1 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -777,19 +777,71 @@ void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_Sr -void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, char a_Action) +void cProtocol172::SendPlayerListAddPlayer(const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? - if (a_Action == 1) + + cPacketizer Pkt(*this, 0x38); // Playerlist Item packet + Pkt.WriteString(a_Player.GetName()); + Pkt.WriteBool(true); + Pkt.WriteShort(a_Player.GetClientHandle()->GetPing()); +} + + + + + +void cProtocol172::SendPlayerListRemovePlayer(const cPlayer & a_Player) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x38); + Pkt.WriteString(a_Player.GetName()); + Pkt.WriteBool(false); + Pkt.WriteShort(0); +} + + + + + +void cProtocol172::SendPlayerListUpdateGameMode(const cPlayer & a_Player) +{ + // Not implemented in this protocol version + UNUSED(a_Player); +} + + + + + +void cProtocol172::SendPlayerListUpdatePing(const cPlayer & a_Player) +{ + // It is a simple add player packet in this protocol. + SendPlayerListAddPlayer(a_Player); +} + + + + + +void cProtocol172::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +{ + ASSERT(m_State == 3); // In game mode? + if (a_OldListName == a_Player.GetName()) { - // Ignore gamemode update return; } - cPacketizer Pkt(*this, 0x38); // Playerlist Item packet - Pkt.WriteString(a_Player.GetName()); - Pkt.WriteBool(a_Action != 4); - Pkt.WriteShort((a_Action == 4) ? 0 : a_Player.GetClientHandle()->GetPing()); + // Remove the old name from the tablist: + { + cPacketizer Pkt(*this, 0x38); + Pkt.WriteString(a_OldListName); + Pkt.WriteBool(false); + Pkt.WriteShort(0); + } + + SendPlayerListAddPlayer(a_Player); } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 6668d0a87..7ec7d0fce 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -61,76 +61,80 @@ public: virtual void DataReceived(const char * a_Data, size_t a_Size) override; /** Sending stuff to clients (alphabetically sorted): */ - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat (const AString & a_Message) override; - virtual void SendChat (const cCompositeChat & a_Message) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendDisconnect (const AString & a_Reason) override; - virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityHeadLook (const cEntity & a_Entity) override; - virtual void SendEntityLook (const cEntity & a_Entity) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityProperties (const cEntity & a_Entity) override; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; - virtual void SendExperience (void) override; - virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; - virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHealth (void) override; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; - virtual void SendKeepAlive (int a_PingID) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; - virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; - virtual void SendPaintingSpawn (const cPainting & a_Painting) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override; - virtual void SendPlayerAbilities (void) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerPosition (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; - virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; - virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; - virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; - virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; - virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; - virtual void SendStatistics (const cStatManager & a_Manager) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendTeleportEntity (const cEntity & a_Entity) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; - virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; + virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; + virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; + virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; + virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; + virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; + virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; + virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; + virtual void SendDestroyEntity (const cEntity & a_Entity) override; + virtual void SendDisconnect (const AString & a_Reason) override; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; + virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) + virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; + virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; + virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; + virtual void SendEntityHeadLook (const cEntity & a_Entity) override; + virtual void SendEntityLook (const cEntity & a_Entity) override; + virtual void SendEntityMetadata (const cEntity & a_Entity) override; + virtual void SendEntityProperties (const cEntity & a_Entity) override; + virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; + virtual void SendEntityVelocity (const cEntity & a_Entity) override; + virtual void SendExperience (void) override; + virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; + virtual void SendGameMode (eGameMode a_GameMode) override; + virtual void SendHealth (void) override; + virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; + virtual void SendKeepAlive (int a_PingID) override; + virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; + virtual void SendLoginSuccess (void) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; + virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; + virtual void SendPickupSpawn (const cPickup & a_Pickup) override; + virtual void SendPlayerAbilities (void) override; + virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerMaxSpeed (void) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerPosition (void) override; + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; + virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; + virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; + virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; + virtual void SendSpawnMob (const cMonster & a_Mob) override; + virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; + virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; + virtual void SendStatistics (const cStatManager & a_Manager) override; + virtual void SendTabCompletionResults (const AStringVector & a_Results) override; + virtual void SendTeleportEntity (const cEntity & a_Entity) override; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; + virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; + virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendWeather (eWeather a_Weather) override; + virtual void SendWholeInventory (const cWindow & a_Window) override; + virtual void SendWindowClose (const cWindow & a_Window) override; + virtual void SendWindowOpen (const cWindow & a_Window) override; + virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; virtual AString GetAuthServerID(void) override { return m_AuthServerID; } diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index a258d9585..293080166 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -793,74 +793,107 @@ void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_Sr -void cProtocol180::SendPlayerListItem(const cPlayer & a_Player, char a_Action) +void cProtocol180::SendPlayerListAddPlayer(const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, 0x38); // Playerlist Item packet - Pkt.WriteVarInt(a_Action); + Pkt.WriteVarInt(0); Pkt.WriteVarInt(1); Pkt.WriteUUID(a_Player.GetUUID()); + Pkt.WriteString(a_Player.GetName()); - switch (a_Action) + const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties(); + Pkt.WriteVarInt(Properties.size()); + for (Json::Value::iterator itr = Properties.begin(), end = Properties.end(); itr != end; ++itr) { - case 0: - { - // Add Player - Pkt.WriteString(a_Player.GetName()); - - const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties(); - Pkt.WriteVarInt(Properties.size()); - for (Json::Value::iterator itr = Properties.begin(), end = Properties.end(); itr != end; ++itr) - { - Pkt.WriteString(((Json::Value)*itr).get("name", "").asString()); - Pkt.WriteString(((Json::Value)*itr).get("value", "").asString()); - AString Signature = ((Json::Value)*itr).get("signature", "").asString(); - if (Signature.empty()) - { - Pkt.WriteBool(false); - } - else - { - Pkt.WriteBool(true); - Pkt.WriteString(Signature); - } - } - - Pkt.WriteVarInt((UInt32)a_Player.GetGameMode()); - Pkt.WriteVarInt((UInt32)a_Player.GetClientHandle()->GetPing()); - Pkt.WriteBool(false); - break; - } - case 1: - { - // Update GameMode - Pkt.WriteVarInt((UInt32)a_Player.GetGameMode()); - break; - } - case 2: - { - // Update Ping - Pkt.WriteVarInt((UInt32)a_Player.GetClientHandle()->GetPing()); - break; - } - case 3: + Pkt.WriteString(((Json::Value)*itr).get("name", "").asString()); + Pkt.WriteString(((Json::Value)*itr).get("value", "").asString()); + AString Signature = ((Json::Value)*itr).get("signature", "").asString(); + if (Signature.empty()) { - // Update DisplayName Pkt.WriteBool(false); - break; } - case 4: + else { - // Remove player - break; - } - default: - { - ASSERT(!"Unhandled player list item action!"); - return; + Pkt.WriteBool(true); + Pkt.WriteString(Signature); } } + + Pkt.WriteVarInt((UInt32)a_Player.GetGameMode()); + Pkt.WriteVarInt((UInt32)a_Player.GetClientHandle()->GetPing()); + Pkt.WriteBool(false); +} + + + + + +void cProtocol180::SendPlayerListRemovePlayer(const cPlayer & a_Player) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x38); // Playerlist Item packet + Pkt.WriteVarInt(4); + Pkt.WriteVarInt(1); + Pkt.WriteUUID(a_Player.GetUUID()); +} + + + + + +void cProtocol180::SendPlayerListUpdateGameMode(const cPlayer & a_Player) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x38); // Playerlist Item packet + Pkt.WriteVarInt(1); + Pkt.WriteVarInt(1); + Pkt.WriteUUID(a_Player.GetUUID()); + Pkt.WriteVarInt((UInt32)a_Player.GetGameMode()); +} + + + + + +void cProtocol180::SendPlayerListUpdatePing(const cPlayer & a_Player) +{ + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x38); // Playerlist Item packet + Pkt.WriteVarInt(2); + Pkt.WriteVarInt(1); + Pkt.WriteUUID(a_Player.GetUUID()); + Pkt.WriteVarInt((UInt32)a_Player.GetClientHandle()->GetPing()); +} + + + + + +void cProtocol180::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +{ + UNUSED(a_OldListName); + ASSERT(m_State == 3); // In game mode? + + cPacketizer Pkt(*this, 0x38); // Playerlist Item packet + Pkt.WriteVarInt(3); + Pkt.WriteVarInt(1); + Pkt.WriteUUID(a_Player.GetUUID()); + + // TODO: Replace this with GetPlayerListName() (It's already done in other pull request) + if (a_Player.GetName().empty()) + { + Pkt.WriteBool(false); + } + else + { + Pkt.WriteBool(true); + Pkt.WriteString(Printf("{\"text\":\"%s\"}", a_Player.GetName().c_str())); + } } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 7ba2b92cd..fd3121d7f 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -60,76 +60,80 @@ public: virtual void DataReceived(const char * a_Data, size_t a_Size) override; /** Sending stuff to clients (alphabetically sorted): */ - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat (const AString & a_Message) override; - virtual void SendChat (const cCompositeChat & a_Message) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendDisconnect (const AString & a_Reason) override; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityHeadLook (const cEntity & a_Entity) override; - virtual void SendEntityLook (const cEntity & a_Entity) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityProperties (const cEntity & a_Entity) override; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; - virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHealth (void) override; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; - virtual void SendKeepAlive (int a_PingID) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; - virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; - virtual void SendPaintingSpawn (const cPainting & a_Painting) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override; - virtual void SendPlayerAbilities (void) override; - virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerPosition (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; - virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; - virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; - virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; - virtual void SendExperience (void) override; - virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; - virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; - virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; - virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; - virtual void SendStatistics (const cStatManager & a_Manager) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendTeleportEntity (const cEntity & a_Entity) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; - virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; + virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; + virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; + virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; + virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; + virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; + virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; + virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; + virtual void SendDestroyEntity (const cEntity & a_Entity) override; + virtual void SendDisconnect (const AString & a_Reason) override; + virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) + virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; + virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; + virtual void SendEntityHeadLook (const cEntity & a_Entity) override; + virtual void SendEntityLook (const cEntity & a_Entity) override; + virtual void SendEntityMetadata (const cEntity & a_Entity) override; + virtual void SendEntityProperties (const cEntity & a_Entity) override; + virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; + virtual void SendEntityVelocity (const cEntity & a_Entity) override; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; + virtual void SendGameMode (eGameMode a_GameMode) override; + virtual void SendHealth (void) override; + virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; + virtual void SendKeepAlive (int a_PingID) override; + virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; + virtual void SendLoginSuccess (void) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; + virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendPickupSpawn (const cPickup & a_Pickup) override; + virtual void SendPlayerAbilities (void) override; + virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; + virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; + virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerMaxSpeed (void) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerPosition (void) override; + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; + virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; + virtual void SendExperience (void) override; + virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; + virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; + virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; + virtual void SendSpawnMob (const cMonster & a_Mob) override; + virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; + virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; + virtual void SendStatistics (const cStatManager & a_Manager) override; + virtual void SendTabCompletionResults (const AStringVector & a_Results) override; + virtual void SendTeleportEntity (const cEntity & a_Entity) override; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; + virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; + virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendWeather (eWeather a_Weather) override; + virtual void SendWholeInventory (const cWindow & a_Window) override; + virtual void SendWindowClose (const cWindow & a_Window) override; + virtual void SendWindowOpen (const cWindow & a_Window) override; + virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; virtual AString GetAuthServerID(void) override { return m_AuthServerID; } diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 611ef6ce0..36e791fc7 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -489,10 +489,50 @@ void cProtocolRecognizer::SendEntityAnimation(const cEntity & a_Entity, char a_A -void cProtocolRecognizer::SendPlayerListItem(const cPlayer & a_Player, char a_Action) +void cProtocolRecognizer::SendPlayerListAddPlayer(const cPlayer & a_Player) { ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerListItem(a_Player, a_Action); + m_Protocol->SendPlayerListAddPlayer(a_Player); +} + + + + + +void cProtocolRecognizer::SendPlayerListRemovePlayer(const cPlayer & a_Player) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendPlayerListRemovePlayer(a_Player); +} + + + + + +void cProtocolRecognizer::SendPlayerListUpdateGameMode(const cPlayer & a_Player) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendPlayerListUpdateGameMode(a_Player); +} + + + + + +void cProtocolRecognizer::SendPlayerListUpdatePing(const cPlayer & a_Player) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendPlayerListUpdatePing(a_Player); +} + + + + + +void cProtocolRecognizer::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_OldListName); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 9a0169b97..3177f06ae 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -64,76 +64,80 @@ public: virtual void DataReceived(const char * a_Data, size_t a_Size) override; /// Sending stuff to clients (alphabetically sorted): - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; - virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; - virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; - virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; - virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; - virtual void SendChat (const AString & a_Message) override; - virtual void SendChat (const cCompositeChat & a_Message) override; - virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; - virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; - virtual void SendDestroyEntity (const cEntity & a_Entity) override; - virtual void SendDisconnect (const AString & a_Reason) override; - virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) - virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityHeadLook (const cEntity & a_Entity) override; - virtual void SendEntityLook (const cEntity & a_Entity) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityProperties (const cEntity & a_Entity) override; - virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; - virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendEntityVelocity (const cEntity & a_Entity) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; - virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHealth (void) override; - virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; - virtual void SendKeepAlive (int a_PingID) override; - virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; - virtual void SendLoginSuccess (void) override; - virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; - virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; - virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; - virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; - virtual void SendPaintingSpawn (const cPainting & a_Painting) override; - virtual void SendPickupSpawn (const cPickup & a_Pickup) override; - virtual void SendPlayerAbilities (void) override; - virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; - virtual void SendPlayerListItem (const cPlayer & a_Player, char a_Action) override; - virtual void SendPlayerMaxSpeed (void) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerPosition (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; - virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; - virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; - virtual void SendExperience (void) override; - virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; - virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; - virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; - virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; - virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; - virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; - virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; - virtual void SendStatistics (const cStatManager & a_Manager) override; - virtual void SendTabCompletionResults(const AStringVector & a_Results) override; - virtual void SendTeleportEntity (const cEntity & a_Entity) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; - virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; - virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; - virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; - virtual void SendWindowOpen (const cWindow & a_Window) override; - virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; + virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override; + virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; + virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; + virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; + virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; + virtual void SendChat (const AString & a_Message) override; + virtual void SendChat (const cCompositeChat & a_Message) override; + virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override; + virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override; + virtual void SendDestroyEntity (const cEntity & a_Entity) override; + virtual void SendDisconnect (const AString & a_Reason) override; + virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+) + virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override; + virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; + virtual void SendEntityHeadLook (const cEntity & a_Entity) override; + virtual void SendEntityLook (const cEntity & a_Entity) override; + virtual void SendEntityMetadata (const cEntity & a_Entity) override; + virtual void SendEntityProperties (const cEntity & a_Entity) override; + virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; + virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; + virtual void SendEntityVelocity (const cEntity & a_Entity) override; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; + virtual void SendGameMode (eGameMode a_GameMode) override; + virtual void SendHealth (void) override; + virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; + virtual void SendKeepAlive (int a_PingID) override; + virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; + virtual void SendLoginSuccess (void) override; + virtual void SendMapColumn (int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale) override; + virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override; + virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override; + virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendPickupSpawn (const cPickup & a_Pickup) override; + virtual void SendPlayerAbilities (void) override; + virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override; + virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerMaxSpeed (void) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerPosition (void) override; + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; + virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; + virtual void SendExperience (void) override; + virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; + virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; + virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; + virtual void SendSpawnMob (const cMonster & a_Mob) override; + virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) override; + virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override; + virtual void SendStatistics (const cStatManager & a_Manager) override; + virtual void SendTabCompletionResults (const AStringVector & a_Results) override; + virtual void SendTeleportEntity (const cEntity & a_Entity) override; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; + virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; + virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendWeather (eWeather a_Weather) override; + virtual void SendWholeInventory (const cWindow & a_Window) override; + virtual void SendWindowClose (const cWindow & a_Window) override; + virtual void SendWindowOpen (const cWindow & a_Window) override; + virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override; virtual AString GetAuthServerID(void) override; diff --git a/src/World.cpp b/src/World.cpp index 2d2137b3f..71ce7e680 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2153,7 +2153,7 @@ void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src -void cWorld::BroadcastPlayerListItem(const cPlayer & a_Player, char a_Action, const cClientHandle * a_Exclude) +void cWorld::BroadcastPlayerListAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) { cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) @@ -2163,7 +2163,79 @@ void cWorld::BroadcastPlayerListItem(const cPlayer & a_Player, char a_Action, co { continue; } - ch->SendPlayerListItem(a_Player, a_Action); + ch->SendPlayerListAddPlayer(a_Player); + } +} + + + + + +void cWorld::BroadcastPlayerListRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) +{ + cCSLock Lock(m_CSPlayers); + for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + cClientHandle * ch = (*itr)->GetClientHandle(); + if ((ch == a_Exclude) || (ch == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + { + continue; + } + ch->SendPlayerListRemovePlayer(a_Player); + } +} + + + + + +void cWorld::BroadcastPlayerListUpdateGameMode(const cPlayer & a_Player, const cClientHandle * a_Exclude) +{ + cCSLock Lock(m_CSPlayers); + for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + cClientHandle * ch = (*itr)->GetClientHandle(); + if ((ch == a_Exclude) || (ch == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + { + continue; + } + ch->SendPlayerListUpdateGameMode(a_Player); + } +} + + + + + +void cWorld::BroadcastPlayerListUpdatePing(const cPlayer & a_Player, const cClientHandle * a_Exclude) +{ + cCSLock Lock(m_CSPlayers); + for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + cClientHandle * ch = (*itr)->GetClientHandle(); + if ((ch == a_Exclude) || (ch == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + { + continue; + } + ch->SendPlayerListUpdatePing(a_Player); + } +} + + + + + +void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName, const cClientHandle * a_Exclude) +{ + cCSLock Lock(m_CSPlayers); + for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + cClientHandle * ch = (*itr)->GetClientHandle(); + if ((ch == a_Exclude) || (ch == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + { + continue; + } + ch->SendPlayerListUpdateDisplayName(a_Player, a_OldListName); } } @@ -2686,7 +2758,7 @@ void cWorld::SendPlayerList(cPlayer * a_DestPlayer) cClientHandle * ch = (*itr)->GetClientHandle(); if ((ch != NULL) && !ch->IsDestroyed()) { - a_DestPlayer->GetClientHandle()->SendPlayerListItem(*(*itr), 0); + a_DestPlayer->GetClientHandle()->SendPlayerListAddPlayer(*(*itr)); } } } diff --git a/src/World.h b/src/World.h index c7b377a21..391124a03 100644 --- a/src/World.h +++ b/src/World.h @@ -223,33 +223,37 @@ public: void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = NULL); // tolua_end - void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL); - void BroadcastCollectEntity (const cEntity & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); - void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override; // tolua_export - void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = NULL); // tolua_export - void BroadcastPlayerListItem (const cPlayer & a_Player, char a_Action, const cClientHandle * a_Exclude = NULL); - void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); - void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); - void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); - void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display); - void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export - void BroadcastSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export - void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); - void BroadcastTimeUpdate (const cClientHandle * a_Exclude = NULL); - virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; - void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = NULL); + void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL); + void BroadcastCollectEntity (const cEntity & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); + void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL); + void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); + virtual void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override; // tolua_export + void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = NULL); // tolua_export + void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); + void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); + void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); + void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); + void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName, const cClientHandle * a_Exclude = NULL); + void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); + void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); + void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); + void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display); + void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export + void BroadcastSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export + void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); + void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); + void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); + void BroadcastTimeUpdate (const cClientHandle * a_Exclude = NULL); + virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = NULL); virtual cBroadcastInterface & GetBroadcastManager(void) override { -- cgit v1.2.3 From 52c875531ec3622eedd7096e44f6bc67c5e5483b Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 18 Sep 2014 18:51:36 +0200 Subject: Derp --- src/Entities/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 36d8307b0..55065d550 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -266,7 +266,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) cTimer t1; if (m_LastPlayerListTime + PLAYER_LIST_TIME_MS <= t1.GetNowTime()) { - // m_World->BroadcastPlayerListUpdatePing(*this); + m_World->BroadcastPlayerListUpdatePing(*this); m_LastPlayerListTime = t1.GetNowTime(); } -- cgit v1.2.3 From 0baca1f1d8e5e8f97e7aa81e319e343949879622 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 19 Sep 2014 14:36:02 +0200 Subject: Updated SPAWNING_ENTITY hook description. --- MCServer/Plugins/APIDump/Hooks/OnSpawningEntity.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MCServer/Plugins/APIDump/Hooks/OnSpawningEntity.lua b/MCServer/Plugins/APIDump/Hooks/OnSpawningEntity.lua index c4bff3916..e2bd1c940 100644 --- a/MCServer/Plugins/APIDump/Hooks/OnSpawningEntity.lua +++ b/MCServer/Plugins/APIDump/Hooks/OnSpawningEntity.lua @@ -6,8 +6,9 @@ return DefaultFnName = "OnSpawningEntity", -- also used as pagename Desc = [[ This hook is called before the server spawns an {{cEntity|entity}}. The plugin can either modify the - entity before it is spawned, or disable the spawning altogether. If the entity spawning is a - monster, the {{OnSpawningMonster|HOOK_SPAWNING_MONSTER}} hook is called before this hook.

+ entity before it is spawned, or disable the spawning altogether. You can't disable the spawning if the + entity is a player. If the entity spawning is a monster, the {{OnSpawningMonster|HOOK_SPAWNING_MONSTER}} + hook is called before this hook.

See also the {{OnSpawnedEntity|HOOK_SPAWNED_ENTITY}} hook for a similar hook called after the entity is spawned. -- cgit v1.2.3 From 6aa331a4fa314daebfb76161b7e26685d7786e2e Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 19 Sep 2014 15:07:01 +0200 Subject: Code improvements. --- src/Protocol/ChunkDataSerializer.cpp | 62 +++++++++++++++++------------------- src/Protocol/ChunkDataSerializer.h | 2 +- src/Protocol/Protocol18x.cpp | 8 ++--- src/Protocol/ProtocolRecognizer.cpp | 2 +- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index 61df24c31..a133cc0e3 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -45,7 +45,7 @@ const AString & cChunkDataSerializer::Serialize(int a_Version, int a_ChunkX, int { case RELEASE_1_2_5: Serialize29(data); break; case RELEASE_1_3_2: Serialize39(data); break; - case RELEASE_1_8_0: Serialize80(data, a_ChunkX, a_ChunkZ); break; + case RELEASE_1_8_0: Serialize47(data, a_ChunkX, a_ChunkZ); break; // TODO: Other protocol versions may serialize the data differently; implement here default: @@ -181,43 +181,41 @@ void cChunkDataSerializer::Serialize39(AString & a_Data) -void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_ChunkZ) +void cChunkDataSerializer::Serialize47(AString & a_Data, int a_ChunkX, int a_ChunkZ) { - // TODO: Do not copy data and then compress it; rather, compress partial blocks of data (zlib *can* stream) - - // Blocktypes converter (1.8 included the meta into the blocktype): - unsigned char Blocks[cChunkDef::NumBlocks * 2]; - size_t LastOffset = 0; - for (size_t Index = 0; Index < cChunkDef::NumBlocks; Index++) - { - BLOCKTYPE BlockType = m_BlockTypes[Index] & 0xFF; - NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; - Blocks[LastOffset] = (unsigned char)(BlockType << 4) | BlockMeta; - Blocks[LastOffset + 1] = (unsigned char)(BlockType >> 4); - LastOffset += 2; - } - - const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; - const int BlockLightOffset = sizeof(Blocks); - const int SkyLightOffset = BlockLightOffset + sizeof(m_BlockLight); - const int BiomeOffset = SkyLightOffset + sizeof(m_BlockSkyLight); - const int DataSize = BiomeOffset + BiomeDataSize; - - // Temporary buffer for the composed data: - char AllData [DataSize]; - memcpy(AllData, Blocks, sizeof(Blocks)); - memcpy(AllData + BlockLightOffset, m_BlockLight, sizeof(m_BlockLight)); - memcpy(AllData + SkyLightOffset, m_BlockSkyLight, sizeof(m_BlockSkyLight)); - memcpy(AllData + BiomeOffset, m_BiomeData, BiomeDataSize); + // This function returns the fully compressed packet (including packet size), not the raw packet! + // Create the packet: cByteBuffer Packet(512 KiB); Packet.WriteVarInt(0x21); // Packet id (Chunk Data packet) Packet.WriteBEInt(a_ChunkX); Packet.WriteBEInt(a_ChunkZ); Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag Packet.WriteBEShort((short) 0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff - Packet.WriteVarInt(DataSize); // Chunk size - Packet.WriteBuf(AllData, DataSize); // Chunk data + + // Write the chunk size: + const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; + UInt32 ChunkSize = ( + (cChunkDef::NumBlocks * 2) + // Block meta + type + sizeof(m_BlockLight) + // Block light + sizeof(m_BlockSkyLight) + // Block sky light + BiomeDataSize // Biome data + ); + Packet.WriteVarInt(ChunkSize); + + // Write the block types to the packet: + for (size_t Index = 0; Index < cChunkDef::NumBlocks; Index++) + { + BLOCKTYPE BlockType = m_BlockTypes[Index] & 0xFF; + NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f; + Packet.WriteByte((unsigned char)(BlockType << 4) | BlockMeta); + Packet.WriteByte((unsigned char)(BlockType >> 4)); + } + + // Write the rest: + Packet.WriteBuf(m_BlockLight, sizeof(m_BlockLight)); + Packet.WriteBuf(m_BlockSkyLight, sizeof(m_BlockSkyLight)); + Packet.WriteBuf(m_BiomeData, BiomeDataSize); AString PacketData; Packet.ReadAll(PacketData); @@ -236,13 +234,13 @@ void cChunkDataSerializer::Serialize80(AString & a_Data, int a_ChunkX, int a_Chu else { AString PostData; - Buffer.WriteVarInt(Packet.GetUsedSpace() + 1); + Buffer.WriteVarInt((UInt32)Packet.GetUsedSpace() + 1); Buffer.WriteVarInt(0); Buffer.ReadAll(PostData); Buffer.CommitRead(); a_Data.clear(); - a_Data.resize(PostData.size() + PacketData.size()); + a_Data.reserve(PostData.size() + PacketData.size()); a_Data.append(PostData.data(), PostData.size()); a_Data.append(PacketData.data(), PacketData.size()); } diff --git a/src/Protocol/ChunkDataSerializer.h b/src/Protocol/ChunkDataSerializer.h index 3caa89d41..a082ef3d8 100644 --- a/src/Protocol/ChunkDataSerializer.h +++ b/src/Protocol/ChunkDataSerializer.h @@ -24,7 +24,7 @@ protected: void Serialize29(AString & a_Data); // Release 1.2.4 and 1.2.5 void Serialize39(AString & a_Data); // Release 1.3.1 to 1.7.10 - void Serialize80(AString & a_Data, int a_ChunkX, int a_ChunkZ); // Release 1.8 + void Serialize47(AString & a_Data, int a_ChunkX, int a_ChunkZ); // Release 1.8 public: enum diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 293080166..4b78bc4cd 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -75,6 +75,7 @@ Implements the 1.8.x protocol classes: const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... +const uLongf MAX_COMPRESSED_PACKET_LEN = 200 KiB; // Maximum size of compressed packets. @@ -1513,11 +1514,10 @@ void cProtocol180::SendWindowProperty(const cWindow & a_Window, int a_Property, bool cProtocol180::CompressPacket(const AString & a_Packet, AString & a_CompressedData) { // Compress the data: - const uLongf CompressedMaxSize = 200000; - char CompressedData[CompressedMaxSize]; + char CompressedData[MAX_COMPRESSED_PACKET_LEN]; uLongf CompressedSize = compressBound(a_Packet.size()); - if (CompressedSize >= CompressedMaxSize) + if (CompressedSize >= MAX_COMPRESSED_PACKET_LEN) { ASSERT(!"Too high packet size."); return false; @@ -1541,7 +1541,7 @@ bool cProtocol180::CompressPacket(const AString & a_Packet, AString & a_Compress Buffer.CommitRead(); a_CompressedData.clear(); - a_CompressedData.resize(LengthData.size() + CompressedSize); + a_CompressedData.reserve(LengthData.size() + CompressedSize); a_CompressedData.append(LengthData.data(), LengthData.size()); a_CompressedData.append(CompressedData, CompressedSize); return true; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 4516975bf..a5b745c2f 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -955,7 +955,7 @@ bool cProtocolRecognizer::TryRecognizeLengthlessProtocol(void) m_Protocol = new cProtocol132(m_Client); return true; } - //case PROTO_VERSION_1_4_2: + case PROTO_VERSION_1_4_2: case PROTO_VERSION_1_4_4: { m_Protocol = new cProtocol142(m_Client); -- cgit v1.2.3 From b2573aad50de4968bbc68824295eaed8cc566733 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 19 Sep 2014 22:30:32 +0200 Subject: Fixed typos in items.ini. --- MCServer/items.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MCServer/items.ini b/MCServer/items.ini index df878cdf4..daf366654 100644 --- a/MCServer/items.ini +++ b/MCServer/items.ini @@ -1,5 +1,6 @@ [Items] air=0 +stone=1 rock=1 granite=1:1 polishedgranite=1:2 @@ -409,7 +410,7 @@ lightgraystainedclay=159:8 lightgreystainedclay=159:8 ltgraystainedclay=159:8 ltgreystainedclay=159:8 -silvertstainedclay=159:8 +silverstainedclay=159:8 cyanstainedclay=159:9 purplestainedclay=159:10 violetstainedclay=159:10 -- cgit v1.2.3 From 66ef05c765a7e66ec3d77cd1a1eaff4f03b28688 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 20 Sep 2014 18:41:21 +0200 Subject: QtBiomeVisualiser: Added support for loading Anvil worlds. --- Tools/QtBiomeVisualiser/ChunkSource.cpp | 241 ++++++++++++++++++++++++++ Tools/QtBiomeVisualiser/ChunkSource.h | 34 +++- Tools/QtBiomeVisualiser/MainWindow.cpp | 12 +- Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro | 38 +++- 4 files changed, 320 insertions(+), 5 deletions(-) diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp index 2235816bc..54da2afe5 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.cpp +++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp @@ -3,6 +3,8 @@ #include #include "Generating/BioGen.h" #include "inifile/iniFile.h" +#include "StringCompression.h" +#include "WorldStorage/FastNBT.h" @@ -182,3 +184,242 @@ void BioGenSource::reload() + +//////////////////////////////////////////////////////////////////////////////// +// AnvilSource::AnvilFile + +class AnvilSource::AnvilFile +{ +public: + /** Coordinates of the region file. */ + int m_RegionX, m_RegionZ; + + /** True iff the file contains proper data. */ + bool m_IsValid; + + + + /** Creates a new instance with the specified region coords. Reads the file header. */ + AnvilFile(int a_RegionX, int a_RegionZ, const AString & a_WorldPath) : + m_RegionX(a_RegionX), + m_RegionZ(a_RegionZ), + m_IsValid(false) + { + readFile(Printf("%s/r.%d.%d.mca", a_WorldPath.c_str(), a_RegionX, a_RegionZ)); + } + + + + /** Returns the compressed data of the specified chunk. + Returns an empty string when chunk not present. */ + AString getChunkData(int a_ChunkX, int a_ChunkZ) + { + if (!m_IsValid) + { + return ""; + } + + // Translate to local coords: + int RelChunkX = a_ChunkX - m_RegionX * 32; + int RelChunkZ = a_ChunkZ - m_RegionZ * 32; + ASSERT((RelChunkX >= 0) && (RelChunkX < 32)); + ASSERT((RelChunkZ >= 0) && (RelChunkZ < 32)); + + // Get the chunk data location: + UInt32 chunkOffset = m_Header[RelChunkX + 32 * RelChunkZ] >> 8; + UInt32 numChunkSectors = m_Header[RelChunkX + 32 * RelChunkZ] & 0xff; + if ((chunkOffset < 2) || (numChunkSectors == 0)) + { + return ""; + } + + // Get the real data size: + const char * chunkData = m_FileData.data() + chunkOffset * 4096; + UInt32 chunkSize = GetBEInt(chunkData); + if ((chunkSize < 2) || (chunkSize / 4096 > numChunkSectors)) + { + // Bad data, bail out + return ""; + } + + // Check the compression method: + if (chunkData[4] != 2) + { + // Chunk is in an unknown compression + return ""; + } + chunkSize--; + + // Read the chunk data: + return m_FileData.substr(chunkOffset * 4096 + 5, chunkSize); + } + +protected: + AString m_FileData; + UInt32 m_Header[2048]; + + + /** Reads the whole specified file contents and parses the header. */ + void readFile(const AString & a_FileName) + { + // Read the entire file: + m_FileData = cFile::ReadWholeFile(a_FileName); + if (m_FileData.size() < sizeof(m_Header)) + { + return; + } + + // Parse the header - change endianness: + const char * hdr = m_FileData.data(); + for (size_t i = 0; i < ARRAYCOUNT(m_Header); i++) + { + m_Header[i] = GetBEInt(hdr + 4 * i); + } + m_IsValid = true; + } +}; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// AnvilSource: + +AnvilSource::AnvilSource(QString a_WorldRegionFolder) : + m_WorldRegionFolder(a_WorldRegionFolder) +{ +} + + + + + +void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) +{ + // Load the compressed data: + AString compressedChunkData = getCompressedChunkData(a_ChunkX, a_ChunkZ); + if (compressedChunkData.empty()) + { + return; + } + + // Uncompress the chunk data: + AString uncompressed; + int res = InflateString(compressedChunkData.data(), compressedChunkData.size(), uncompressed); + if (res != Z_OK) + { + return; + } + + // Parse the NBT data: + cParsedNBT nbt(uncompressed.data(), uncompressed.size()); + if (!nbt.IsValid()) + { + return; + } + + // Get the biomes out of the NBT: + int Level = nbt.FindChildByName(0, "Level"); + if (Level < 0) + { + return; + } + cChunkDef::BiomeMap biomeMap; + int mcsBiomes = nbt.FindChildByName(Level, "MCSBiomes"); + if ((mcsBiomes >= 0) && (nbt.GetDataLength(mcsBiomes) == sizeof(biomeMap))) + { + // Convert the biomes from BigEndian to platform native numbers: + const char * beBiomes = nbt.GetData(mcsBiomes); + for (size_t i = 0; i < ARRAYCOUNT(biomeMap); i++) + { + biomeMap[i] = (EMCSBiome)GetBEInt(beBiomes + 4 * i); + } + // Render the biomes: + Chunk::Image img; + biomesToImage(biomeMap, img); + a_DestChunk->setImage(img); + return; + } + + // MCS biomes not found, load Vanilla biomes instead: + int biomes = nbt.FindChildByName(Level, "Biomes"); + if ((biomes < 0) || (nbt.GetDataLength(biomes) != ARRAYCOUNT(biomeMap))) + { + return; + } + // Convert the biomes from Vanilla to EMCSBiome: + const char * vanillaBiomes = nbt.GetData(biomes); + for (size_t i = 0; i < ARRAYCOUNT(biomeMap); i++) + { + biomeMap[i] = EMCSBiome(vanillaBiomes[i]); + } + // Render the biomes: + Chunk::Image img; + biomesToImage(biomeMap, img); + a_DestChunk->setImage(img); +} + + + + + +void AnvilSource::reload() +{ + // Remove all files from the cache: + QMutexLocker lock(&m_Mtx); + m_Files.clear(); +} + + + + + +void AnvilSource::chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ) +{ + a_RegionX = a_ChunkX >> 5; + a_RegionZ = a_ChunkZ >> 5; +} + + + + + +AString AnvilSource::getCompressedChunkData(int a_ChunkX, int a_ChunkZ) +{ + return getAnvilFile(a_ChunkX, a_ChunkZ)->getChunkData(a_ChunkX, a_ChunkZ); +} + + + + + +AnvilSource::AnvilFilePtr AnvilSource::getAnvilFile(int a_ChunkX, int a_ChunkZ) +{ + int RegionX, RegionZ; + chunkToRegion(a_ChunkX, a_ChunkZ, RegionX, RegionZ); + + // Search the cache for the file: + QMutexLocker lock(&m_Mtx); + for (auto itr = m_Files.cbegin(), end = m_Files.cend(); itr != end; ++itr) + { + if (((*itr)->m_RegionX == RegionX) && ((*itr)->m_RegionZ == RegionZ)) + { + // Found the file in the cache, move it to front and return it: + AnvilFilePtr file(*itr); + m_Files.erase(itr); + m_Files.push_front(file); + return file; + } + } + + // File not in cache, create it: + AnvilFilePtr file(new AnvilFile(RegionX, RegionZ, m_WorldRegionFolder.toStdString())); + m_Files.push_front(file); + return file; +} + + + + + diff --git a/Tools/QtBiomeVisualiser/ChunkSource.h b/Tools/QtBiomeVisualiser/ChunkSource.h index 868e4a144..a5612da01 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.h +++ b/Tools/QtBiomeVisualiser/ChunkSource.h @@ -1,4 +1,5 @@ #pragma once +#include "Globals.h" #include #include #include "Chunk.h" @@ -64,11 +65,40 @@ class AnvilSource : public ChunkSource { public: - // TODO + /** Constructs a new AnvilSource based on the world path. */ + AnvilSource(QString a_WorldRegionFolder); // ChunkSource overrides: virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override; - virtual void reload() override {} + virtual void reload() override; + +protected: + class AnvilFile; + typedef std::shared_ptr AnvilFilePtr; + + + /** Folder where the individual Anvil Region files are located. */ + QString m_WorldRegionFolder; + + /** List of currently loaded files. Acts as a cache so that a file is not opened and closed over and over again. + Protected against multithreaded access by m_Mtx. */ + std::list m_Files; + + /** Guards m_Files agains multithreaded access. */ + QMutex m_Mtx; + + + /** Converts chunk coords to region coords. */ + void chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ); + + /** Returns the compressed data of the specified chunk. + Returns an empty string if the chunk is not available. */ + AString getCompressedChunkData(int a_ChunkX, int a_ChunkZ); + + /** Returns the file object that contains the specified chunk. + The file is taken from the cache if available there, otherwise it is created anew. */ + AnvilFilePtr getAnvilFile(int a_ChunkX, int a_ChunkZ); + }; diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index 65d0ccf5e..b6db806f9 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -39,6 +39,10 @@ MainWindow::~MainWindow() void MainWindow::generate() { QString worldIni = QFileDialog::getOpenFileName(this, tr("Open world.ini"), QString(), tr("world.ini (world.ini)")); + if (worldIni.isEmpty()) + { + return; + } m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(worldIni))); m_BiomeView->redraw(); } @@ -49,7 +53,13 @@ void MainWindow::generate() void MainWindow::open() { - // TODO + QString regionFolder = QFileDialog::getExistingDirectory(this, tr("Select the region folder"), QString()); + if (regionFolder.isEmpty()) + { + return; + } + m_BiomeView->setChunkSource(std::shared_ptr(new AnvilSource(regionFolder))); + m_BiomeView->redraw(); } diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro index e6b65e628..283e180f8 100644 --- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro @@ -29,7 +29,24 @@ SOURCES += main.cpp\ ChunkCache.cpp \ Chunk.cpp \ ChunkSource.cpp \ - ChunkLoader.cpp + ChunkLoader.cpp \ + ../../src/StringCompression.cpp \ + ../../src/WorldStorage/FastNBT.cpp \ + ../../lib/zlib/adler32.c \ + ../../lib/zlib/compress.c \ + ../../lib/zlib/crc32.c \ + ../../lib/zlib/deflate.c \ + ../../lib/zlib/gzclose.c \ + ../../lib/zlib/gzlib.c \ + ../../lib/zlib/gzread.c \ + ../../lib/zlib/gzwrite.c \ + ../../lib/zlib/infback.c \ + ../../lib/zlib/inffast.c \ + ../../lib/zlib/inflate.c \ + ../../lib/zlib/inftrees.c \ + ../../lib/zlib/trees.c \ + ../../lib/zlib/uncompr.c \ + ../../lib/zlib/zutil.c HEADERS += MainWindow.h \ Globals.h \ @@ -48,7 +65,20 @@ HEADERS += MainWindow.h \ ChunkCache.h \ Chunk.h \ ChunkSource.h \ - ChunkLoader.h + ChunkLoader.h \ + ../../src/StringCompression.h \ + ../../src/WorldStorage/FastNBT.h \ + ../../lib/zlib/crc32.h \ + ../../lib/zlib/deflate.h \ + ../../lib/zlib/gzguts.h \ + ../../lib/zlib/inffast.h \ + ../../lib/zlib/inffixed.h \ + ../../lib/zlib/inflate.h \ + ../../lib/zlib/inftrees.h \ + ../../lib/zlib/trees.h \ + ../../lib/zlib/zconf.h \ + ../../lib/zlib/zlib.h \ + ../../lib/zlib/zutil.h INCLUDEPATH += $$_PRO_FILE_PWD_ \ $$_PRO_FILE_PWD_/../../src \ @@ -57,4 +87,8 @@ INCLUDEPATH += $$_PRO_FILE_PWD_ \ CONFIG += C++11 +OTHER_FILES += \ + ../../lib/zlib/example.c.txt \ + ../../lib/zlib/minigzip.c.txt + -- cgit v1.2.3 From 3676a84916103ff1fcab472217817e64f5e341a5 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 20 Sep 2014 23:01:42 +0200 Subject: Fixed cParsedNBT::FindTagByPath(). There was an off-by-one error in the name handling. --- src/WorldStorage/FastNBT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp index c6294b99c..ed8e8bb14 100644 --- a/src/WorldStorage/FastNBT.cpp +++ b/src/WorldStorage/FastNBT.cpp @@ -310,7 +310,7 @@ int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const { continue; } - Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin - 1); + Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin); if (Tag < 0) { return -1; -- cgit v1.2.3 From 14123c6d1653b79b6c58e7766dc97e5d06bf1fc9 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 20 Sep 2014 23:03:13 +0200 Subject: QtBiomeVisualiser: Added list of vanilla worlds. --- Tools/QtBiomeVisualiser/MainWindow.cpp | 132 +++++++++++++++++++++++++++++++-- Tools/QtBiomeVisualiser/MainWindow.h | 20 +++++ 2 files changed, 145 insertions(+), 7 deletions(-) diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index b6db806f9..c56cf8bc2 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -5,9 +5,13 @@ #include #include #include +#include +#include #include "inifile/iniFile.h" #include "ChunkSource.h" #include "Generating/BioGen.h" +#include "StringCompression.h" +#include "WorldStorage/FastNBT.h" @@ -16,6 +20,8 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) { + initMinecraftPath(); + m_BiomeView = new BiomeView(this); setCentralWidget(m_BiomeView); @@ -66,8 +72,41 @@ void MainWindow::open() +void MainWindow::openVanillaWorld() +{ + QAction * action = qobject_cast(sender()); + if (action == nullptr) + { + return; + } + m_BiomeView->setChunkSource(std::shared_ptr(new AnvilSource(action->data().toString()))); + m_BiomeView->redraw(); +} + + + + + +void MainWindow::initMinecraftPath() +{ + #ifdef Q_OS_MAC + m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/Library/Application Support/minecraft"); + #elif defined Q_OS_WIN32 + QSettings ini(QSettings::IniFormat, QSettings::UserScope, ".minecraft", "minecraft1"); + m_MinecraftPath = QFileInfo(ini.fileName()).absolutePath(); + #else + m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/.minecraft"); + #endif +} + + + + + void MainWindow::createActions() { + createWorldActions(); + m_actGen = new QAction(tr("&Generate..."), this); m_actGen->setShortcut(tr("Ctrl+N")); m_actGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); @@ -93,15 +132,94 @@ void MainWindow::createActions() +void MainWindow::createWorldActions() +{ + QDir mc(m_MinecraftPath); + if (!mc.cd("saves")) + { + return; + } + + QDirIterator it(mc); + int key = 1; + while (it.hasNext()) + { + it.next(); + if (!it.fileInfo().isDir()) + { + continue; + } + QString name = getWorldName(it.filePath().toStdString()); + if (name.isEmpty()) + { + continue; + } + QAction * w = new QAction(this); + w->setText(name); + w->setData(it.filePath() + "/region"); + if (key < 10) + { + w->setShortcut("Ctrl+" + QString::number(key)); + key++; + } + connect(w, SIGNAL(triggered()), this, SLOT(openVanillaWorld())); + m_WorldActions.append(w); + } +} + + + + + void MainWindow::createMenus() { - QMenu * mFile = menuBar()->addMenu(tr("&World")); - mFile->addAction(m_actGen); - mFile->addAction(m_actOpen); - mFile->addSeparator(); - mFile->addAction(m_actReload); - mFile->addSeparator(); - mFile->addAction(m_actExit); + QMenu * file = menuBar()->addMenu(tr("&Map")); + file->addAction(m_actGen); + file->addSeparator(); + QMenu * worlds = file->addMenu(tr("Open existing")); + worlds->addActions(m_WorldActions); + if (m_WorldActions.empty()) + { + worlds->setEnabled(false); + } + file->addAction(m_actOpen); + file->addSeparator(); + file->addAction(m_actReload); + file->addSeparator(); + file->addAction(m_actExit); +} + + + + + +QString MainWindow::getWorldName(const AString & a_Path) +{ + AString levelData = cFile::ReadWholeFile(a_Path + "/level.dat"); + if (levelData.empty()) + { + // No such file / no data + return QString(); + } + + AString uncompressed; + if (UncompressStringGZIP(levelData.data(), levelData.size(), uncompressed) != Z_OK) + { + return QString(); + } + cParsedNBT nbt(uncompressed.data(), uncompressed.size()); + if (!nbt.IsValid()) + { + return QString(); + } + AString name = nbt.GetName(1); + OutputDebugStringA(name.c_str()); + int levelNameTag = nbt.FindTagByPath(nbt.GetRoot(), "Data\\LevelName"); + if ((levelNameTag <= 0) || (nbt.GetType(levelNameTag) != TAG_String)) + { + return QString(); + } + return QString::fromStdString(nbt.GetString(levelNameTag)); } diff --git a/Tools/QtBiomeVisualiser/MainWindow.h b/Tools/QtBiomeVisualiser/MainWindow.h index b37bf4120..997d7a5d2 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.h +++ b/Tools/QtBiomeVisualiser/MainWindow.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "BiomeView.h" @@ -25,6 +26,9 @@ private slots: /** Opens an existing world and displays the loaded biomes. */ void open(); + /** Opens a vanilla world that is specified by the calling action. */ + void openVanillaWorld(); + protected: // Actions: QAction * m_actGen; @@ -32,12 +36,28 @@ protected: QAction * m_actReload; QAction * m_actExit; + /** List of actions that open the specific vanilla world. */ + QList m_WorldActions; + + /** Path to the vanilla folder. */ + QString m_MinecraftPath; + + + /** Initializes the m_MinecraftPath based on the proper MC path */ + void initMinecraftPath(); /** Creates the actions that the UI supports. */ void createActions(); + /** Creates the actions that open a specific vanilla world. Iterates over the minecraft saves folder. */ + void createWorldActions(); + /** Creates the menu bar and connects its events. */ void createMenus(); + + /** Returns the name of the vanilla world in the specified path. + Reads the level.dat file for the name. Returns an empty string on failure. */ + QString getWorldName(const AString & a_Path); }; -- cgit v1.2.3 From cb709250779ee6e29d29cacff84e3980983dbd77 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 21 Sep 2014 19:24:45 +0100 Subject: Fix crash in cLineBlockTracer * Fixes #1418 --- src/LineBlockTracer.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/LineBlockTracer.cpp b/src/LineBlockTracer.cpp index f03e796d1..71b8334fa 100644 --- a/src/LineBlockTracer.cpp +++ b/src/LineBlockTracer.cpp @@ -227,9 +227,11 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk) } // Update the current chunk - if (a_Chunk != NULL) + a_Chunk = a_Chunk->GetNeighborChunk(m_CurrentX, m_CurrentZ); + if (a_Chunk == NULL) { - a_Chunk = a_Chunk->GetNeighborChunk(m_CurrentX, m_CurrentZ); + m_Callbacks->OnNoChunk(); + return false; } if (a_Chunk->IsValid()) @@ -245,13 +247,10 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk) return false; } } - else + else if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace)) { - if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace)) - { - // The callback terminated the trace - return false; - } + // The callback terminated the trace + return false; } } } -- cgit v1.2.3 From dda66ea6efaa1ae3305dae97a9ab9bdb4254cf46 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 21 Sep 2014 22:58:09 +0200 Subject: QtBiomeVisualiser: Added the base for INI editting. --- Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp | 125 ++++++++++++++++++++++++++ Tools/QtBiomeVisualiser/GeneratorSetupDlg.h | 53 +++++++++++ Tools/QtBiomeVisualiser/MainWindow.cpp | 77 +++++++++++++--- Tools/QtBiomeVisualiser/MainWindow.h | 25 ++++-- Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro | 6 +- 5 files changed, 266 insertions(+), 20 deletions(-) create mode 100644 Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp create mode 100644 Tools/QtBiomeVisualiser/GeneratorSetupDlg.h diff --git a/Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp b/Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp new file mode 100644 index 000000000..e6037fa9b --- /dev/null +++ b/Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp @@ -0,0 +1,125 @@ +#include "Globals.h" +#include "GeneratorSetupDlg.h" +#include +#include +#include "Generating/BioGen.h" +#include "inifile/iniFile.h" + + + + + +static const QString s_GeneratorNames[] = +{ + QString("Checkerboard"), + QString("Constant"), + QString("DistortedVoronoi"), + QString("MultiStepMap"), + QString("TwoLevel"), + QString("Voronoi"), +}; + + + + + +GeneratorSetupDlg::GeneratorSetupDlg(const AString & a_IniFileName, QWidget * a_Parent) : + super(a_Parent), + m_IniFile(new cIniFile()) +{ + // The generator name is in a separate form layout at the top, always present: + m_cbGenerator = new QComboBox(); + m_cbGenerator->setMinimumWidth(300); + for (size_t i = 0; i < ARRAYCOUNT(s_GeneratorNames); i++) + { + m_cbGenerator->addItem(s_GeneratorNames[i]); + } + QFormLayout * nameLayout = new QFormLayout(); + nameLayout->addRow(new QLabel(tr("Generator")), m_cbGenerator); + + // The rest of the controls are in a dynamically created form layout: + m_FormLayout = new QFormLayout(); + + // The main layout joins these two vertically: + m_MainLayout = new QVBoxLayout(); + m_MainLayout->addLayout(nameLayout); + m_MainLayout->addLayout(m_FormLayout); + setLayout(m_MainLayout); + + // Load the INI file, if specified, otherwise set defaults: + if (!a_IniFileName.empty() && m_IniFile->ReadFile(a_IniFileName)) + { + m_cbGenerator->setCurrentText(QString::fromStdString(m_IniFile->GetValue("Generator", "BiomeGen"))); + } + else + { + m_IniFile->SetValue("Generator", "Generator", "Composable"); + m_IniFile->SetValue("Generator", "BiomeGen", m_cbGenerator->currentText().toStdString()); + bool dummy; + delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); + } + updateFromIni(); + + // Connect the combo change even only after the data has been loaded: + connect(m_cbGenerator, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(generatorChanged(QString))); +} + + + + + +void GeneratorSetupDlg::generatorChanged(const QString & a_NewName) +{ + // Clear the current contents of the form layout by assigning it to a stack temporary: + { + m_MainLayout->takeAt(1); + QWidget().setLayout(m_FormLayout); + } + + // Re-create the layout: + m_FormLayout = new QFormLayout(); + m_MainLayout->addLayout(m_FormLayout); + + // Recreate the INI file: + m_IniFile->Clear(); + m_IniFile->SetValue("Generator", "Generator", "Composable"); + m_IniFile->SetValue("Generator", "BiomeGen", a_NewName.toStdString()); + + // Create a dummy biome gen from the INI file, this will create the defaults in the INI file: + bool dummy; + delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); + + // Read all values from the INI file and put them into the form layout: + updateFromIni(); +} + + + + + +void GeneratorSetupDlg::updateFromIni() +{ + int keyID = m_IniFile->FindKey("Generator"); + if (keyID <= -1) + { + return; + } + int numItems = m_IniFile->GetNumValues(keyID); + for (int i = 0; i < numItems; i++) + { + AString itemName = m_IniFile->GetValueName(keyID, i); + AString itemValue = m_IniFile->GetValue(keyID, i); + if ((itemName == "Generator") || (itemName == "BiomeGen")) + { + // These special cases are not to be added + continue; + } + QLineEdit * edit = new QLineEdit(); + edit->setText(QString::fromStdString(itemValue)); + m_FormLayout->addRow(new QLabel(QString::fromStdString(itemName)), edit); + } // for i - INI values[] +} + + + + diff --git a/Tools/QtBiomeVisualiser/GeneratorSetupDlg.h b/Tools/QtBiomeVisualiser/GeneratorSetupDlg.h new file mode 100644 index 000000000..d7070e331 --- /dev/null +++ b/Tools/QtBiomeVisualiser/GeneratorSetupDlg.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include +#include + + + + + +class cIniFile; + + + + + +class GeneratorSetupDlg : + public QDialog +{ + typedef QDialog super; + + Q_OBJECT + +public: + /** Creates the dialog and loads the contents of the INI file, if not empty. */ + explicit GeneratorSetupDlg(const std::string & a_IniFileName, QWidget * parent = nullptr); + +signals: + +public slots: + /** Called when the user selects a different generator from the top combobox. + Re-creates m_IniFile and updates the form layout. */ + void generatorChanged(const QString & a_NewName); + +protected: + QComboBox * m_cbGenerator; + QVBoxLayout * m_MainLayout; + QFormLayout * m_FormLayout; + + std::unique_ptr m_IniFile; + + int m_Seed; + + + /** Updates the form layout with the values from m_IniFile. */ + void updateFromIni(); +}; + + + + diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index c56cf8bc2..d2c1ae2c1 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -12,6 +12,7 @@ #include "Generating/BioGen.h" #include "StringCompression.h" #include "WorldStorage/FastNBT.h" +#include "GeneratorSetupDlg.h" @@ -42,13 +43,37 @@ MainWindow::~MainWindow() -void MainWindow::generate() +void MainWindow::newGenerator() { + // TODO + + // (Re-)open the generator setup dialog: + m_GeneratorSetupDlg.reset(new GeneratorSetupDlg("")); + m_GeneratorSetupDlg->show(); + m_GeneratorSetupDlg->raise(); + + // TODO +} + + + + + +void MainWindow::openGenerator() +{ + // Let the user specify the world.ini file: QString worldIni = QFileDialog::getOpenFileName(this, tr("Open world.ini"), QString(), tr("world.ini (world.ini)")); if (worldIni.isEmpty()) { return; } + + // (Re-)open the generator setup dialog: + m_GeneratorSetupDlg.reset(new GeneratorSetupDlg(worldIni.toStdString())); + m_GeneratorSetupDlg->show(); + m_GeneratorSetupDlg->raise(); + + // Set the chunk source: m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(worldIni))); m_BiomeView->redraw(); } @@ -57,13 +82,23 @@ void MainWindow::generate() -void MainWindow::open() +void MainWindow::openWorld() { + // Let the user specify the world: QString regionFolder = QFileDialog::getExistingDirectory(this, tr("Select the region folder"), QString()); if (regionFolder.isEmpty()) { return; } + + // Remove the generator setup dialog, if open: + if (m_GeneratorSetupDlg.get() != nullptr) + { + m_GeneratorSetupDlg->hide(); + m_GeneratorSetupDlg.reset(nullptr); + } + + // Set the chunk source: m_BiomeView->setChunkSource(std::shared_ptr(new AnvilSource(regionFolder))); m_BiomeView->redraw(); } @@ -74,11 +109,21 @@ void MainWindow::open() void MainWindow::openVanillaWorld() { + // The world is stored in the sender action's data, retrieve it: QAction * action = qobject_cast(sender()); if (action == nullptr) { return; } + + // Remove the generator setup dialog, if open: + if (m_GeneratorSetupDlg.get() != nullptr) + { + m_GeneratorSetupDlg->hide(); + m_GeneratorSetupDlg.reset(nullptr); + } + + // Set the chunk source: m_BiomeView->setChunkSource(std::shared_ptr(new AnvilSource(action->data().toString()))); m_BiomeView->redraw(); } @@ -107,19 +152,24 @@ void MainWindow::createActions() { createWorldActions(); - m_actGen = new QAction(tr("&Generate..."), this); - m_actGen->setShortcut(tr("Ctrl+N")); - m_actGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); - connect(m_actGen, SIGNAL(triggered()), this, SLOT(generate())); + m_actNewGen = new QAction(tr("&New generator"), this); + m_actNewGen->setShortcut(tr("Ctrl+N")); + m_actNewGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); + connect(m_actNewGen, SIGNAL(triggered()), this, SLOT(newGenerator())); + + m_actOpenGen = new QAction(tr("&Open generator..."), this); + m_actOpenGen->setShortcut(tr("Ctrl+G")); + m_actOpenGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); + connect(m_actOpenGen, SIGNAL(triggered()), this, SLOT(openGenerator())); - m_actOpen = new QAction(tr("&Open world..."), this); - m_actOpen->setShortcut(tr("Ctrl+O")); - m_actOpen->setStatusTip(tr("Open an existing world and display its biomes")); - connect(m_actOpen, SIGNAL(triggered()), this, SLOT(open())); + m_actOpenWorld = new QAction(tr("&Open world..."), this); + m_actOpenWorld->setShortcut(tr("Ctrl+O")); + m_actOpenWorld->setStatusTip(tr("Open an existing world and display its biomes")); + connect(m_actOpenWorld, SIGNAL(triggered()), this, SLOT(openWorld())); m_actReload = new QAction(tr("&Reload"), this); m_actReload->setShortcut(tr("F5")); - m_actReload->setStatusTip(tr("Open an existing world and display its biomes")); + m_actReload->setStatusTip(tr("Clear the view cache and force a reload of all the data")); connect(m_actReload, SIGNAL(triggered()), m_BiomeView, SLOT(reload())); m_actExit = new QAction(tr("E&xit"), this); @@ -174,7 +224,8 @@ void MainWindow::createWorldActions() void MainWindow::createMenus() { QMenu * file = menuBar()->addMenu(tr("&Map")); - file->addAction(m_actGen); + file->addAction(m_actNewGen); + file->addAction(m_actOpenGen); file->addSeparator(); QMenu * worlds = file->addMenu(tr("Open existing")); worlds->addActions(m_WorldActions); @@ -182,7 +233,7 @@ void MainWindow::createMenus() { worlds->setEnabled(false); } - file->addAction(m_actOpen); + file->addAction(m_actOpenWorld); file->addSeparator(); file->addAction(m_actReload); file->addSeparator(); diff --git a/Tools/QtBiomeVisualiser/MainWindow.h b/Tools/QtBiomeVisualiser/MainWindow.h index 997d7a5d2..840e01b0f 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.h +++ b/Tools/QtBiomeVisualiser/MainWindow.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include "BiomeView.h" @@ -8,6 +9,13 @@ +// fwd: +class GeneratorSetupDlg; + + + + + class MainWindow : public QMainWindow { @@ -16,23 +24,27 @@ class MainWindow : BiomeView * m_BiomeView; public: - MainWindow(QWidget *parent = 0); + MainWindow(QWidget * parent = nullptr); ~MainWindow(); private slots: + /** Creates a generator definition from scratch, lets user modify generator params in realtime. */ + void newGenerator(); + /** Opens a generator definition and generates the biomes based on that. */ - void generate(); + void openGenerator(); /** Opens an existing world and displays the loaded biomes. */ - void open(); + void openWorld(); /** Opens a vanilla world that is specified by the calling action. */ void openVanillaWorld(); protected: // Actions: - QAction * m_actGen; - QAction * m_actOpen; + QAction * m_actNewGen; + QAction * m_actOpenGen; + QAction * m_actOpenWorld; QAction * m_actReload; QAction * m_actExit; @@ -42,6 +54,9 @@ protected: /** Path to the vanilla folder. */ QString m_MinecraftPath; + /** The dialog for setting up the generator. */ + std::unique_ptr m_GeneratorSetupDlg; + /** Initializes the m_MinecraftPath based on the proper MC path */ void initMinecraftPath(); diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro index 283e180f8..7171562bb 100644 --- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro @@ -46,7 +46,8 @@ SOURCES += main.cpp\ ../../lib/zlib/inftrees.c \ ../../lib/zlib/trees.c \ ../../lib/zlib/uncompr.c \ - ../../lib/zlib/zutil.c + ../../lib/zlib/zutil.c \ + GeneratorSetupDlg.cpp HEADERS += MainWindow.h \ Globals.h \ @@ -78,7 +79,8 @@ HEADERS += MainWindow.h \ ../../lib/zlib/trees.h \ ../../lib/zlib/zconf.h \ ../../lib/zlib/zlib.h \ - ../../lib/zlib/zutil.h + ../../lib/zlib/zutil.h \ + GeneratorSetupDlg.h INCLUDEPATH += $$_PRO_FILE_PWD_ \ $$_PRO_FILE_PWD_/../../src \ -- cgit v1.2.3 From 195b646aa4189ec9858f4994754eadd2c05ef9df Mon Sep 17 00:00:00 2001 From: Chris Darnell Date: Mon, 22 Sep 2014 03:22:36 -0400 Subject: Made it compile with clang --- src/Entities/Entity.cpp | 4 ++-- src/Entities/Minecart.cpp | 4 ++-- src/Generating/Caves.cpp | 2 +- src/Generating/Noise3DGenerator.cpp | 4 ++-- src/LineBlockTracer.cpp | 6 +++--- src/Tracer.cpp | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 42b207c48..996f2fff3 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -260,7 +260,7 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R void cEntity::SetYawFromSpeed(void) { const double EPS = 0.0000001; - if ((abs(m_Speed.x) < EPS) && (abs(m_Speed.z) < EPS)) + if ((std::abs(m_Speed.x) < EPS) && (std::abs(m_Speed.z) < EPS)) { // atan2() may overflow or is undefined, pick any number SetYaw(0); @@ -277,7 +277,7 @@ void cEntity::SetPitchFromSpeed(void) { const double EPS = 0.0000001; double xz = sqrt(m_Speed.x * m_Speed.x + m_Speed.z * m_Speed.z); // Speed XZ-plane component - if ((abs(xz) < EPS) && (abs(m_Speed.y) < EPS)) + if ((std::abs(xz) < EPS) && (std::abs(m_Speed.y) < EPS)) { // atan2() may overflow or is undefined, pick any number SetPitch(0); diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 1501eea84..bc9e21d8e 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -876,7 +876,7 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); // Prevent division by small numbers - if (abs(Distance.z) < 0.001) + if (std::abs(Distance.z) < 0.001) { Distance.z = 0.001; } @@ -925,7 +925,7 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); // Prevent division by small numbers - if (abs(Distance.z) < 0.001) + if (std::abs(Distance.z) < 0.001) { Distance.z = 0.001; } diff --git a/src/Generating/Caves.cpp b/src/Generating/Caves.cpp index 71154dff9..fc925a150 100644 --- a/src/Generating/Caves.cpp +++ b/src/Generating/Caves.cpp @@ -755,7 +755,7 @@ void cStructGenDualRidgeCaves::GenFinish(cChunkDesc & a_ChunkDesc) float n2 = m_Noise2.CubicNoise3D(xx, yy, zz); float n3 = m_Noise1.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4; float n4 = m_Noise2.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4; - if ((abs(n1 + n3) * abs(n2 + n4)) > m_Threshold) + if ((std::abs(n1 + n3) * std::abs(n2 + n4)) > m_Threshold) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); } diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index eb816f564..c3ca30384 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -236,7 +236,7 @@ void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DAT m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 25, EndX / 25, StartZ / 25, EndZ / 25); for (size_t i = 0; i < ARRAYCOUNT(Height); i++) { - Height[i] = abs(Height[i]) * m_HeightAmplification + 1; + Height[i] = std::abs(Height[i]) * m_HeightAmplification + 1; } // Modify the noise by height data: @@ -395,7 +395,7 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) for (int x = 0; x < 17; x += UPSCALE_X) { NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX; - NOISE_DATATYPE val = abs(m_Noise1.CubicNoise2D(NoiseX / 5, NoiseZ / 5)) * m_HeightAmplification + 1; + NOISE_DATATYPE val = std::abs(m_Noise1.CubicNoise2D(NoiseX / 5, NoiseZ / 5)) * m_HeightAmplification + 1; Height[x + 17 * z] = val * val * val; } } diff --git a/src/LineBlockTracer.cpp b/src/LineBlockTracer.cpp index 71b8334fa..1b42081c2 100644 --- a/src/LineBlockTracer.cpp +++ b/src/LineBlockTracer.cpp @@ -146,7 +146,7 @@ bool cLineBlockTracer::MoveToNextBlock(void) dirY, dirZ, } Direction = dirNONE; - if (abs(m_DiffX) > EPS) + if (std::abs(m_DiffX) > EPS) { double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX; Coeff = (DestX - m_StartX) / m_DiffX; @@ -155,7 +155,7 @@ bool cLineBlockTracer::MoveToNextBlock(void) Direction = dirX; } } - if (abs(m_DiffY) > EPS) + if (std::abs(m_DiffY) > EPS) { double DestY = (m_DirY > 0) ? (m_CurrentY + 1) : m_CurrentY; double CoeffY = (DestY - m_StartY) / m_DiffY; @@ -165,7 +165,7 @@ bool cLineBlockTracer::MoveToNextBlock(void) Direction = dirY; } } - if (abs(m_DiffZ) > EPS) + if (std::abs(m_DiffZ) > EPS) { double DestZ = (m_DirZ > 0) ? (m_CurrentZ + 1) : m_CurrentZ; double CoeffZ = (DestZ - m_StartZ) / m_DiffZ; diff --git a/src/Tracer.cpp b/src/Tracer.cpp index 756147a7b..8ccd18071 100644 --- a/src/Tracer.cpp +++ b/src/Tracer.cpp @@ -250,7 +250,7 @@ int LinesCross(float x0, float y0, float x1, float y1, float x2, float y2, float // float linx, liny; float d=(x1-x0)*(y3-y2)-(y1-y0)*(x3-x2); - if (abs(d)<0.001) {return 0;} + if (std::abs(d)<0.001) {return 0;} float AB=((y0-y2)*(x3-x2)-(x0-x2)*(y3-y2))/d; if (AB>=0.0 && AB<=1.0) { -- cgit v1.2.3 From bcb11078e323240b21d5ff1de8b694212eea2bbf Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 22 Sep 2014 17:15:08 +0200 Subject: Fixed item nbt reading. --- src/Protocol/Protocol18x.cpp | 168 ++++++++++++++++++++++++++++++++++++++++++- src/Protocol/Protocol18x.h | 3 + 2 files changed, 168 insertions(+), 3 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 4b78bc4cd..07e21923c 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1652,6 +1652,169 @@ void cProtocol180::FixItemFramePositions(int a_ObjectData, double & a_PosX, doub +AString cProtocol180::ReadNBTDataFromBuffer(cByteBuffer & a_ByteBuffer, int a_ListTag) +{ + cByteBuffer BufferCache(64 KiB); + AString Data; + + while (a_ByteBuffer.GetReadableSpace() != 0) + { + unsigned char TypeID; + if (a_ListTag != 0) + { + TypeID = (unsigned char)a_ListTag; + } + else + { + if (!a_ByteBuffer.ReadByte(TypeID)) + { + // Can't read the next byte + break; + } + BufferCache.WriteByte(TypeID); + } + + if ((TypeID <= eTagType::TAG_Min) || (TypeID > eTagType::TAG_Max)) + { + // Bad type id (or TAG_End) + break; + } + eTagType TagType = static_cast(TypeID); + + // Read the following string length: + if (a_ListTag == 0) + { + short StrLength = 0; + if (!a_ByteBuffer.ReadBEShort(StrLength)) + { + // Can't read string length + return Data; + } + BufferCache.WriteBEShort(StrLength); + + // Read string and write to BufferCache: + AString TagTitle; + if (!a_ByteBuffer.ReadString(TagTitle, (size_t)StrLength)) + { + // Can't read string + return Data; + } + BufferCache.WriteBuf(TagTitle.data(), TagTitle.size()); + } + + size_t TagLength = 0; + switch (TagType) + { + case eTagType::TAG_Byte: TagLength = sizeof(Byte); break; + case eTagType::TAG_Short: TagLength = sizeof(short); break; + case eTagType::TAG_Int: TagLength = sizeof(int); break; + case eTagType::TAG_Long: TagLength = sizeof(long); break; + case eTagType::TAG_Float: TagLength = sizeof(float); break; + case eTagType::TAG_Double: TagLength = sizeof(double); break; + case eTagType::TAG_End: break; + case eTagType::TAG_Compound: + { + AString CompoundData = ReadNBTDataFromBuffer(a_ByteBuffer); + Data.append(CompoundData.data(), CompoundData.size()); + break; + } + case eTagType::TAG_List: + { + Byte ListType; + int ListLength; + if (!a_ByteBuffer.ReadByte(ListType) || !a_ByteBuffer.ReadBEInt(ListLength) || (ListLength < 0)) + { + // Bad list type or list length + return Data; + } + LOGWARNING("LIST, Type: %i", (int)ListType); + + BufferCache.WriteByte(ListType); + BufferCache.WriteBEInt(ListLength); + + if ((ListType <= eTagType::TAG_Min) || (ListType > eTagType::TAG_Max)) + { + // Bad tag type + return Data; + } + + for (int i = 0; i < ListLength; i++) + { + AString EntryData = ReadNBTDataFromBuffer(a_ByteBuffer, ListType); + BufferCache.WriteBuf(EntryData.data(), EntryData.size()); + } + break; + } + case eTagType::TAG_String: + { + // Read the following string length: + short StrLength; + if (!a_ByteBuffer.ReadBEShort(StrLength)) + { + // Can't read string length + return Data; + } + BufferCache.WriteBEShort(StrLength); + TagLength += (size_t)StrLength; + break; + } + case eTagType::TAG_ByteArray: + { + int ArrayLength; + if (!a_ByteBuffer.ReadBEInt(ArrayLength) || (ArrayLength < 0) || (ArrayLength >= 16777216)) + { + // Bad array length + return Data; + } + BufferCache.WriteBEInt(ArrayLength); + TagLength += (size_t) ArrayLength; + break; + } + case eTagType::TAG_IntArray: + { + int ArrayLength; + if (!a_ByteBuffer.ReadBEInt(ArrayLength) || (ArrayLength < 0) || (ArrayLength >= 16777216)) + { + // Bad array length + return Data; + } + BufferCache.WriteBEInt(ArrayLength); + TagLength += (size_t)ArrayLength * sizeof(int); + break; + } + } + + // Copy tag bytes to the cache: + AString TagBytes; + if (!a_ByteBuffer.ReadString(TagBytes, TagLength)) + { + break; + } + BufferCache.WriteBuf(TagBytes.data(), TagBytes.size()); + + // Write cache to Data and clean: + AString Bytes; + BufferCache.ReadAll(Bytes); + BufferCache.CommitRead(); + Data.append(Bytes.data(), Bytes.size()); + } + + // Read the rest from cache + if (BufferCache.GetUsedSpace() != 0) + { + AString Bytes; + BufferCache.ReadAll(Bytes); + BufferCache.CommitRead(); + Data.append(Bytes.data(), Bytes.size()); + } + + return Data; +} + + + + + void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) { // Write the incoming data into the comm log file: @@ -2530,9 +2693,8 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) a_Item.Empty(); } - AString Metadata; - a_ByteBuffer.ReadAll(Metadata); - if ((Metadata.size() == 0) || (Metadata[0] == 0)) + AString Metadata = ReadNBTDataFromBuffer(a_ByteBuffer); + if (Metadata.size() == 0 || (Metadata[0] == 0)) { // No metadata return true; diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index fd3121d7f..2275f6298 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -269,6 +269,9 @@ protected: /** The dimension that was last sent to a player in a Respawn or Login packet. Used to avoid Respawning into the same dimension, which confuses the client. */ eDimension m_LastSentDimension; + + /** Read a nbt data from the buffer. (It's needed because the 1.8 protocol doesn't send the nbt length) */ + AString ReadNBTDataFromBuffer(cByteBuffer & a_ByteBuffer, int a_ListTag = 0); /** Adds the received (unencrypted) data to m_ReceivedData, parses complete packets */ -- cgit v1.2.3 From 9cddffb6df595afef1584c92b6d5fc97c9eb162c Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 22 Sep 2014 21:18:13 +0200 Subject: Changed metadata reading again. --- src/Protocol/Protocol18x.cpp | 175 ++----------------------------------------- src/Protocol/Protocol18x.h | 5 +- 2 files changed, 7 insertions(+), 173 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 07e21923c..fbeb845f8 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1652,169 +1652,6 @@ void cProtocol180::FixItemFramePositions(int a_ObjectData, double & a_PosX, doub -AString cProtocol180::ReadNBTDataFromBuffer(cByteBuffer & a_ByteBuffer, int a_ListTag) -{ - cByteBuffer BufferCache(64 KiB); - AString Data; - - while (a_ByteBuffer.GetReadableSpace() != 0) - { - unsigned char TypeID; - if (a_ListTag != 0) - { - TypeID = (unsigned char)a_ListTag; - } - else - { - if (!a_ByteBuffer.ReadByte(TypeID)) - { - // Can't read the next byte - break; - } - BufferCache.WriteByte(TypeID); - } - - if ((TypeID <= eTagType::TAG_Min) || (TypeID > eTagType::TAG_Max)) - { - // Bad type id (or TAG_End) - break; - } - eTagType TagType = static_cast(TypeID); - - // Read the following string length: - if (a_ListTag == 0) - { - short StrLength = 0; - if (!a_ByteBuffer.ReadBEShort(StrLength)) - { - // Can't read string length - return Data; - } - BufferCache.WriteBEShort(StrLength); - - // Read string and write to BufferCache: - AString TagTitle; - if (!a_ByteBuffer.ReadString(TagTitle, (size_t)StrLength)) - { - // Can't read string - return Data; - } - BufferCache.WriteBuf(TagTitle.data(), TagTitle.size()); - } - - size_t TagLength = 0; - switch (TagType) - { - case eTagType::TAG_Byte: TagLength = sizeof(Byte); break; - case eTagType::TAG_Short: TagLength = sizeof(short); break; - case eTagType::TAG_Int: TagLength = sizeof(int); break; - case eTagType::TAG_Long: TagLength = sizeof(long); break; - case eTagType::TAG_Float: TagLength = sizeof(float); break; - case eTagType::TAG_Double: TagLength = sizeof(double); break; - case eTagType::TAG_End: break; - case eTagType::TAG_Compound: - { - AString CompoundData = ReadNBTDataFromBuffer(a_ByteBuffer); - Data.append(CompoundData.data(), CompoundData.size()); - break; - } - case eTagType::TAG_List: - { - Byte ListType; - int ListLength; - if (!a_ByteBuffer.ReadByte(ListType) || !a_ByteBuffer.ReadBEInt(ListLength) || (ListLength < 0)) - { - // Bad list type or list length - return Data; - } - LOGWARNING("LIST, Type: %i", (int)ListType); - - BufferCache.WriteByte(ListType); - BufferCache.WriteBEInt(ListLength); - - if ((ListType <= eTagType::TAG_Min) || (ListType > eTagType::TAG_Max)) - { - // Bad tag type - return Data; - } - - for (int i = 0; i < ListLength; i++) - { - AString EntryData = ReadNBTDataFromBuffer(a_ByteBuffer, ListType); - BufferCache.WriteBuf(EntryData.data(), EntryData.size()); - } - break; - } - case eTagType::TAG_String: - { - // Read the following string length: - short StrLength; - if (!a_ByteBuffer.ReadBEShort(StrLength)) - { - // Can't read string length - return Data; - } - BufferCache.WriteBEShort(StrLength); - TagLength += (size_t)StrLength; - break; - } - case eTagType::TAG_ByteArray: - { - int ArrayLength; - if (!a_ByteBuffer.ReadBEInt(ArrayLength) || (ArrayLength < 0) || (ArrayLength >= 16777216)) - { - // Bad array length - return Data; - } - BufferCache.WriteBEInt(ArrayLength); - TagLength += (size_t) ArrayLength; - break; - } - case eTagType::TAG_IntArray: - { - int ArrayLength; - if (!a_ByteBuffer.ReadBEInt(ArrayLength) || (ArrayLength < 0) || (ArrayLength >= 16777216)) - { - // Bad array length - return Data; - } - BufferCache.WriteBEInt(ArrayLength); - TagLength += (size_t)ArrayLength * sizeof(int); - break; - } - } - - // Copy tag bytes to the cache: - AString TagBytes; - if (!a_ByteBuffer.ReadString(TagBytes, TagLength)) - { - break; - } - BufferCache.WriteBuf(TagBytes.data(), TagBytes.size()); - - // Write cache to Data and clean: - AString Bytes; - BufferCache.ReadAll(Bytes); - BufferCache.CommitRead(); - Data.append(Bytes.data(), Bytes.size()); - } - - // Read the rest from cache - if (BufferCache.GetUsedSpace() != 0) - { - AString Bytes; - BufferCache.ReadAll(Bytes); - BufferCache.CommitRead(); - Data.append(Bytes.data(), Bytes.size()); - } - - return Data; -} - - - - - void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) { // Write the incoming data into the comm log file: @@ -2254,7 +2091,7 @@ void cProtocol180::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) } cItem Item; - ReadItem(a_ByteBuffer, Item); + ReadItem(a_ByteBuffer, Item, a_ByteBuffer.GetReadableSpace() - 3); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorX); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorY); @@ -2328,7 +2165,7 @@ void cProtocol180::HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffe { HANDLE_READ(a_ByteBuffer, ReadBEShort, short, SlotNum); cItem Item; - if (!ReadItem(a_ByteBuffer, Item)) + if (!ReadItem(a_ByteBuffer, Item, a_ByteBuffer.GetReadableSpace())) { return; } @@ -2581,7 +2418,7 @@ void cProtocol180::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEShort, short, TransactionID); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Mode); cItem Item; - ReadItem(a_ByteBuffer, Item); + ReadItem(a_ByteBuffer, Item, a_ByteBuffer.GetReadableSpace()); // Convert Button, Mode, SlotNum and HeldItem into eClickAction: eClickAction Action; @@ -2673,7 +2510,7 @@ void cProtocol180::SendData(const char * a_Data, size_t a_Size) -bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) +bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_MetadataSize) { HANDLE_PACKET_READ(a_ByteBuffer, ReadBEShort, short, ItemType); if (ItemType == -1) @@ -2693,8 +2530,8 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item) a_Item.Empty(); } - AString Metadata = ReadNBTDataFromBuffer(a_ByteBuffer); - if (Metadata.size() == 0 || (Metadata[0] == 0)) + AString Metadata; + if (!a_ByteBuffer.ReadString(Metadata, a_MetadataSize) || (Metadata.size() == 0) || (Metadata[0] == 0)) { // No metadata return true; diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 2275f6298..59a5dd0b6 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -269,9 +269,6 @@ protected: /** The dimension that was last sent to a player in a Respawn or Login packet. Used to avoid Respawning into the same dimension, which confuses the client. */ eDimension m_LastSentDimension; - - /** Read a nbt data from the buffer. (It's needed because the 1.8 protocol doesn't send the nbt length) */ - AString ReadNBTDataFromBuffer(cByteBuffer & a_ByteBuffer, int a_ListTag = 0); /** Adds the received (unencrypted) data to m_ReceivedData, parses complete packets */ @@ -325,7 +322,7 @@ protected: void SendCompass(const cWorld & a_World); /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */ - virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item); + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_MetadataSize = 1); /** Parses item metadata as read by ReadItem(), into the item enchantments. */ void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); -- cgit v1.2.3 From 10c5d5056691f0a03798c7e9439138126da30b8a Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 22 Sep 2014 18:26:35 +0200 Subject: QtBiomeVisualiser: Moved the generator setup into a side-pane. --- Tools/QtBiomeVisualiser/GeneratorSetup.cpp | 135 ++++++++++++++++++++++++++ Tools/QtBiomeVisualiser/GeneratorSetup.h | 57 +++++++++++ Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp | 125 ------------------------ Tools/QtBiomeVisualiser/GeneratorSetupDlg.h | 53 ---------- Tools/QtBiomeVisualiser/MainWindow.cpp | 69 +++++++++---- Tools/QtBiomeVisualiser/MainWindow.h | 24 ++++- Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro | 4 +- 7 files changed, 262 insertions(+), 205 deletions(-) create mode 100644 Tools/QtBiomeVisualiser/GeneratorSetup.cpp create mode 100644 Tools/QtBiomeVisualiser/GeneratorSetup.h delete mode 100644 Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp delete mode 100644 Tools/QtBiomeVisualiser/GeneratorSetupDlg.h diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp new file mode 100644 index 000000000..d512d2b90 --- /dev/null +++ b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp @@ -0,0 +1,135 @@ +#include "Globals.h" +#include "GeneratorSetup.h" +#include +#include +#include "Generating/BioGen.h" +#include "inifile/iniFile.h" + + + + + +static const QString s_GeneratorNames[] = +{ + QString("Checkerboard"), + QString("Constant"), + QString("DistortedVoronoi"), + QString("MultiStepMap"), + QString("TwoLevel"), + QString("Voronoi"), +}; + + + + + +GeneratorSetup::GeneratorSetup(const AString & a_IniFileName, QWidget * a_Parent) : + super(a_Parent), + m_IniFile(new cIniFile()) +{ + // The generator name is in a separate form layout at the top, always present: + m_cbGenerator = new QComboBox(); + m_cbGenerator->setMinimumWidth(120); + for (size_t i = 0; i < ARRAYCOUNT(s_GeneratorNames); i++) + { + m_cbGenerator->addItem(s_GeneratorNames[i]); + } + QFormLayout * nameLayout = new QFormLayout(); + nameLayout->addRow(new QLabel(tr("Generator")), m_cbGenerator); + + // The rest of the controls are in a dynamically created form layout: + m_FormLayout = new QFormLayout(); + + // The main layout joins these two vertically: + m_MainLayout = new QVBoxLayout(); + m_MainLayout->addLayout(nameLayout); + m_MainLayout->addLayout(m_FormLayout); + m_MainLayout->addStretch(); + setLayout(m_MainLayout); + + // Load the INI file, if specified, otherwise set defaults: + if (!a_IniFileName.empty() && m_IniFile->ReadFile(a_IniFileName)) + { + m_cbGenerator->setCurrentText(QString::fromStdString(m_IniFile->GetValue("Generator", "BiomeGen"))); + } + else + { + m_IniFile->SetValue("Generator", "Generator", "Composable"); + m_IniFile->SetValue("Generator", "BiomeGen", m_cbGenerator->currentText().toStdString()); + bool dummy; + delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); + } + updateFromIni(); + + // Connect the combo change even only after the data has been loaded: + connect(m_cbGenerator, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(generatorChanged(QString))); +} + + + + + +void GeneratorSetup::generatorChanged(const QString & a_NewName) +{ + // Clear the current contents of the form layout by assigning it to a stack temporary: + { + m_MainLayout->takeAt(1); + QWidget().setLayout(m_FormLayout); + } + + // Re-create the layout: + m_FormLayout = new QFormLayout(); + m_MainLayout->insertLayout(1, m_FormLayout); + + // Recreate the INI file: + m_IniFile->Clear(); + m_IniFile->SetValue("Generator", "Generator", "Composable"); + m_IniFile->SetValue("Generator", "BiomeGen", a_NewName.toStdString()); + + // Create a dummy biome gen from the INI file, this will create the defaults in the INI file: + bool dummy; + delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); + + // Read all values from the INI file and put them into the form layout: + updateFromIni(); +} + + + + + +void GeneratorSetup::updateFromIni() +{ + int keyID = m_IniFile->FindKey("Generator"); + if (keyID <= -1) + { + return; + } + int numItems = m_IniFile->GetNumValues(keyID); + AString generatorName = m_IniFile->GetValue("Generator", "BiomeGen"); + size_t generatorNameLen = generatorName.length(); + for (int i = 0; i < numItems; i++) + { + AString itemName = m_IniFile->GetValueName(keyID, i); + AString itemValue = m_IniFile->GetValue(keyID, i); + if ((itemName == "Generator") || (itemName == "BiomeGen")) + { + // These special cases are not to be added + continue; + } + + // Remove the generator name prefix from the item name, for clarity purposes: + if (NoCaseCompare(itemName.substr(0, generatorNameLen), generatorName) == 0) + { + itemName.erase(0, generatorNameLen); + } + + QLineEdit * edit = new QLineEdit(); + edit->setText(QString::fromStdString(itemValue)); + m_FormLayout->addRow(new QLabel(QString::fromStdString(itemName)), edit); + } // for i - INI values[] +} + + + + diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.h b/Tools/QtBiomeVisualiser/GeneratorSetup.h new file mode 100644 index 000000000..0594e1998 --- /dev/null +++ b/Tools/QtBiomeVisualiser/GeneratorSetup.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include +#include +#include + + + + + +class cIniFile; +typedef std::shared_ptr cIniFilePtr; + + + + + +class GeneratorSetup : + public QWidget +{ + typedef QWidget super; + + Q_OBJECT + +public: + /** Creates the widget and loads the contents of the INI file, if not empty. */ + explicit GeneratorSetup(const std::string & a_IniFileName, QWidget * parent = nullptr); + + /** Returns the cIniFile instance that is being edited by this widget. */ + cIniFilePtr getIniFile() { return m_IniFile; } + +signals: + +public slots: + /** Called when the user selects a different generator from the top combobox. + Re-creates m_IniFile and updates the form layout. */ + void generatorChanged(const QString & a_NewName); + +protected: + QComboBox * m_cbGenerator; + QVBoxLayout * m_MainLayout; + QFormLayout * m_FormLayout; + + cIniFilePtr m_IniFile; + + int m_Seed; + + + /** Updates the form layout with the values from m_IniFile. */ + void updateFromIni(); +}; + + + + diff --git a/Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp b/Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp deleted file mode 100644 index e6037fa9b..000000000 --- a/Tools/QtBiomeVisualiser/GeneratorSetupDlg.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "Globals.h" -#include "GeneratorSetupDlg.h" -#include -#include -#include "Generating/BioGen.h" -#include "inifile/iniFile.h" - - - - - -static const QString s_GeneratorNames[] = -{ - QString("Checkerboard"), - QString("Constant"), - QString("DistortedVoronoi"), - QString("MultiStepMap"), - QString("TwoLevel"), - QString("Voronoi"), -}; - - - - - -GeneratorSetupDlg::GeneratorSetupDlg(const AString & a_IniFileName, QWidget * a_Parent) : - super(a_Parent), - m_IniFile(new cIniFile()) -{ - // The generator name is in a separate form layout at the top, always present: - m_cbGenerator = new QComboBox(); - m_cbGenerator->setMinimumWidth(300); - for (size_t i = 0; i < ARRAYCOUNT(s_GeneratorNames); i++) - { - m_cbGenerator->addItem(s_GeneratorNames[i]); - } - QFormLayout * nameLayout = new QFormLayout(); - nameLayout->addRow(new QLabel(tr("Generator")), m_cbGenerator); - - // The rest of the controls are in a dynamically created form layout: - m_FormLayout = new QFormLayout(); - - // The main layout joins these two vertically: - m_MainLayout = new QVBoxLayout(); - m_MainLayout->addLayout(nameLayout); - m_MainLayout->addLayout(m_FormLayout); - setLayout(m_MainLayout); - - // Load the INI file, if specified, otherwise set defaults: - if (!a_IniFileName.empty() && m_IniFile->ReadFile(a_IniFileName)) - { - m_cbGenerator->setCurrentText(QString::fromStdString(m_IniFile->GetValue("Generator", "BiomeGen"))); - } - else - { - m_IniFile->SetValue("Generator", "Generator", "Composable"); - m_IniFile->SetValue("Generator", "BiomeGen", m_cbGenerator->currentText().toStdString()); - bool dummy; - delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); - } - updateFromIni(); - - // Connect the combo change even only after the data has been loaded: - connect(m_cbGenerator, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(generatorChanged(QString))); -} - - - - - -void GeneratorSetupDlg::generatorChanged(const QString & a_NewName) -{ - // Clear the current contents of the form layout by assigning it to a stack temporary: - { - m_MainLayout->takeAt(1); - QWidget().setLayout(m_FormLayout); - } - - // Re-create the layout: - m_FormLayout = new QFormLayout(); - m_MainLayout->addLayout(m_FormLayout); - - // Recreate the INI file: - m_IniFile->Clear(); - m_IniFile->SetValue("Generator", "Generator", "Composable"); - m_IniFile->SetValue("Generator", "BiomeGen", a_NewName.toStdString()); - - // Create a dummy biome gen from the INI file, this will create the defaults in the INI file: - bool dummy; - delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); - - // Read all values from the INI file and put them into the form layout: - updateFromIni(); -} - - - - - -void GeneratorSetupDlg::updateFromIni() -{ - int keyID = m_IniFile->FindKey("Generator"); - if (keyID <= -1) - { - return; - } - int numItems = m_IniFile->GetNumValues(keyID); - for (int i = 0; i < numItems; i++) - { - AString itemName = m_IniFile->GetValueName(keyID, i); - AString itemValue = m_IniFile->GetValue(keyID, i); - if ((itemName == "Generator") || (itemName == "BiomeGen")) - { - // These special cases are not to be added - continue; - } - QLineEdit * edit = new QLineEdit(); - edit->setText(QString::fromStdString(itemValue)); - m_FormLayout->addRow(new QLabel(QString::fromStdString(itemName)), edit); - } // for i - INI values[] -} - - - - diff --git a/Tools/QtBiomeVisualiser/GeneratorSetupDlg.h b/Tools/QtBiomeVisualiser/GeneratorSetupDlg.h deleted file mode 100644 index d7070e331..000000000 --- a/Tools/QtBiomeVisualiser/GeneratorSetupDlg.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - - - - - -class cIniFile; - - - - - -class GeneratorSetupDlg : - public QDialog -{ - typedef QDialog super; - - Q_OBJECT - -public: - /** Creates the dialog and loads the contents of the INI file, if not empty. */ - explicit GeneratorSetupDlg(const std::string & a_IniFileName, QWidget * parent = nullptr); - -signals: - -public slots: - /** Called when the user selects a different generator from the top combobox. - Re-creates m_IniFile and updates the form layout. */ - void generatorChanged(const QString & a_NewName); - -protected: - QComboBox * m_cbGenerator; - QVBoxLayout * m_MainLayout; - QFormLayout * m_FormLayout; - - std::unique_ptr m_IniFile; - - int m_Seed; - - - /** Updates the form layout with the values from m_IniFile. */ - void updateFromIni(); -}; - - - - diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index d2c1ae2c1..f9915901d 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -12,19 +12,27 @@ #include "Generating/BioGen.h" #include "StringCompression.h" #include "WorldStorage/FastNBT.h" -#include "GeneratorSetupDlg.h" +#include "GeneratorSetup.h" MainWindow::MainWindow(QWidget * parent) : - QMainWindow(parent) + QMainWindow(parent), + m_GeneratorSetup(nullptr), + m_LineSeparator(nullptr) { initMinecraftPath(); - m_BiomeView = new BiomeView(this); - setCentralWidget(m_BiomeView); + m_BiomeView = new BiomeView(); + m_MainLayout = new QHBoxLayout(); + m_MainLayout->addWidget(m_BiomeView); + m_MainLayout->setMenuBar(menuBar()); + m_MainLayout->setMargin(0); + QWidget * central = new QWidget(); + central->setLayout(m_MainLayout); + setCentralWidget(central); createActions(); createMenus(); @@ -48,9 +56,7 @@ void MainWindow::newGenerator() // TODO // (Re-)open the generator setup dialog: - m_GeneratorSetupDlg.reset(new GeneratorSetupDlg("")); - m_GeneratorSetupDlg->show(); - m_GeneratorSetupDlg->raise(); + openGeneratorSetup(""); // TODO } @@ -69,9 +75,7 @@ void MainWindow::openGenerator() } // (Re-)open the generator setup dialog: - m_GeneratorSetupDlg.reset(new GeneratorSetupDlg(worldIni.toStdString())); - m_GeneratorSetupDlg->show(); - m_GeneratorSetupDlg->raise(); + openGeneratorSetup(worldIni.toStdString()); // Set the chunk source: m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(worldIni))); @@ -92,11 +96,7 @@ void MainWindow::openWorld() } // Remove the generator setup dialog, if open: - if (m_GeneratorSetupDlg.get() != nullptr) - { - m_GeneratorSetupDlg->hide(); - m_GeneratorSetupDlg.reset(nullptr); - } + closeGeneratorSetup(); // Set the chunk source: m_BiomeView->setChunkSource(std::shared_ptr(new AnvilSource(regionFolder))); @@ -117,11 +117,7 @@ void MainWindow::openVanillaWorld() } // Remove the generator setup dialog, if open: - if (m_GeneratorSetupDlg.get() != nullptr) - { - m_GeneratorSetupDlg->hide(); - m_GeneratorSetupDlg.reset(nullptr); - } + closeGeneratorSetup(); // Set the chunk source: m_BiomeView->setChunkSource(std::shared_ptr(new AnvilSource(action->data().toString()))); @@ -276,3 +272,36 @@ QString MainWindow::getWorldName(const AString & a_Path) + +void MainWindow::openGeneratorSetup(const AString & a_IniFileName) +{ + // Close any previous editor: + closeGeneratorSetup(); + + // Open up a new editor: + m_GeneratorSetup = new GeneratorSetup(a_IniFileName); + m_LineSeparator = new QWidget(); + m_LineSeparator->setFixedWidth(2); + m_LineSeparator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + m_LineSeparator->setStyleSheet(QString("background-color: #c0c0c0;")); + m_MainLayout->addWidget(m_LineSeparator); + m_MainLayout->addWidget(m_GeneratorSetup); +} + + + + + +void MainWindow::closeGeneratorSetup() +{ + delete m_MainLayout->takeAt(2); + delete m_MainLayout->takeAt(1); + delete m_GeneratorSetup; + delete m_LineSeparator; + m_GeneratorSetup = nullptr; + m_LineSeparator = nullptr; +} + + + + diff --git a/Tools/QtBiomeVisualiser/MainWindow.h b/Tools/QtBiomeVisualiser/MainWindow.h index 840e01b0f..6490a937f 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.h +++ b/Tools/QtBiomeVisualiser/MainWindow.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "BiomeView.h" @@ -10,7 +11,7 @@ // fwd: -class GeneratorSetupDlg; +class GeneratorSetup; @@ -21,8 +22,6 @@ class MainWindow : { Q_OBJECT - BiomeView * m_BiomeView; - public: MainWindow(QWidget * parent = nullptr); ~MainWindow(); @@ -54,8 +53,17 @@ protected: /** Path to the vanilla folder. */ QString m_MinecraftPath; - /** The dialog for setting up the generator. */ - std::unique_ptr m_GeneratorSetupDlg; + /** The pane for setting up the generator, available when visualising a generator. */ + GeneratorSetup * m_GeneratorSetup; + + /** The main biome display widget. */ + BiomeView * m_BiomeView; + + /** The layout for the window. */ + QHBoxLayout * m_MainLayout; + + /** The separator line between biome view and generator setup. */ + QWidget * m_LineSeparator; /** Initializes the m_MinecraftPath based on the proper MC path */ @@ -73,6 +81,12 @@ protected: /** Returns the name of the vanilla world in the specified path. Reads the level.dat file for the name. Returns an empty string on failure. */ QString getWorldName(const AString & a_Path); + + /** Opens the generator setup pane, if not already open, and loads the specified INI file to it. */ + void openGeneratorSetup(const AString & a_IniFileName); + + /** Closes and destroys the generator setup pane, if there is one. */ + void closeGeneratorSetup(); }; diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro index 7171562bb..2ed1be719 100644 --- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro @@ -47,7 +47,7 @@ SOURCES += main.cpp\ ../../lib/zlib/trees.c \ ../../lib/zlib/uncompr.c \ ../../lib/zlib/zutil.c \ - GeneratorSetupDlg.cpp + GeneratorSetup.cpp HEADERS += MainWindow.h \ Globals.h \ @@ -80,7 +80,7 @@ HEADERS += MainWindow.h \ ../../lib/zlib/zconf.h \ ../../lib/zlib/zlib.h \ ../../lib/zlib/zutil.h \ - GeneratorSetupDlg.h + GeneratorSetup.h INCLUDEPATH += $$_PRO_FILE_PWD_ \ $$_PRO_FILE_PWD_/../../src \ -- cgit v1.2.3 From 583532e1b927e1b9af9782e35c7f2d089e997254 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 22 Sep 2014 18:33:18 +0200 Subject: QtBiomeVisualiser: generator source is read from generator setup ini. --- Tools/QtBiomeVisualiser/ChunkSource.cpp | 12 ++++-------- Tools/QtBiomeVisualiser/ChunkSource.h | 7 ++++--- Tools/QtBiomeVisualiser/MainWindow.cpp | 10 +++++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp index 54da2afe5..d8cecbaa4 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.cpp +++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp @@ -142,8 +142,8 @@ static void biomesToImage(cChunkDef::BiomeMap & a_Biomes, Chunk::Image & a_Image //////////////////////////////////////////////////////////////////////////////// // BioGenSource: -BioGenSource::BioGenSource(QString a_WorldIniPath) : - m_WorldIniPath(a_WorldIniPath), +BioGenSource::BioGenSource(cIniFilePtr a_IniFile) : + m_IniFile(a_IniFile), m_Mtx(QMutex::Recursive) { reload(); @@ -171,14 +171,10 @@ void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChu void BioGenSource::reload() { - cIniFile ini; - ini.ReadFile(m_WorldIniPath.toStdString()); - int seed = ini.GetValueSetI("Seed", "Seed", 0); + int seed = m_IniFile->GetValueSetI("Seed", "Seed", 0); bool unused = false; QMutexLocker lock(&m_Mtx); - m_BiomeGen.reset(cBiomeGen::CreateBiomeGen(ini, seed, unused)); - lock.unlock(); - ini.WriteFile(m_WorldIniPath.toStdString()); + m_BiomeGen.reset(cBiomeGen::CreateBiomeGen(*m_IniFile, seed, unused)); } diff --git a/Tools/QtBiomeVisualiser/ChunkSource.h b/Tools/QtBiomeVisualiser/ChunkSource.h index a5612da01..05e8ac5de 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.h +++ b/Tools/QtBiomeVisualiser/ChunkSource.h @@ -12,6 +12,7 @@ class cBiomeGen; typedef std::shared_ptr cBiomeGenPtr; class cIniFile; +typedef std::shared_ptr cIniFilePtr; @@ -41,15 +42,15 @@ class BioGenSource : { public: /** Constructs a new BioGenSource based on the biome generator that is defined in the specified world.ini file. */ - BioGenSource(QString a_WorldIniPath); + BioGenSource(cIniFilePtr a_IniFile); // ChunkSource overrides: virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override; virtual void reload(void) override; protected: - /** Path to the world.ini file from which the m_WorldIni is regenerated on reload requests. */ - QString m_WorldIniPath; + /** The world.ini contents from which the generator is created and re-created on reload(). */ + cIniFilePtr m_IniFile; /** The generator used for generating biomes. */ std::unique_ptr m_BiomeGen; diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index f9915901d..c55d85082 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -53,12 +53,12 @@ MainWindow::~MainWindow() void MainWindow::newGenerator() { - // TODO - - // (Re-)open the generator setup dialog: + // (Re-)open the generator setup dialog with empty settings: openGeneratorSetup(""); - // TODO + // Set the chunk source: + m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(m_GeneratorSetup->getIniFile()))); + m_BiomeView->redraw(); } @@ -78,7 +78,7 @@ void MainWindow::openGenerator() openGeneratorSetup(worldIni.toStdString()); // Set the chunk source: - m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(worldIni))); + m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(m_GeneratorSetup->getIniFile()))); m_BiomeView->redraw(); } -- cgit v1.2.3 From 83588fb0aad5c8597df783792c946c27327f1a40 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 22 Sep 2014 21:51:59 +0200 Subject: QtBiomeVisualiser: Implemented live-update for the generator setup. --- Tools/QtBiomeVisualiser/ChunkSource.cpp | 2 +- Tools/QtBiomeVisualiser/GeneratorSetup.cpp | 44 +++++++++++++++++++++------ Tools/QtBiomeVisualiser/GeneratorSetup.h | 7 +++++ Tools/QtBiomeVisualiser/MainWindow.cpp | 9 ++++-- Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro | 4 +-- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp index d8cecbaa4..f7174b624 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.cpp +++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp @@ -171,7 +171,7 @@ void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChu void BioGenSource::reload() { - int seed = m_IniFile->GetValueSetI("Seed", "Seed", 0); + int seed = m_IniFile->GetValueSetI("Generator", "Seed", 0); bool unused = false; QMutexLocker lock(&m_Mtx); m_BiomeGen.reset(cBiomeGen::CreateBiomeGen(*m_IniFile, seed, unused)); diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp index d512d2b90..239965409 100644 --- a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp +++ b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp @@ -27,22 +27,27 @@ GeneratorSetup::GeneratorSetup(const AString & a_IniFileName, QWidget * a_Parent super(a_Parent), m_IniFile(new cIniFile()) { - // The generator name is in a separate form layout at the top, always present: + // The seed and generator name is in a separate form layout at the top, always present: + m_eSeed = new QLineEdit(); + m_eSeed->setValidator(new QIntValidator()); + m_eSeed->setText("0"); + m_eSeed->setProperty("INI.ItemName", QVariant("Seed")); m_cbGenerator = new QComboBox(); m_cbGenerator->setMinimumWidth(120); for (size_t i = 0; i < ARRAYCOUNT(s_GeneratorNames); i++) { m_cbGenerator->addItem(s_GeneratorNames[i]); } - QFormLayout * nameLayout = new QFormLayout(); - nameLayout->addRow(new QLabel(tr("Generator")), m_cbGenerator); + QFormLayout * baseLayout = new QFormLayout(); + baseLayout->addRow(new QLabel(tr("Seed")), m_eSeed); + baseLayout->addRow(new QLabel(tr("Generator")), m_cbGenerator); // The rest of the controls are in a dynamically created form layout: m_FormLayout = new QFormLayout(); // The main layout joins these two vertically: m_MainLayout = new QVBoxLayout(); - m_MainLayout->addLayout(nameLayout); + m_MainLayout->addLayout(baseLayout); m_MainLayout->addLayout(m_FormLayout); m_MainLayout->addStretch(); setLayout(m_MainLayout); @@ -51,18 +56,20 @@ GeneratorSetup::GeneratorSetup(const AString & a_IniFileName, QWidget * a_Parent if (!a_IniFileName.empty() && m_IniFile->ReadFile(a_IniFileName)) { m_cbGenerator->setCurrentText(QString::fromStdString(m_IniFile->GetValue("Generator", "BiomeGen"))); + m_eSeed->setText(QString::number(m_IniFile->GetValueI("Generator", "Seed"))); } else { m_IniFile->SetValue("Generator", "Generator", "Composable"); m_IniFile->SetValue("Generator", "BiomeGen", m_cbGenerator->currentText().toStdString()); bool dummy; - delete cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); + delete cBiomeGen::CreateBiomeGen(*m_IniFile, 0, dummy); } updateFromIni(); - // Connect the combo change even only after the data has been loaded: - connect(m_cbGenerator, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(generatorChanged(QString))); + // Connect the change events only after the data has been loaded: + connect(m_cbGenerator, SIGNAL(currentIndexChanged(QString)), this, SLOT(generatorChanged(QString))); + connect(m_eSeed, SIGNAL(textChanged(QString)), this, SLOT(editChanged(QString))); } @@ -92,6 +99,20 @@ void GeneratorSetup::generatorChanged(const QString & a_NewName) // Read all values from the INI file and put them into the form layout: updateFromIni(); + + // Notify of the changes: + emit generatorUpdated(); +} + + + + + +void GeneratorSetup::editChanged(const QString & a_NewValue) +{ + QString itemName = sender()->property("INI.ItemName").toString(); + m_IniFile->SetValue("Generator", itemName.toStdString(), a_NewValue.toStdString()); + emit generatorUpdated(); } @@ -111,12 +132,16 @@ void GeneratorSetup::updateFromIni() for (int i = 0; i < numItems; i++) { AString itemName = m_IniFile->GetValueName(keyID, i); - AString itemValue = m_IniFile->GetValue(keyID, i); if ((itemName == "Generator") || (itemName == "BiomeGen")) { // These special cases are not to be added continue; } + AString itemValue = m_IniFile->GetValue(keyID, i); + + QLineEdit * edit = new QLineEdit(); + edit->setText(QString::fromStdString(itemValue)); + edit->setProperty("INI.ItemName", QVariant(QString::fromStdString(itemName))); // Remove the generator name prefix from the item name, for clarity purposes: if (NoCaseCompare(itemName.substr(0, generatorNameLen), generatorName) == 0) @@ -124,8 +149,7 @@ void GeneratorSetup::updateFromIni() itemName.erase(0, generatorNameLen); } - QLineEdit * edit = new QLineEdit(); - edit->setText(QString::fromStdString(itemValue)); + connect(edit, SIGNAL(textChanged(QString)), this, SLOT(editChanged(QString))); m_FormLayout->addRow(new QLabel(QString::fromStdString(itemName)), edit); } // for i - INI values[] } diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.h b/Tools/QtBiomeVisualiser/GeneratorSetup.h index 0594e1998..e72d3abbc 100644 --- a/Tools/QtBiomeVisualiser/GeneratorSetup.h +++ b/Tools/QtBiomeVisualiser/GeneratorSetup.h @@ -32,14 +32,21 @@ public: cIniFilePtr getIniFile() { return m_IniFile; } signals: + /** Emitted when the generator parameters have changed. */ + void generatorUpdated(); public slots: /** Called when the user selects a different generator from the top combobox. Re-creates m_IniFile and updates the form layout. */ void generatorChanged(const QString & a_NewName); +protected slots: + /** Called when any of the edit widgets are changed. */ + void editChanged(const QString & a_NewValue); + protected: QComboBox * m_cbGenerator; + QLineEdit * m_eSeed; QVBoxLayout * m_MainLayout; QFormLayout * m_FormLayout; diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index c55d85082..a2cfa7794 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -27,7 +27,7 @@ MainWindow::MainWindow(QWidget * parent) : m_BiomeView = new BiomeView(); m_MainLayout = new QHBoxLayout(); - m_MainLayout->addWidget(m_BiomeView); + m_MainLayout->addWidget(m_BiomeView, 1); m_MainLayout->setMenuBar(menuBar()); m_MainLayout->setMargin(0); QWidget * central = new QWidget(); @@ -57,7 +57,8 @@ void MainWindow::newGenerator() openGeneratorSetup(""); // Set the chunk source: - m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(m_GeneratorSetup->getIniFile()))); + cIniFilePtr iniFile = m_GeneratorSetup->getIniFile(); + m_BiomeView->setChunkSource(std::shared_ptr(new BioGenSource(iniFile))); m_BiomeView->redraw(); } @@ -260,7 +261,6 @@ QString MainWindow::getWorldName(const AString & a_Path) return QString(); } AString name = nbt.GetName(1); - OutputDebugStringA(name.c_str()); int levelNameTag = nbt.FindTagByPath(nbt.GetRoot(), "Data\\LevelName"); if ((levelNameTag <= 0) || (nbt.GetType(levelNameTag) != TAG_String)) { @@ -286,6 +286,9 @@ void MainWindow::openGeneratorSetup(const AString & a_IniFileName) m_LineSeparator->setStyleSheet(QString("background-color: #c0c0c0;")); m_MainLayout->addWidget(m_LineSeparator); m_MainLayout->addWidget(m_GeneratorSetup); + + // Connect the signals from the setup pane: + connect(m_GeneratorSetup, SIGNAL(generatorUpdated()), m_BiomeView, SLOT(reload())); } diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro index 2ed1be719..4275f73eb 100644 --- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro @@ -89,8 +89,6 @@ INCLUDEPATH += $$_PRO_FILE_PWD_ \ CONFIG += C++11 -OTHER_FILES += \ - ../../lib/zlib/example.c.txt \ - ../../lib/zlib/minigzip.c.txt +OTHER_FILES += -- cgit v1.2.3 From fc11818f4c9eaeb9eb1acab4fcc3c6776e6c2d00 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 22 Sep 2014 22:06:08 +0200 Subject: Hotfixed 1.8 item reading. --- src/Protocol/Protocol18x.cpp | 10 +++++----- src/Protocol/Protocol18x.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index fbeb845f8..a7ab3abb1 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -2091,7 +2091,7 @@ void cProtocol180::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) } cItem Item; - ReadItem(a_ByteBuffer, Item, a_ByteBuffer.GetReadableSpace() - 3); + ReadItem(a_ByteBuffer, Item, 3); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorX); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, CursorY); @@ -2165,7 +2165,7 @@ void cProtocol180::HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffe { HANDLE_READ(a_ByteBuffer, ReadBEShort, short, SlotNum); cItem Item; - if (!ReadItem(a_ByteBuffer, Item, a_ByteBuffer.GetReadableSpace())) + if (!ReadItem(a_ByteBuffer, Item)) { return; } @@ -2418,7 +2418,7 @@ void cProtocol180::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadBEShort, short, TransactionID); HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Mode); cItem Item; - ReadItem(a_ByteBuffer, Item, a_ByteBuffer.GetReadableSpace()); + ReadItem(a_ByteBuffer, Item); // Convert Button, Mode, SlotNum and HeldItem into eClickAction: eClickAction Action; @@ -2510,7 +2510,7 @@ void cProtocol180::SendData(const char * a_Data, size_t a_Size) -bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_MetadataSize) +bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_RemainingBytes) { HANDLE_PACKET_READ(a_ByteBuffer, ReadBEShort, short, ItemType); if (ItemType == -1) @@ -2531,7 +2531,7 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a } AString Metadata; - if (!a_ByteBuffer.ReadString(Metadata, a_MetadataSize) || (Metadata.size() == 0) || (Metadata[0] == 0)) + if (!a_ByteBuffer.ReadString(Metadata, a_ByteBuffer.GetReadableSpace() - a_RemainingBytes) || (Metadata.size() == 0) || (Metadata[0] == 0)) { // No metadata return true; diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index 59a5dd0b6..eb0253663 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -322,7 +322,7 @@ protected: void SendCompass(const cWorld & a_World); /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */ - virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_MetadataSize = 1); + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_RemainingBytes = 0); /** Parses item metadata as read by ReadItem(), into the item enchantments. */ void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); -- cgit v1.2.3 From 1aa64f32e1bea1620b721d9bd86e9fc315738ea3 Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 22 Sep 2014 22:07:58 +0200 Subject: Updated README.md --- README.md | 2 +- src/Protocol/ProtocolRecognizer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 27166413e..b42467039 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ MCServer is a Minecraft server that is written in C++ and designed to be efficie MCServer can run on PCs, Macs, and *nix. This includes android phones and tablets as well as Raspberry Pis. -We currently support the protocol from Minecraft 1.2 all the way up to Minecraft 1.7.10. +We currently support the protocol from Minecraft 1.2 all the way up to Minecraft 1.8. Installation ------------ diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 3177f06ae..55348a758 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -18,7 +18,7 @@ // Adjust these if a new protocol is added or an old one is removed: -#define MCS_CLIENT_VERSIONS "1.2.4, 1.2.5, 1.3.1, 1.3.2, 1.4.2, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.5, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.7.2, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.7.10" +#define MCS_CLIENT_VERSIONS "1.2.4, 1.2.5, 1.3.1, 1.3.2, 1.4.2, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.5, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.7.2, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.7.10, 1.8" #define MCS_PROTOCOL_VERSIONS "29, 39, 47, 49, 51, 60, 61, 73, 74, 77, 78, 4, 5" -- cgit v1.2.3 From 806871b86f2f04545f20caa6a8c30db2ccb7bc12 Mon Sep 17 00:00:00 2001 From: Chris Darnell Date: Mon, 22 Sep 2014 18:23:56 -0400 Subject: A few compiler warning fixes --- src/BlockEntities/RedstonePoweredEntity.h | 2 +- src/Entities/Entity.cpp | 5 +- src/Entities/EntityEffect.cpp | 1 + src/Entities/Minecart.cpp | 81 ++++++++++++++++--------------- src/Tracer.cpp | 2 +- 5 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/BlockEntities/RedstonePoweredEntity.h b/src/BlockEntities/RedstonePoweredEntity.h index f11df4fc4..eac4e35d4 100644 --- a/src/BlockEntities/RedstonePoweredEntity.h +++ b/src/BlockEntities/RedstonePoweredEntity.h @@ -6,7 +6,7 @@ class cRedstonePoweredEntity { public: - virtual ~cRedstonePoweredEntity() {}; + virtual ~cRedstonePoweredEntity() {} /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate virtual void SetRedstonePower(bool a_IsPowered) = 0; diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index c8ebc4314..8ef24828e 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -342,6 +342,7 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) a_TDI.FinalDamage += (int)ceil(2.5 * SmiteLevel); break; } + default: break; } } } @@ -1015,7 +1016,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) if (Tracer.HitNormal.y != 0.f) NextSpeed.y = 0.f; if (Tracer.HitNormal.z != 0.f) NextSpeed.z = 0.f; - if (Tracer.HitNormal.y == 1) // Hit BLOCK_FACE_YP, we are on the ground + if (Tracer.HitNormal.y == 1.f) // Hit BLOCK_FACE_YP, we are on the ground { m_bOnGround = true; } @@ -1960,7 +1961,7 @@ void cEntity::SteerVehicle(float a_Forward, float a_Sideways) { return; } - if ((a_Forward != 0) || (a_Sideways != 0)) + if ((a_Forward != 0.f) || (a_Sideways != 0.f)) { m_AttachedTo->HandleSpeedFromAttachee(a_Forward, a_Sideways); } diff --git a/src/Entities/EntityEffect.cpp b/src/Entities/EntityEffect.cpp index 1a923930f..98c5d23b4 100644 --- a/src/Entities/EntityEffect.cpp +++ b/src/Entities/EntityEffect.cpp @@ -96,6 +96,7 @@ int cEntityEffect::GetPotionEffectDuration(short a_ItemDamage) base = 1800; break; } + default: break; } // If potion is level II, half the duration. If not, stays the same diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index bc9e21d8e..5833cb4ae 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -13,6 +13,7 @@ #include "Player.h" #include "../BoundingBox.h" +#define NO_SPEED 0.0 #define MAX_SPEED 8 #define MAX_SPEED_NEGATIVE -MAX_SPEED @@ -220,7 +221,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedZ() != 0) // Don't do anything if cart is stationary + if (GetSpeedZ() != NO_SPEED) // Don't do anything if cart is stationary { if (GetSpeedZ() > 0) { @@ -239,13 +240,13 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { SetYaw(180); SetPosY(floor(GetPosY()) + 0.55); - SetSpeedY(0); - SetSpeedZ(0); + SetSpeedY(NO_SPEED); + SetSpeedZ(NO_SPEED); bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedX() != 0) + if (GetSpeedX() != NO_SPEED) { if (GetSpeedX() > 0) { @@ -305,9 +306,9 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) case E_META_RAIL_ASCEND_XM: // ASCEND EAST { SetYaw(180); - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); - if (GetSpeedX() >= 0) + if (GetSpeedX() >= NO_SPEED) { if (GetSpeedX() <= MAX_SPEED) { @@ -424,9 +425,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedZ() != 0) + if (GetSpeedZ() != NO_SPEED) { - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { AddSpeedZ(AccelDecelSpeed); } @@ -441,15 +442,15 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) { SetYaw(180); SetPosY(floor(GetPosY()) + 0.55); - SetSpeedY(0); - SetSpeedZ(0); + SetSpeedY(NO_SPEED); + SetSpeedZ(NO_SPEED); bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedX() != 0) + if (GetSpeedX() != NO_SPEED) { - if (GetSpeedX() > 0) + if (GetSpeedX() > NO_SPEED) { AddSpeedX(AccelDecelSpeed); } @@ -463,9 +464,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_XM: // ASCEND EAST { SetYaw(180); - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); - if (GetSpeedX() >= 0) + if (GetSpeedX() >= NO_SPEED) { if (GetSpeedX() <= MAX_SPEED) { @@ -483,9 +484,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_XP: // ASCEND WEST { SetYaw(180); - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); - if (GetSpeedX() > 0) + if (GetSpeedX() > NO_SPEED) { AddSpeedX(AccelDecelSpeed); SetSpeedY(GetSpeedX()); @@ -503,9 +504,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH { SetYaw(270); - SetSpeedX(0); + SetSpeedX(NO_SPEED); - if (GetSpeedZ() >= 0) + if (GetSpeedZ() >= NO_SPEED) { if (GetSpeedZ() <= MAX_SPEED) { @@ -523,9 +524,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH { SetYaw(270); - SetSpeedX(0); + SetSpeedX(NO_SPEED); - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { AddSpeedZ(AccelDecelSpeed); SetSpeedY(GetSpeedZ()); @@ -576,7 +577,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_XP: case E_META_RAIL_XM_XP: { - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); break; } @@ -584,7 +585,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_ZP: case E_META_RAIL_ZM_ZP: { - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); break; } @@ -593,12 +594,12 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) { if (GetPosZ() > floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { SetSpeedX(-GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() > floor(GetPosX()) + 0.5) @@ -608,82 +609,82 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedZ(-GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } - SetSpeedY(0); + SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZM_XP: { if (GetPosZ() > floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { SetSpeedX(GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() < floor(GetPosX()) + 0.5) { - if (GetSpeedX() < 0) + if (GetSpeedX() < NO_SPEED) { SetSpeedZ(GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } - SetSpeedY(0); + SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZP_XM: { if (GetPosZ() < floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() < 0) + if (GetSpeedZ() < NO_SPEED) { SetSpeedX(GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() > floor(GetPosX()) + 0.5) { - if (GetSpeedX() > 0) + if (GetSpeedX() > NO_SPEED) { SetSpeedZ(GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } - SetSpeedY(0); + SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZP_XP: { if (GetPosZ() < floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() < 0) + if (GetSpeedZ() < NO_SPEED) { SetSpeedX(-GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() < floor(GetPosX()) + 0.5) { - if (GetSpeedX() < 0) + if (GetSpeedX() < NO_SPEED) { SetSpeedZ(-GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } SetSpeedY(0); diff --git a/src/Tracer.cpp b/src/Tracer.cpp index 8ccd18071..e125c6aa4 100644 --- a/src/Tracer.cpp +++ b/src/Tracer.cpp @@ -283,7 +283,7 @@ int cTracer::intersect3D_SegmentPlane( const Vector3f & a_Origin, const Vector3f if (fabs(D) < EPSILON) { // segment is parallel to plane - if (N == 0) + if (N == 0.0) { // segment lies in plane return 2; -- cgit v1.2.3 From 5f6bac20915fda0d0a92c805f6dfbf562bb4beee Mon Sep 17 00:00:00 2001 From: archshift Date: Tue, 23 Sep 2014 00:12:28 -0700 Subject: Made ExpBottleEntity break on entities. Fixes #1369 --- src/Entities/ExpBottleEntity.cpp | 19 ++++++++++++++++++- src/Entities/ExpBottleEntity.h | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Entities/ExpBottleEntity.cpp b/src/Entities/ExpBottleEntity.cpp index 202dde942..ee142a5a2 100644 --- a/src/Entities/ExpBottleEntity.cpp +++ b/src/Entities/ExpBottleEntity.cpp @@ -18,10 +18,27 @@ cExpBottleEntity::cExpBottleEntity(cEntity * a_Creator, double a_X, double a_Y, void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) +{ + Break(a_HitPos); +} + + + + + +void cExpBottleEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) +{ + Break(a_HitPos); +} + + + + + +void cExpBottleEntity::Break(const Vector3d &a_HitPos) { // Spawn an experience orb with a reward between 3 and 11. m_World->BroadcastSoundParticleEffect(2002, POSX_TOINT, POSY_TOINT, POSZ_TOINT, 0); m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), 3 + m_World->GetTickRandomNumber(8)); - Destroy(); } diff --git a/src/Entities/ExpBottleEntity.h b/src/Entities/ExpBottleEntity.h index d62a84469..d36110f97 100644 --- a/src/Entities/ExpBottleEntity.h +++ b/src/Entities/ExpBottleEntity.h @@ -29,5 +29,10 @@ protected: // cProjectileEntity overrides: virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override; + virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override; + + /** Breaks the bottle, fires its particle effects and sounds + @param a_HitPos The position where the bottle will break */ + void Break(const Vector3d &a_HitPos); }; // tolua_export -- cgit v1.2.3 From de163f013416dc6a55f04eba5b23a7f8a9002c74 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 23 Sep 2014 12:39:09 +0200 Subject: QtBiomeVisualiser: Fixed confusion about Globals.h. --- Tools/QtBiomeVisualiser/ChunkSource.cpp | 6 +++--- Tools/QtBiomeVisualiser/GeneratorSetup.cpp | 2 +- Tools/QtBiomeVisualiser/Globals.h | 24 ++++++++++++------------ Tools/QtBiomeVisualiser/MainWindow.cpp | 6 +++--- Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp index f7174b624..28d184615 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.cpp +++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp @@ -1,10 +1,10 @@ #include "Globals.h" #include "ChunkSource.h" #include -#include "Generating/BioGen.h" +#include "src/Generating/BioGen.h" #include "inifile/iniFile.h" -#include "StringCompression.h" -#include "WorldStorage/FastNBT.h" +#include "src/StringCompression.h" +#include "src/WorldStorage/FastNBT.h" diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp index 239965409..f5412404c 100644 --- a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp +++ b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp @@ -2,7 +2,7 @@ #include "GeneratorSetup.h" #include #include -#include "Generating/BioGen.h" +#include "src/Generating/BioGen.h" #include "inifile/iniFile.h" diff --git a/Tools/QtBiomeVisualiser/Globals.h b/Tools/QtBiomeVisualiser/Globals.h index d3c7f0675..8d2e913b7 100644 --- a/Tools/QtBiomeVisualiser/Globals.h +++ b/Tools/QtBiomeVisualiser/Globals.h @@ -238,14 +238,14 @@ template class SizeChecker; #ifndef TEST_GLOBALS // Common headers (part 1, without macros): - #include "StringUtils.h" - #include "OSSupport/Sleep.h" - #include "OSSupport/CriticalSection.h" - #include "OSSupport/Semaphore.h" - #include "OSSupport/Event.h" - #include "OSSupport/Thread.h" - #include "OSSupport/File.h" - #include "Logger.h" + #include "src/StringUtils.h" + #include "src/OSSupport/Sleep.h" + #include "src/OSSupport/CriticalSection.h" + #include "src/OSSupport/Semaphore.h" + #include "src/OSSupport/Event.h" + #include "src/OSSupport/Thread.h" + #include "src/OSSupport/File.h" + #include "src/Logger.h" #else // Logging functions void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2); @@ -375,10 +375,10 @@ T Clamp(T a_Value, T a_Min, T a_Max) // Common headers (part 2, with macros): -#include "ChunkDef.h" -#include "BiomeDef.h" -#include "BlockID.h" -#include "BlockInfo.h" +#include "src/ChunkDef.h" +#include "src/BiomeDef.h" +#include "src/BlockID.h" +#include "src/BlockInfo.h" diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index a2cfa7794..eb45690c1 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -9,9 +9,9 @@ #include #include "inifile/iniFile.h" #include "ChunkSource.h" -#include "Generating/BioGen.h" -#include "StringCompression.h" -#include "WorldStorage/FastNBT.h" +#include "src/Generating/BioGen.h" +#include "src/StringCompression.h" +#include "src/WorldStorage/FastNBT.h" #include "GeneratorSetup.h" diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro index 4275f73eb..d6630bd34 100644 --- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro @@ -83,8 +83,8 @@ HEADERS += MainWindow.h \ GeneratorSetup.h INCLUDEPATH += $$_PRO_FILE_PWD_ \ - $$_PRO_FILE_PWD_/../../src \ - $$_PRO_FILE_PWD_/../../lib + $$_PRO_FILE_PWD_/../../lib \ + $$_PRO_FILE_PWD_/../../ CONFIG += C++11 -- cgit v1.2.3 From b9a5122e29842321a1b4ac84239baa96ac4db8b4 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 23 Sep 2014 14:44:15 +0200 Subject: Fixed SQLiteCpp downgrade --- lib/SQLiteCpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SQLiteCpp b/lib/SQLiteCpp index 203c2fb68..55edadd56 160000 --- a/lib/SQLiteCpp +++ b/lib/SQLiteCpp @@ -1 +1 @@ -Subproject commit 203c2fb68bbf871eaf4ca98756a113d74d620dea +Subproject commit 55edadd56d0d6f506954ad00c3b9a5d425814a2f -- cgit v1.2.3 From 366af5067b987e7d4ad233e258b9e93d6f472afe Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 23 Sep 2014 19:16:17 +0200 Subject: MCServer world compatiblity with vanilla and mcedit. --- src/WorldStorage/NBTChunkSerializer.cpp | 16 ++++++++++++++ src/WorldStorage/NBTChunkSerializer.h | 2 ++ src/WorldStorage/WSSAnvil.cpp | 39 ++++++++++++++++++++++++++++----- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 1962d42ff..09225dd90 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -765,6 +765,22 @@ void cNBTChunkSerializer::LightIsValid(bool a_IsLightValid) +void cNBTChunkSerializer::HeightMap(const cChunkDef::HeightMap * a_HeightMap) +{ + for (int RelX = 0; RelX < cChunkDef::Width; RelX++) + { + for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++) + { + int Height = cChunkDef::GetHeight(*a_HeightMap, RelX, RelZ); + m_VanillaHeightMap[(RelZ << 4) | RelX] = Height; + } + } +} + + + + + void cNBTChunkSerializer::BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) { memcpy(m_Biomes, a_BiomeMap, sizeof(m_Biomes)); diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 4c229a65c..5ffab8cc5 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -59,6 +59,7 @@ class cNBTChunkSerializer : public: cChunkDef::BiomeMap m_Biomes; unsigned char m_VanillaBiomes[cChunkDef::Width * cChunkDef::Width]; + int m_VanillaHeightMap[cChunkDef::Width * cChunkDef::Width]; bool m_BiomesAreValid; @@ -125,6 +126,7 @@ protected: // cChunkDataSeparateCollector overrides: virtual void LightIsValid(bool a_IsLightValid) override; + virtual void HeightMap(const cChunkDef::HeightMap * a_HeightMap) override; virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) override; virtual void Entity(cEntity * a_Entity) override; virtual void BlockEntity(cBlockEntity * a_Entity) override; diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 10cc39083..8dc4088b7 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -96,10 +96,26 @@ cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) : if (!cFile::Exists(fnam)) { cFastNBTWriter Writer; - Writer.BeginCompound(""); - Writer.AddInt("SpawnX", (int)(a_World->GetSpawnX())); - Writer.AddInt("SpawnY", (int)(a_World->GetSpawnY())); - Writer.AddInt("SpawnZ", (int)(a_World->GetSpawnZ())); + Writer.BeginCompound("Data"); + Writer.AddByte("allowCommands", 1); + Writer.AddByte("Difficulty", 2); + Writer.AddByte("hardcore", 0); + Writer.AddByte("initialized", 1); + Writer.AddByte("MapFeatures", 1); + Writer.AddByte("raining", a_World->IsWeatherRain() ? 1 : 0); + Writer.AddByte("thundering", a_World->IsWeatherStorm() ? 1 : 0); + Writer.AddInt("GameType", (int)a_World->GetGameMode()); + Writer.AddInt("generatorVersion", 1); + Writer.AddInt("SpawnX", (int)a_World->GetSpawnX()); + Writer.AddInt("SpawnY", (int)a_World->GetSpawnY()); + Writer.AddInt("SpawnZ", (int)a_World->GetSpawnZ()); + Writer.AddInt("version", 19133); + Writer.AddLong("DayTime", (Int64)a_World->GetTimeOfDay()); + Writer.AddLong("Time", a_World->GetWorldAge()); + Writer.AddLong("SizeOnDisk", 0); + Writer.AddString("generatorName", "default"); + Writer.AddString("generatorOptions", ""); + Writer.AddString("LevelName", a_World->GetName()); Writer.EndCompound(); Writer.Finish(); @@ -440,6 +456,13 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_ a_Writer.BeginCompound("Level"); a_Writer.AddInt("xPos", a_Chunk.m_ChunkX); a_Writer.AddInt("zPos", a_Chunk.m_ChunkZ); + + // Add "Entities" and "TileEntities". MCEdit can't load the chunk if one of these lists doesn't exists. + a_Writer.BeginList("Entities", TAG_Compound); + a_Writer.EndList(); + a_Writer.BeginList("TileEntities", TAG_Compound); + a_Writer.EndList(); + cNBTChunkSerializer Serializer(a_Writer); if (!m_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Serializer)) { @@ -454,7 +477,10 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_ a_Writer.AddByteArray("Biomes", (const char *)(Serializer.m_VanillaBiomes), ARRAYCOUNT(Serializer.m_VanillaBiomes)); a_Writer.AddIntArray ("MCSBiomes", (const int *)(Serializer.m_Biomes), ARRAYCOUNT(Serializer.m_Biomes)); } - + + // Save heightmap (Vanilla require this): + a_Writer.AddIntArray("HeightMap", (const int *)Serializer.m_VanillaHeightMap, ARRAYCOUNT(Serializer.m_VanillaHeightMap)); + // Save blockdata: a_Writer.BeginList("Sections", TAG_Compound); size_t SliceSizeBlock = cChunkDef::Width * cChunkDef::Width * 16; @@ -485,6 +511,9 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_ { a_Writer.AddByte("MCSIsLightValid", 1); } + + // Save the world age to the chunk data. Required by vanilla and mcedit. + a_Writer.AddLong("LastUpdate", m_World->GetWorldAge()); // Store the flag that the chunk has all the ores, trees, dungeons etc. MCS chunks are always complete. a_Writer.AddByte("TerrainPopulated", 1); -- cgit v1.2.3 From 0b40ce971c85eb7037250b03bab01a66536e7b05 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 23 Sep 2014 22:11:25 +0200 Subject: Fixed a crash in WSSAnvil. Reported as #1448. --- src/WorldStorage/WSSAnvil.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 10cc39083..e132a0c26 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -2464,19 +2464,19 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N LoadWolfOwner(*Monster.get(), a_NBT, a_TagIdx); int SittingIdx = a_NBT.FindChildByName(a_TagIdx, "Sitting"); - if (SittingIdx > 0) + if ((SittingIdx > 0) && (a_NBT.GetType(SittingIdx) == TAG_Byte)) { bool Sitting = ((a_NBT.GetByte(SittingIdx) == 1) ? true : false); Monster->SetIsSitting(Sitting); } int AngryIdx = a_NBT.FindChildByName(a_TagIdx, "Angry"); - if (AngryIdx > 0) + if ((AngryIdx > 0) && (a_NBT.GetType(AngryIdx) == TAG_Byte)) { bool Angry = ((a_NBT.GetByte(AngryIdx) == 1) ? true : false); Monster->SetIsAngry(Angry); } int CollarColorIdx = a_NBT.FindChildByName(a_TagIdx, "CollarColor"); - if (CollarColorIdx > 0) + if ((CollarColorIdx > 0) && (a_NBT.GetType(CollarColorIdx) == TAG_Int)) { int CollarColor = a_NBT.GetInt(CollarColorIdx); Monster->SetCollarColor(CollarColor); -- cgit v1.2.3 From d04ab9b70300e9c7fc5cddeac648fde3aa7d3450 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 23 Sep 2014 22:12:24 +0200 Subject: Fixed compiler warnings in 1.8 protocol. --- src/Protocol/Protocol18x.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index e2ea6701a..f62d350fe 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -576,7 +576,7 @@ void cProtocol180::SendLogin(const cPlayer & a_Player, const cWorld & a_World) // Send the spawn position: { cPacketizer Pkt(*this, 0x05); // Spawn Position packet - Pkt.WritePosition(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); + Pkt.WritePosition((int)a_World.GetSpawnX(), (int)a_World.GetSpawnY(), (int)a_World.GetSpawnZ()); } // Send the server difficulty: @@ -633,7 +633,7 @@ void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) cPacketizer Pkt(*this, 0x10); // Spawn Painting packet Pkt.WriteVarInt(a_Painting.GetUniqueID()); Pkt.WriteString(a_Painting.GetName().c_str()); - Pkt.WritePosition(PosX, PosY, PosZ); + Pkt.WritePosition((int)PosX, (int)PosY, (int)PosZ); Pkt.WriteChar(a_Painting.GetDirection()); } -- cgit v1.2.3 From 8d9dfc5d1a090f163f927484a43baaad49052f31 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 23 Sep 2014 22:22:38 +0200 Subject: Anvil: Wolf collar color is a byte in Vanilla. Kept the old Int reading for compatibility reasons. Ref.: #1448 --- src/WorldStorage/NBTChunkSerializer.cpp | 2 +- src/WorldStorage/WSSAnvil.cpp | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 1962d42ff..3c9da6de7 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -582,7 +582,7 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) } m_Writer.AddByte("Sitting", Wolf.IsSitting() ? 1 : 0); m_Writer.AddByte("Angry", Wolf.IsAngry() ? 1 : 0); - m_Writer.AddInt("CollarColor", Wolf.GetCollarColor()); + m_Writer.AddByte("CollarColor", (unsigned char)Wolf.GetCollarColor()); break; } case cMonster::mtZombie: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index e132a0c26..be526e74e 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -2476,10 +2476,24 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N Monster->SetIsAngry(Angry); } int CollarColorIdx = a_NBT.FindChildByName(a_TagIdx, "CollarColor"); - if ((CollarColorIdx > 0) && (a_NBT.GetType(CollarColorIdx) == TAG_Int)) + if (CollarColorIdx > 0) { - int CollarColor = a_NBT.GetInt(CollarColorIdx); - Monster->SetCollarColor(CollarColor); + switch (a_NBT.GetType(CollarColorIdx)) + { + case TAG_Byte: + { + // Vanilla uses this + unsigned char CollarColor = a_NBT.GetByte(CollarColorIdx); + Monster->SetCollarColor(CollarColor); + break; + } + case TAG_Int: + { + // Old MCS code used this, keep reading it for compatibility reasons: + Monster->SetCollarColor(a_NBT.GetInt(CollarColorIdx)); + break; + } + } } a_Entities.push_back(Monster.release()); } -- cgit v1.2.3 From 34b83656b3dc0da7deb69851f6b8239e492d2862 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 24 Sep 2014 11:21:59 +0200 Subject: QtBiomeVisualiser: Fixed MSVC path-crossing. MSVC would occasionally compile the wrong CPP file - the same name, but wrong path. --- Tools/QtBiomeVisualiser/BiomeView.cpp | 2 +- Tools/QtBiomeVisualiser/Chunk.cpp | 36 ------------------------ Tools/QtBiomeVisualiser/Chunk.h | 40 --------------------------- Tools/QtBiomeVisualiser/ChunkSource.cpp | 2 +- Tools/QtBiomeVisualiser/ChunkSource.h | 2 +- Tools/QtBiomeVisualiser/QtBiomeVisualiser.cpp | 20 ++++++++++++++ Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro | 16 +++++++---- Tools/QtBiomeVisualiser/QtChunk.cpp | 35 +++++++++++++++++++++++ Tools/QtBiomeVisualiser/QtChunk.h | 40 +++++++++++++++++++++++++++ Tools/QtBiomeVisualiser/main.cpp | 20 -------------- 10 files changed, 109 insertions(+), 104 deletions(-) delete mode 100644 Tools/QtBiomeVisualiser/Chunk.cpp delete mode 100644 Tools/QtBiomeVisualiser/Chunk.h create mode 100644 Tools/QtBiomeVisualiser/QtBiomeVisualiser.cpp create mode 100644 Tools/QtBiomeVisualiser/QtChunk.cpp create mode 100644 Tools/QtBiomeVisualiser/QtChunk.h delete mode 100644 Tools/QtBiomeVisualiser/main.cpp diff --git a/Tools/QtBiomeVisualiser/BiomeView.cpp b/Tools/QtBiomeVisualiser/BiomeView.cpp index bbaccb369..ce5a870cd 100644 --- a/Tools/QtBiomeVisualiser/BiomeView.cpp +++ b/Tools/QtBiomeVisualiser/BiomeView.cpp @@ -1,6 +1,6 @@ #include "Globals.h" #include "BiomeView.h" -#include "Chunk.h" +#include "QtChunk.h" #include #include diff --git a/Tools/QtBiomeVisualiser/Chunk.cpp b/Tools/QtBiomeVisualiser/Chunk.cpp deleted file mode 100644 index d3419af9c..000000000 --- a/Tools/QtBiomeVisualiser/Chunk.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "Globals.h" -#include "Globals.h" -#include "Chunk.h" - - - - - -Chunk::Chunk() : - m_IsValid(false) -{ -} - - - - - -const uchar * Chunk::getImage(void) const -{ - ASSERT(m_IsValid); - return m_Image; -} - - - - - -void Chunk::setImage(const Image & a_Image) -{ - memcpy(m_Image, a_Image, sizeof(a_Image)); - m_IsValid = true; -} - - - - diff --git a/Tools/QtBiomeVisualiser/Chunk.h b/Tools/QtBiomeVisualiser/Chunk.h deleted file mode 100644 index 03e7bd1b3..000000000 --- a/Tools/QtBiomeVisualiser/Chunk.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include - - - - - -class Chunk -{ -public: - /** The type used for storing image data for a chunk. */ - typedef uchar Image[16 * 16 * 4]; - - - Chunk(void); - - /** Returns true iff the chunk data is valid - loaded or generated. */ - bool isValid(void) const { return m_IsValid; } - - /** Returns the image of the chunk's biomes. Assumes that the chunk is valid. */ - const uchar * getImage(void) const; - - /** Sets the image data for this chunk. */ - void setImage(const Image & a_Image); - -protected: - /** Flag that specifies if the chunk data is valid - loaded or generated. */ - bool m_IsValid; - - /** Cached rendered image of this chunk's biomes. Updated in render(). */ - Image m_Image; -}; - -typedef std::shared_ptr ChunkPtr; - - - - - diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp index 28d184615..bebf89a0a 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.cpp +++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp @@ -2,9 +2,9 @@ #include "ChunkSource.h" #include #include "src/Generating/BioGen.h" -#include "inifile/iniFile.h" #include "src/StringCompression.h" #include "src/WorldStorage/FastNBT.h" +#include "inifile/iniFile.h" diff --git a/Tools/QtBiomeVisualiser/ChunkSource.h b/Tools/QtBiomeVisualiser/ChunkSource.h index 05e8ac5de..7bd1865ff 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.h +++ b/Tools/QtBiomeVisualiser/ChunkSource.h @@ -2,7 +2,7 @@ #include "Globals.h" #include #include -#include "Chunk.h" +#include "QtChunk.h" diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.cpp b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.cpp new file mode 100644 index 000000000..f41cdcfb2 --- /dev/null +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.cpp @@ -0,0 +1,20 @@ +#include "Globals.h" +#include "MainWindow.h" +#include + + + + + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} + + + + diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro index d6630bd34..9e5d1303c 100644 --- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro @@ -12,7 +12,7 @@ TARGET = QtBiomeVisualiser TEMPLATE = app -SOURCES += main.cpp\ +SOURCES +=\ MainWindow.cpp \ BiomeView.cpp \ ../../src/Generating/BioGen.cpp \ @@ -27,7 +27,6 @@ SOURCES += main.cpp\ ../../src/OSSupport/IsThread.cpp \ ../../src/BiomeDef.cpp \ ChunkCache.cpp \ - Chunk.cpp \ ChunkSource.cpp \ ChunkLoader.cpp \ ../../src/StringCompression.cpp \ @@ -47,7 +46,9 @@ SOURCES += main.cpp\ ../../lib/zlib/trees.c \ ../../lib/zlib/uncompr.c \ ../../lib/zlib/zutil.c \ - GeneratorSetup.cpp + GeneratorSetup.cpp \ + QtBiomeVisualiser.cpp \ + QtChunk.cpp HEADERS += MainWindow.h \ Globals.h \ @@ -64,7 +65,6 @@ HEADERS += MainWindow.h \ ../../src/OSSupport/IsThread.h \ ../../src/BiomeDef.h \ ChunkCache.h \ - Chunk.h \ ChunkSource.h \ ChunkLoader.h \ ../../src/StringCompression.h \ @@ -80,13 +80,19 @@ HEADERS += MainWindow.h \ ../../lib/zlib/zconf.h \ ../../lib/zlib/zlib.h \ ../../lib/zlib/zutil.h \ - GeneratorSetup.h + GeneratorSetup.h \ + QtChunk.h INCLUDEPATH += $$_PRO_FILE_PWD_ \ $$_PRO_FILE_PWD_/../../lib \ + $$_PRO_FILE_PWD_/../../lib/jsoncpp/include \ + $$_PRO_FILE_PWD_/../../lib/polarssl/include \ + $$_PRO_FILE_PWD_/../../lib/sqlite \ + $$_PRO_FILE_PWD_/../../lib/SQLiteCpp/include \ $$_PRO_FILE_PWD_/../../ + CONFIG += C++11 OTHER_FILES += diff --git a/Tools/QtBiomeVisualiser/QtChunk.cpp b/Tools/QtBiomeVisualiser/QtChunk.cpp new file mode 100644 index 000000000..80109b2f8 --- /dev/null +++ b/Tools/QtBiomeVisualiser/QtChunk.cpp @@ -0,0 +1,35 @@ +#include "Globals.h" +#include "QtChunk.h" + + + + + +Chunk::Chunk() : + m_IsValid(false) +{ +} + + + + + +const uchar * Chunk::getImage(void) const +{ + ASSERT(m_IsValid); + return m_Image; +} + + + + + +void Chunk::setImage(const Image & a_Image) +{ + memcpy(m_Image, a_Image, sizeof(a_Image)); + m_IsValid = true; +} + + + + diff --git a/Tools/QtBiomeVisualiser/QtChunk.h b/Tools/QtBiomeVisualiser/QtChunk.h new file mode 100644 index 000000000..03e7bd1b3 --- /dev/null +++ b/Tools/QtBiomeVisualiser/QtChunk.h @@ -0,0 +1,40 @@ +#pragma once + +#include + + + + + +class Chunk +{ +public: + /** The type used for storing image data for a chunk. */ + typedef uchar Image[16 * 16 * 4]; + + + Chunk(void); + + /** Returns true iff the chunk data is valid - loaded or generated. */ + bool isValid(void) const { return m_IsValid; } + + /** Returns the image of the chunk's biomes. Assumes that the chunk is valid. */ + const uchar * getImage(void) const; + + /** Sets the image data for this chunk. */ + void setImage(const Image & a_Image); + +protected: + /** Flag that specifies if the chunk data is valid - loaded or generated. */ + bool m_IsValid; + + /** Cached rendered image of this chunk's biomes. Updated in render(). */ + Image m_Image; +}; + +typedef std::shared_ptr ChunkPtr; + + + + + diff --git a/Tools/QtBiomeVisualiser/main.cpp b/Tools/QtBiomeVisualiser/main.cpp deleted file mode 100644 index f41cdcfb2..000000000 --- a/Tools/QtBiomeVisualiser/main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "Globals.h" -#include "MainWindow.h" -#include - - - - - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - MainWindow w; - w.show(); - - return a.exec(); -} - - - - -- cgit v1.2.3 From 1d588b5195507f52c25d57a627c3304c024770ce Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 24 Sep 2014 15:17:20 +0200 Subject: Don't create two entity lists. --- src/WorldStorage/NBTChunkSerializer.cpp | 12 ++++++++++++ src/WorldStorage/WSSAnvil.cpp | 9 ++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 0e364d8b0..a052bf5f3 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -81,6 +81,18 @@ void cNBTChunkSerializer::Finish(void) memset(m_BlockLight, 0, sizeof(m_BlockLight)); memset(m_BlockSkyLight, 0, sizeof(m_BlockSkyLight)); } + + // Check if "Entity" and "TileEntities" lists exists. MCEdit requires this. + if (!m_HasHadEntity) + { + a_Writer.BeginList("Entities", TAG_Compound); + a_Writer.EndList(); + } + if (!m_HasHadBlockEntity) + { + a_Writer.BeginList("TileEntities", TAG_Compound); + a_Writer.EndList(); + } } diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 3821ad976..bd814e2c7 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -51,6 +51,7 @@ #include "../Entities/ItemFrame.h" #include "../Protocol/MojangAPI.h" +#include "Server.h" @@ -99,7 +100,7 @@ cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) : Writer.BeginCompound("Data"); Writer.AddByte("allowCommands", 1); Writer.AddByte("Difficulty", 2); - Writer.AddByte("hardcore", 0); + Writer.AddByte("hardcore", cRoot::Get()->GetServer()->IsHardcore() ? 1 : 0); Writer.AddByte("initialized", 1); Writer.AddByte("MapFeatures", 1); Writer.AddByte("raining", a_World->IsWeatherRain() ? 1 : 0); @@ -457,12 +458,6 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_ a_Writer.AddInt("xPos", a_Chunk.m_ChunkX); a_Writer.AddInt("zPos", a_Chunk.m_ChunkZ); - // Add "Entities" and "TileEntities". MCEdit can't load the chunk if one of these lists doesn't exists. - a_Writer.BeginList("Entities", TAG_Compound); - a_Writer.EndList(); - a_Writer.BeginList("TileEntities", TAG_Compound); - a_Writer.EndList(); - cNBTChunkSerializer Serializer(a_Writer); if (!m_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Serializer)) { -- cgit v1.2.3 From 32ecb121a3f7e0fa2cd35c78403949947e889c1d Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 24 Sep 2014 15:30:52 +0200 Subject: derp --- src/WorldStorage/NBTChunkSerializer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index a052bf5f3..08ed893f5 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -85,13 +85,13 @@ void cNBTChunkSerializer::Finish(void) // Check if "Entity" and "TileEntities" lists exists. MCEdit requires this. if (!m_HasHadEntity) { - a_Writer.BeginList("Entities", TAG_Compound); - a_Writer.EndList(); + m_Writer.BeginList("Entities", TAG_Compound); + m_Writer.EndList(); } if (!m_HasHadBlockEntity) { - a_Writer.BeginList("TileEntities", TAG_Compound); - a_Writer.EndList(); + m_Writer.BeginList("TileEntities", TAG_Compound); + m_Writer.EndList(); } } -- cgit v1.2.3 From 799c96661d7dc8ea89517fa0be205e72ea2f717e Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 25 Sep 2014 15:45:39 +0100 Subject: Fixed style --- src/BlockInfo.h | 4 +- src/Blocks/ChunkInterface.cpp | 66 ++++++++++++++++++++++++++++++ src/Blocks/GetHandlerCompileTimeTemplate.h | 37 +++++++++++++++++ src/Mobs/Monster.h | 3 ++ 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/BlockInfo.h b/src/BlockInfo.h index bfa62a132..1e4cf2ca0 100644 --- a/src/BlockInfo.h +++ b/src/BlockInfo.h @@ -19,8 +19,8 @@ public: /** Returns the associated BlockInfo structure for the specified block type. */ /** This accessor makes sure that the cBlockInfo structures are properly initialized exactly once. -It does so by using the C++ singleton approximation - storing the actual singleton as the function's static variable. -It works only if it is called for the first time before the app spawns other threads. */ + It does so by using the C++ singleton approximation - storing the actual singleton as the function's static variable. + It works only if it is called for the first time before the app spawns other threads. */ static cBlockInfo & Get(BLOCKTYPE a_Type) { static cBlockInfo ms_Info[256]; diff --git a/src/Blocks/ChunkInterface.cpp b/src/Blocks/ChunkInterface.cpp index a4c96a478..5ac4dcf80 100644 --- a/src/Blocks/ChunkInterface.cpp +++ b/src/Blocks/ChunkInterface.cpp @@ -5,24 +5,49 @@ #include "ChunkMap.h" #include "BlockHandler.h" + + + + + BLOCKTYPE cChunkInterface::GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ) { return m_ChunkMap->GetBlock(a_BlockX, a_BlockY, a_BlockZ); } + + + + + BLOCKTYPE cChunkInterface::GetBlock(const Vector3i & a_Pos) { return GetBlock(a_Pos.x, a_Pos.y, a_Pos.z); } + + + + + NIBBLETYPE cChunkInterface::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ) { return m_ChunkMap->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); } + + + + + bool cChunkInterface::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) { return m_ChunkMap->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); } + + + + + /** Sets the block at the specified coords to the specified value. Full processing, incl. updating neighbors, is performed. */ @@ -31,16 +56,31 @@ void cChunkInterface::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTY m_ChunkMap->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); } + + + + + void cChunkInterface::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData) { m_ChunkMap->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_MetaData); } + + + + + void cChunkInterface::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_TickDelay, BLOCKTYPE a_PreviousBlockType, cWorldInterface & a_WorldInterface) { m_ChunkMap->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_WorldInterface.GetWorldAge() + a_TickDelay, a_PreviousBlockType); } + + + + + /** Sets the block at the specified coords to the specified value. The replacement doesn't trigger block updates. The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block) @@ -50,29 +90,55 @@ void cChunkInterface::FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLO m_ChunkMap->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); } + + + + + void cChunkInterface::FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta); } + + + + + void cChunkInterface::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) { m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); } + + + + + bool cChunkInterface::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) { return m_ChunkMap->ForEachChunkInRect(a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ, a_Callback); } + + + + + bool cChunkInterface::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { return m_ChunkMap->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); } + + + + + bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, int a_X, int a_Y, int a_Z) { cBlockHandler * Handler = cBlockInfo::GetHandler(GetBlock(a_X, a_Y, a_Z)); Handler->OnDestroyed(*this, a_WorldInterface, a_X, a_Y, a_Z); return m_ChunkMap->DigBlock(a_X, a_Y, a_Z); } + diff --git a/src/Blocks/GetHandlerCompileTimeTemplate.h b/src/Blocks/GetHandlerCompileTimeTemplate.h index 658497bf2..3466b5426 100644 --- a/src/Blocks/GetHandlerCompileTimeTemplate.h +++ b/src/Blocks/GetHandlerCompileTimeTemplate.h @@ -8,9 +8,20 @@ class cBlockTripwireHookHandler; class cBlockDoorHandler; class cBlockPistonHandler; + + + + + template class GetHandlerCompileTime; + + + + + + template<> class GetHandlerCompileTime { @@ -18,6 +29,11 @@ public: typedef cBlockTorchHandler type; }; + + + + + template<> class GetHandlerCompileTime { @@ -25,6 +41,11 @@ public: typedef cBlockLeverHandler type; }; + + + + + template<> class GetHandlerCompileTime { @@ -32,6 +53,11 @@ public: typedef cBlockButtonHandler type; }; + + + + + template<> class GetHandlerCompileTime { @@ -39,6 +65,11 @@ public: typedef cBlockTripwireHookHandler type; }; + + + + + template<> class GetHandlerCompileTime { @@ -46,9 +77,15 @@ public: typedef cBlockDoorHandler type; }; + + + + + template<> class GetHandlerCompileTime { public: typedef cBlockPistonHandler type; }; + diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index 9fd67d67c..ba746ebc8 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -25,6 +25,9 @@ class cMonster : typedef cPawn super; public: + //Depreciated + typedef eMonsterType eType; + enum eFamily { mfHostile = 0, // Spider, Zombies ... -- cgit v1.2.3 From 843f31ecbace5b78486cb72df9404e0bfec900df Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 18:33:01 +0200 Subject: HangingEntity: Silenced a crash. Vanilla worlds sometimes contain data that this was asserting upon. Changed into a log. --- src/Entities/HangingEntity.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Entities/HangingEntity.cpp b/src/Entities/HangingEntity.cpp index 8c70c606e..6e9a89550 100644 --- a/src/Entities/HangingEntity.cpp +++ b/src/Entities/HangingEntity.cpp @@ -28,11 +28,17 @@ void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle) // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces switch (m_BlockFace) { - case BLOCK_FACE_ZP: break; // Initialised to zero + case BLOCK_FACE_ZP: Dir = 0; break; case BLOCK_FACE_ZM: Dir = 2; break; case BLOCK_FACE_XM: Dir = 1; break; case BLOCK_FACE_XP: Dir = 3; break; - default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return; + default: + { + LOGINFO("Invalid face (%d) in a cHangingEntity at {%d, %d, %d}, adjusting to BLOCK_FACE_XP.", + m_BlockFace, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ() + ); + Dir = 3; + } } if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180 -- cgit v1.2.3 From a518a83c258897d5f2e0d769aa7fce8c30befafb Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 18:33:34 +0200 Subject: 1.7 Protocol: fixed potential problems with no-payload packets. --- src/Protocol/Protocol17x.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 67a4c47a7..73d2a74f9 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1519,9 +1519,6 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); m_ReceivedData.CommitRead(); - // Write one NUL extra, so that we can detect over-reads - bb.Write("\0", 1); - UInt32 PacketType; if (!bb.ReadVarInt(PacketType)) { @@ -1529,6 +1526,9 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) break; } + // Write one NUL extra, so that we can detect over-reads + bb.Write("\0", 1); + // Log the packet info into the comm log file: if (g_ShouldLogCommIn) { @@ -1536,7 +1536,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size) bb.ReadAll(PacketData); bb.ResetRead(); bb.ReadVarInt(PacketType); - ASSERT(PacketData.size() > 0); + ASSERT(PacketData.size() > 0); // We have written an extra NUL, so there had to be at least one byte read PacketData.resize(PacketData.size() - 1); AString PacketDataHex; CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16); -- cgit v1.2.3 From aeabc4ff6b19384df47031fc995cd8ac988c2e0a Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 18:34:40 +0200 Subject: 1.8 Protocol: Fixed problems with no-payload packets. --- src/Protocol/Protocol18x.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index f62d350fe..94eaa43db 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1711,7 +1711,7 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) m_ReceivedData.ResetRead(); break; } - cByteBuffer bb(PacketLen); + cByteBuffer bb(PacketLen + 1); VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); m_ReceivedData.CommitRead(); @@ -1726,9 +1726,6 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) } } - // Write one NUL extra, so that we can detect over-reads - bb.Write("\0", 1); - UInt32 PacketType; if (!bb.ReadVarInt(PacketType)) { @@ -1736,6 +1733,9 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) break; } + // Write one NUL extra, so that we can detect over-reads + bb.Write("\0", 1); + // Log the packet info into the comm log file: if (g_ShouldLogCommIn) { @@ -1743,7 +1743,7 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) bb.ReadAll(PacketData); bb.ResetRead(); bb.ReadVarInt(PacketType); - ASSERT(PacketData.size() > 0); + ASSERT(PacketData.size() > 0); // We have written an extra NUL, so there had to be at least one byte read PacketData.resize(PacketData.size() - 1); AString PacketDataHex; CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16); @@ -1777,7 +1777,8 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) return; } - if (bb.GetReadableSpace() != 0) + // The packet should have 1 byte left in the buffer - the NUL we had added + if (bb.GetReadableSpace() != 1) { // Read more or less than packet length, report as error LOGWARNING("Protocol 1.8: Wrong number of bytes read for packet 0x%x, state %d. Read " SIZE_T_FMT " bytes, packet contained %u bytes", -- cgit v1.2.3 From c6f78d516b356c9ea1137331fbd5eff0762aa1a9 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 18:35:41 +0200 Subject: Redstone: Fixed a crash with repeaters on a chunk border. --- src/Simulator/IncrementalRedstoneSimulator.cpp | 35 ++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 7b3a2c2fa..8649a1841 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -1619,17 +1619,22 @@ bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelB { // Check if eastern(right) neighbor is a powered on repeater who is facing us BLOCKTYPE Block = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater? + NIBBLETYPE OtherRepeaterDir = 0; + if (m_Chunk->UnboundedRelGetBlock(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block, OtherRepeaterDir) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater? { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ) & 0x3; - if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked + if ((OtherRepeaterDir & 0x03) == 0x03) + { + return true; + } // If so, I am latched/locked } // Check if western(left) neighbor is a powered on repeater who is facing us - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) + if (m_Chunk->UnboundedRelGetBlock(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block, OtherRepeaterDir) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX -1, a_RelBlockY, a_RelBlockZ) & 0x3; - if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked + if ((OtherRepeaterDir & 0x03) == 0x01) + { + return true; + } // If so, I am latched/locked } break; @@ -1641,19 +1646,23 @@ bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelB { // Check if southern(down) neighbor is a powered on repeater who is facing us BLOCKTYPE Block = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) + NIBBLETYPE OtherRepeaterDir = 0; + if (m_Chunk->UnboundedRelGetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, Block, OtherRepeaterDir) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1) & 0x3; - if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked + if ((OtherRepeaterDir & 0x03) == 0x00) + { + return true; + } // If so, am latched/locked } // Check if northern(up) neighbor is a powered on repeater who is facing us - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) + if (m_Chunk->UnboundedRelGetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, Block, OtherRepeaterDir) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1) & 0x3; - if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked + if ((OtherRepeaterDir & 0x03) == 0x02) + { + return true; + } // If so, I am latched/locked } - break; } } -- cgit v1.2.3 From daf5127b28f3c6884e94fc066b3e5e117a6b5d35 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 25 Sep 2014 18:37:24 +0200 Subject: Fixed hanging direction bugs. --- src/Entities/HangingEntity.cpp | 15 +++++++++++++++ src/Entities/HangingEntity.h | 2 +- src/WorldStorage/WSSAnvil.cpp | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Entities/HangingEntity.cpp b/src/Entities/HangingEntity.cpp index 8c70c606e..e789f5f18 100644 --- a/src/Entities/HangingEntity.cpp +++ b/src/Entities/HangingEntity.cpp @@ -21,6 +21,21 @@ cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, +void cHangingEntity::SetDirection(eBlockFace a_BlockFace) +{ + if ((a_BlockFace < 2) || (a_BlockFace > 5)) + { + ASSERT(!"Tried to set a bad direction!"); + return; + } + + m_BlockFace = a_BlockFace; +} + + + + + void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle) { int Dir = 0; diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h index 3593f9ede..455f2f23f 100644 --- a/src/Entities/HangingEntity.h +++ b/src/Entities/HangingEntity.h @@ -24,7 +24,7 @@ public: eBlockFace GetDirection() const { return m_BlockFace; } // tolua_export /** Set the orientation from the hanging entity */ - void SetDirection(eBlockFace a_BlockFace) { m_BlockFace = a_BlockFace; } // tolua_export + void SetDirection(eBlockFace a_BlockFace); // tolua_export /** Returns the X coord. */ int GetTileX() const { return POSX_TOINT; } // tolua_export diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index bd814e2c7..7a9490cd4 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1664,7 +1664,7 @@ void cWSSAnvil::LoadHangingFromNBT(cHangingEntity & a_Hanging, const cParsedNBT if (Direction > 0) { Direction = (int)a_NBT.GetByte(Direction); - if ((Direction < 0) || (Direction > 5)) + if ((Direction < 2) || (Direction > 5)) { a_Hanging.SetDirection(BLOCK_FACE_NORTH); } -- cgit v1.2.3 From 67fe834499b2f0f93cdba1132a80ccb1924e199c Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 25 Sep 2014 18:37:36 +0200 Subject: Fixed dispender direction bug --- src/BlockEntities/DispenserEntity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BlockEntities/DispenserEntity.cpp b/src/BlockEntities/DispenserEntity.cpp index c02c68afa..f8830bf25 100644 --- a/src/BlockEntities/DispenserEntity.cpp +++ b/src/BlockEntities/DispenserEntity.cpp @@ -203,7 +203,7 @@ void cDispenserEntity::SpawnProjectileFromDispenser(int a_BlockX, int a_BlockY, Vector3d cDispenserEntity::GetShootVector(NIBBLETYPE a_Meta) { - switch (a_Meta) + switch (a_Meta & 0x7) { case E_META_DROPSPENSER_FACING_YP: return Vector3d( 0, 1, 0); case E_META_DROPSPENSER_FACING_YM: return Vector3d( 0, -1, 0); -- cgit v1.2.3 From 12621e3800ec353bca179243d521580e0da6eae9 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 25 Sep 2014 18:49:55 +0200 Subject: Use the json writer to write sign texts. Without this change the client disconnects if the text contains " --- src/Protocol/Protocol18x.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index f62d350fe..a92ab5f54 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1391,13 +1391,18 @@ void cProtocol180::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) void cProtocol180::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) { ASSERT(m_State == 3); // In game mode? - + cPacketizer Pkt(*this, 0x33); Pkt.WritePosition(a_BlockX, a_BlockY, a_BlockZ); - Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line1.c_str())); - Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line2.c_str())); - Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line3.c_str())); - Pkt.WriteString(Printf("{\"text\": \"%s\"}", a_Line4.c_str())); + + Json::StyledWriter JsonWriter; + AString Lines[] = { a_Line1, a_Line2, a_Line3, a_Line4 }; + for (size_t i = 0; i < ARRAYCOUNT(Lines); i++) + { + Json::Value RootValue; + RootValue["text"] = Lines[i]; + Pkt.WriteString(JsonWriter.write(RootValue).c_str()); + } } -- cgit v1.2.3 From 7cdcf0a8833b56a98d60a87a341607fed988cac7 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 25 Sep 2014 19:01:44 +0200 Subject: Anvil: Arrow Tile tags are a short in Vanilla --- src/WorldStorage/NBTChunkSerializer.cpp | 6 +++--- src/WorldStorage/WSSAnvil.cpp | 25 +++++++++++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 08ed893f5..849e9eb77 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -637,9 +637,9 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile) { cArrowEntity * Arrow = (cArrowEntity *)a_Projectile; - m_Writer.AddInt("xTile", (Int16)Arrow->GetBlockHit().x); - m_Writer.AddInt("yTile", (Int16)Arrow->GetBlockHit().y); - m_Writer.AddInt("zTile", (Int16)Arrow->GetBlockHit().z); + m_Writer.AddShort("xTile", (Int16)Arrow->GetBlockHit().x); + m_Writer.AddShort("yTile", (Int16)Arrow->GetBlockHit().y); + m_Writer.AddShort("zTile", (Int16)Arrow->GetBlockHit().z); m_Writer.AddByte("pickup", Arrow->GetPickupState()); m_Writer.AddDouble("damage", Arrow->GetDamageCoeff()); break; diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 7a9490cd4..092b9514c 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1752,7 +1752,7 @@ void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_ // Load pickup state: int PickupIdx = a_NBT.FindChildByName(a_TagIdx, "pickup"); - if (PickupIdx > 0) + if ((PickupIdx > 0) && (a_NBT.GetType(PickupIdx) == TAG_Byte)) { Arrow->SetPickupState((cArrowEntity::ePickupState)a_NBT.GetByte(PickupIdx)); } @@ -1760,7 +1760,7 @@ void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_ { // Try the older "player" tag: int PlayerIdx = a_NBT.FindChildByName(a_TagIdx, "player"); - if (PlayerIdx > 0) + if ((PlayerIdx > 0) && (a_NBT.GetType(PlayerIdx) == TAG_Byte)) { Arrow->SetPickupState((a_NBT.GetByte(PlayerIdx) == 0) ? cArrowEntity::psNoPickup : cArrowEntity::psInSurvivalOrCreative); } @@ -1768,7 +1768,7 @@ void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_ // Load damage: int DamageIdx = a_NBT.FindChildByName(a_TagIdx, "damage"); - if (DamageIdx > 0) + if ((DamageIdx > 0) && (a_NBT.GetType(DamageIdx) == TAG_Double)) { Arrow->SetDamageCoeff(a_NBT.GetDouble(DamageIdx)); } @@ -1779,7 +1779,24 @@ void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_ int InBlockZIdx = a_NBT.FindChildByName(a_TagIdx, "zTile"); if ((InBlockXIdx > 0) && (InBlockYIdx > 0) && (InBlockZIdx > 0)) { - Arrow->SetBlockHit(Vector3i(a_NBT.GetInt(InBlockXIdx), a_NBT.GetInt(InBlockYIdx), a_NBT.GetInt(InBlockZIdx))); + if (a_NBT.GetType(InBlockXIdx) == a_NBT.GetType(InBlockYIdx) == a_NBT.GetType(InBlockZIdx)) + { + switch (a_NBT.GetType(InBlockXIdx)) + { + case TAG_Int: + { + // Old MCS code used this, keep reading it for compatibility reasons: + Arrow->SetBlockHit(Vector3i(a_NBT.GetInt(InBlockXIdx), a_NBT.GetInt(InBlockYIdx), a_NBT.GetInt(InBlockZIdx))); + break; + } + case TAG_Short: + { + // Vanilla uses this + Arrow->SetBlockHit(Vector3i((int)a_NBT.GetShort(InBlockXIdx), (int)a_NBT.GetShort(InBlockYIdx), (int)a_NBT.GetShort(InBlockZIdx))); + break; + } + } + } } // Store the new arrow in the entities list: -- cgit v1.2.3 From 060ac500fcd369814d43100549e3d8b0ab51304d Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 25 Sep 2014 19:19:30 +0200 Subject: Fixed wrong Surrounding size --- src/Mobs/Villager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 1cdac7c74..0efd5501e 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -109,11 +109,11 @@ void cVillager::HandleFarmerPrepareFarmCrops() Surrounding.Read( m_World, (int) GetPosX() - 5, - (int) GetPosX() + 5, + (int) GetPosX() + 6, (int) GetPosY() - 3, - (int) GetPosY() + 3, + (int) GetPosY() + 4, (int) GetPosZ() - 5, - (int) GetPosZ() + 5 + (int) GetPosZ() + 6 ); for (int I = 0; I < 5; I++) -- cgit v1.2.3 From 050b28741bbc503170679d5d3e91000f06f4d6ea Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 25 Sep 2014 19:28:11 +0200 Subject: Comment style --- src/Entities/HangingEntity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h index 455f2f23f..1cc0034e1 100644 --- a/src/Entities/HangingEntity.h +++ b/src/Entities/HangingEntity.h @@ -24,7 +24,7 @@ public: eBlockFace GetDirection() const { return m_BlockFace; } // tolua_export /** Set the orientation from the hanging entity */ - void SetDirection(eBlockFace a_BlockFace); // tolua_export + void SetDirection(eBlockFace a_BlockFace); // tolua_export /** Returns the X coord. */ int GetTileX() const { return POSX_TOINT; } // tolua_export -- cgit v1.2.3 From 3459bc1ede4ebbb8177444cc2b265ecea0678dea Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 19:42:35 +0200 Subject: Protocol 1.8: Added checks for values presence. Reported by @worktycho / Coverity. --- src/Protocol/Protocol18x.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 94eaa43db..c07441ef7 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1966,13 +1966,19 @@ void cProtocol180::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) void cProtocol180::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) { UInt32 EncKeyLength, EncNonceLength; - a_ByteBuffer.ReadVarInt(EncKeyLength); + if (!a_ByteBuffer.ReadVarInt(EncKeyLength)) + { + return; + } AString EncKey; if (!a_ByteBuffer.ReadString(EncKey, EncKeyLength)) { return; } - a_ByteBuffer.ReadVarInt(EncNonceLength); + if (!a_ByteBuffer.ReadVarInt(EncNonceLength)) + { + return; + } AString EncNonce; if (!a_ByteBuffer.ReadString(EncNonce, EncNonceLength)) { -- cgit v1.2.3 From 27187371ebe3988f92a03d5ed822aba5f3d97d79 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 20:34:49 +0200 Subject: Protocol 1.8: Handling packet compression properly. The compression didn't work with CommLog turned on. --- src/Protocol/Protocol18x.cpp | 47 +++++++++++++++++++++++++++++++++----------- src/Protocol/Protocol18x.h | 6 ++++-- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index c07441ef7..8a9c492ff 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1711,20 +1711,43 @@ void cProtocol180::AddReceivedData(const char * a_Data, size_t a_Size) m_ReceivedData.ResetRead(); break; } - cByteBuffer bb(PacketLen + 1); - VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); - m_ReceivedData.CommitRead(); - - // Compressed packets + + // Check packet for compression: + UInt32 CompressedSize = 0; + AString UncompressedData; if (m_State == 3) { - UInt32 CompressedSize; - if (!bb.ReadVarInt(CompressedSize)) + UInt32 NumBytesRead = m_ReceivedData.GetReadableSpace(); + m_ReceivedData.ReadVarInt(CompressedSize); + if (CompressedSize > 0) { - // Not enough data - break; + // Decompress the data: + AString CompressedData; + m_ReceivedData.ReadString(CompressedData, CompressedSize); + InflateString(CompressedData.data(), CompressedSize, UncompressedData); + PacketLen = UncompressedData.size(); + } + else + { + NumBytesRead -= m_ReceivedData.GetReadableSpace(); // How many bytes has the CompressedSize taken up? + ASSERT(PacketLen > NumBytesRead); + PacketLen -= NumBytesRead; } } + + // Move the packet payload to a separate cByteBuffer, bb: + cByteBuffer bb(PacketLen + 1); + if (CompressedSize == 0) + { + // No compression was used, move directly + VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); + } + else + { + // Compression was used, move the uncompressed data: + VERIFY(bb.Write(UncompressedData.data(), UncompressedData.size())); + } + m_ReceivedData.CommitRead(); UInt32 PacketType; if (!bb.ReadVarInt(PacketType)) @@ -2299,7 +2322,7 @@ void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); AString Data; - a_ByteBuffer.ReadAll(Data); + a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1); m_Client->HandlePluginMessage(Channel, Data); } @@ -2526,7 +2549,7 @@ void cProtocol180::SendData(const char * a_Data, size_t a_Size) -bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_RemainingBytes) +bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) { HANDLE_PACKET_READ(a_ByteBuffer, ReadBEShort, short, ItemType); if (ItemType == -1) @@ -2547,7 +2570,7 @@ bool cProtocol180::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a } AString Metadata; - if (!a_ByteBuffer.ReadString(Metadata, a_ByteBuffer.GetReadableSpace() - a_RemainingBytes) || (Metadata.size() == 0) || (Metadata[0] == 0)) + if (!a_ByteBuffer.ReadString(Metadata, a_ByteBuffer.GetReadableSpace() - a_KeepRemainingBytes - 1) || (Metadata.size() == 0) || (Metadata[0] == 0)) { // No metadata return true; diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index eb0253663..df188b70f 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -321,8 +321,10 @@ protected: void SendCompass(const cWorld & a_World); - /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */ - virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_RemainingBytes = 0); + /** Reads an item out of the received data, sets a_Item to the values read. + Returns false if not enough received data. + a_KeepRemainingBytes tells the function to keep that many bytes at the end of the buffer. */ + virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes = 0); /** Parses item metadata as read by ReadItem(), into the item enchantments. */ void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); -- cgit v1.2.3 From 8f4cc27e39188d302f6575e7324002e2515fd789 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 20:46:50 +0200 Subject: Added cByteBuffer::WriteBEUShort(). --- src/ByteBuffer.cpp | 13 +++++++++++++ src/ByteBuffer.h | 1 + src/Protocol/ChunkDataSerializer.cpp | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index 17e8091c7..5bf98eda9 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -547,6 +547,19 @@ bool cByteBuffer::WriteBEShort(short a_Value) +bool cByteBuffer::WriteBEUShort(unsigned short a_Value) +{ + CHECK_THREAD; + CheckValid(); + PUTBYTES(2); + u_short Converted = htons((u_short)a_Value); + return WriteBuf(&Converted, 2); +} + + + + + bool cByteBuffer::WriteBEInt(int a_Value) { CHECK_THREAD; diff --git a/src/ByteBuffer.h b/src/ByteBuffer.h index c1c71d8c4..74dc378d4 100644 --- a/src/ByteBuffer.h +++ b/src/ByteBuffer.h @@ -82,6 +82,7 @@ public: bool WriteChar (char a_Value); bool WriteByte (unsigned char a_Value); bool WriteBEShort (short a_Value); + bool WriteBEUShort (unsigned short a_Value); bool WriteBEInt (int a_Value); bool WriteBEInt64 (Int64 a_Value); bool WriteBEFloat (float a_Value); diff --git a/src/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp index a133cc0e3..5d080656d 100644 --- a/src/Protocol/ChunkDataSerializer.cpp +++ b/src/Protocol/ChunkDataSerializer.cpp @@ -191,7 +191,7 @@ void cChunkDataSerializer::Serialize47(AString & a_Data, int a_ChunkX, int a_Chu Packet.WriteBEInt(a_ChunkX); Packet.WriteBEInt(a_ChunkZ); Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag - Packet.WriteBEShort((short) 0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff + Packet.WriteBEUShort(0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff // Write the chunk size: const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; -- cgit v1.2.3 From e5293706de4433d5198e510de0a3e32f572ce230 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 20:47:16 +0200 Subject: TwoLevel BioGen: reads params from INI file. --- src/Generating/BioGen.cpp | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 217ca8f80..3ee0bd4c5 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -913,15 +913,32 @@ EMCSBiome cBioGenTwoLevel::SelectBiome(int a_BiomeGroup, int a_BiomeIdx, int a_D void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile) { - // TODO: Read these from a file - m_VoronoiLarge.SetCellSize(1024); - m_VoronoiSmall.SetCellSize(128); - m_DistortX.AddOctave(0.01f, 16); - m_DistortX.AddOctave(0.005f, 8); - m_DistortX.AddOctave(0.0025f, 4); - m_DistortZ.AddOctave(0.01f, 16); - m_DistortZ.AddOctave(0.005f, 8); - m_DistortZ.AddOctave(0.0025f, 4); + m_VoronoiLarge.SetCellSize(a_IniFile.GetValueSetI("Generator", "TwoLevelLargeCellSize", 1024)); + m_VoronoiSmall.SetCellSize(a_IniFile.GetValueSetI("Generator", "TwoLevelSmallCellSize", 128)); + m_DistortX.AddOctave( + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave1Freq", 0.01), + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave1Amp", 16) + ); + m_DistortX.AddOctave( + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave2Freq", 0.005), + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave2Amp", 8) + ); + m_DistortX.AddOctave( + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave3Freq", 0.0025), + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave3Amp", 4) + ); + m_DistortZ.AddOctave( + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave1Freq", 0.01), + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave1Amp", 16) + ); + m_DistortZ.AddOctave( + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave2Freq", 0.005), + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave2Amp", 8) + ); + m_DistortZ.AddOctave( + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave3Freq", 0.0025), + (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave3Amp", 4) + ); } -- cgit v1.2.3 From 0443f5d531b21917b3605254b17475569573fc48 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 21:23:05 +0200 Subject: cByteBuffer: Fixed position reading. --- src/ByteBuffer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index 5bf98eda9..e61a90bbc 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -500,9 +500,9 @@ bool cByteBuffer::ReadPosition(int & a_BlockX, int & a_BlockY, int & a_BlockZ) UInt32 BlockXRaw = (Value >> 38) & 0x3ffffff; UInt32 BlockYRaw = (Value >> 26) & 0xfff; UInt32 BlockZRaw = (Value & 0x3ffffff); - a_BlockX = ((BlockXRaw & 0x2000000) == 0) ? BlockXRaw : (~(BlockXRaw & 0x1ffffff)) + 1; - a_BlockY = ((BlockYRaw & 0x800) == 0) ? BlockYRaw : (~(BlockXRaw & 0x7ff)) + 1; - a_BlockZ = ((BlockZRaw & 0x2000000) == 0) ? BlockZRaw : (~(BlockZRaw & 0x1ffffff)) + 1; + a_BlockX = ((BlockXRaw & 0x2000000) == 0) ? BlockXRaw : -(0x03ffffff - (int)BlockXRaw + 1); + a_BlockY = ((BlockYRaw & 0x800) == 0) ? BlockYRaw : -(0x07ff - (int)BlockYRaw + 1); + a_BlockZ = ((BlockZRaw & 0x2000000) == 0) ? BlockZRaw : -(0x03ffffff - (int)BlockZRaw + 1); return true; } -- cgit v1.2.3 From 976c6bd32bd81e26fed392a55dc25f2090f18735 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 21:33:20 +0200 Subject: Protocol 1.8: Fixed plugin message packet. --- src/Protocol/Protocol18x.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 3e1863f97..896947d03 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -1000,6 +1000,7 @@ void cProtocol180::SendPluginMessage(const AString & a_Channel, const AString & cPacketizer Pkt(*this, 0x3f); Pkt.WriteString(a_Channel); + Pkt.WriteVarInt((UInt32)a_Message.size()); Pkt.WriteBuf(a_Message.data(), a_Message.size()); } @@ -2326,8 +2327,9 @@ void cProtocol180::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, DataLen); AString Data; - a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1); + a_ByteBuffer.ReadString(Data, DataLen); m_Client->HandlePluginMessage(Channel, Data); } -- cgit v1.2.3 From 6b260f06ba8ec773e4a81fea38fb123b1ea09081 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 25 Sep 2014 23:06:21 +0200 Subject: cByteBuffer: Simplified ReadPosition(). Also, by popular demand, added more comments to the code. --- src/ByteBuffer.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index e61a90bbc..70fdc008c 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -497,12 +497,15 @@ bool cByteBuffer::ReadPosition(int & a_BlockX, int & a_BlockY, int & a_BlockZ) return false; } - UInt32 BlockXRaw = (Value >> 38) & 0x3ffffff; - UInt32 BlockYRaw = (Value >> 26) & 0xfff; - UInt32 BlockZRaw = (Value & 0x3ffffff); - a_BlockX = ((BlockXRaw & 0x2000000) == 0) ? BlockXRaw : -(0x03ffffff - (int)BlockXRaw + 1); - a_BlockY = ((BlockYRaw & 0x800) == 0) ? BlockYRaw : -(0x07ff - (int)BlockYRaw + 1); - a_BlockZ = ((BlockZRaw & 0x2000000) == 0) ? BlockZRaw : -(0x03ffffff - (int)BlockZRaw + 1); + // Convert the 64 received bits into 3 coords: + UInt32 BlockXRaw = (Value >> 38) & 0x03ffffff; // Top 26 bits + UInt32 BlockYRaw = (Value >> 26) & 0x0fff; // Middle 12 bits + UInt32 BlockZRaw = (Value & 0x03ffffff); // Bottom 26 bits + + // If the highest bit in the number's range is set, convert the number into negative: + a_BlockX = ((BlockXRaw & 0x02000000) == 0) ? BlockXRaw : -(0x04000000 - (int)BlockXRaw); + a_BlockY = ((BlockYRaw & 0x0800) == 0) ? BlockYRaw : -(0x0800 - (int)BlockYRaw); + a_BlockZ = ((BlockZRaw & 0x02000000) == 0) ? BlockZRaw : -(0x04000000 - (int)BlockZRaw); return true; } -- cgit v1.2.3 From 157cad900724f26f7d2f19fae1d7e917510170d8 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 26 Sep 2014 13:04:34 +0200 Subject: Improved searching for spawn. Won't spawn on a small island inside ocean anymore. --- src/World.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/World.cpp b/src/World.cpp index 8664bbec6..60d0ea723 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -681,8 +681,19 @@ void cWorld::GenerateRandomSpawn(void) { LOGD("Generating random spawnpoint..."); - while (IsBlockWaterOrIce(GetBlock((int)m_SpawnX, GetHeight((int)m_SpawnX, (int)m_SpawnZ), (int)m_SpawnZ))) + // Look for a spawn point at most 100 chunks away from map center: + for (int i = 0; i < 100; i++) { + EMCSBiome biome = GetBiomeAt((int)m_SpawnX, (int)m_SpawnZ); + if ( + (biome != biOcean) && (biome != biFrozenOcean) && // The biome is acceptable (don't want a small ocean island) + !IsBlockWaterOrIce(GetBlock((int)m_SpawnX, GetHeight((int)m_SpawnX, (int)m_SpawnZ), (int)m_SpawnZ)) // The terrain is acceptable (don't want to spawn inside a lake / river) + ) + { + // A good spawnpoint was found + break; + } + // Try a neighboring chunk: if ((GetTickRandomNumber(4) % 2) == 0) // Randomise whether to increment X or Z coords { m_SpawnX += cChunkDef::Width; @@ -691,11 +702,11 @@ void cWorld::GenerateRandomSpawn(void) { m_SpawnZ += cChunkDef::Width; } - } + } // for i - 100* m_SpawnY = (double)GetHeight((int)m_SpawnX, (int)m_SpawnZ) + 1.6f; // 1.6f to accomodate player height - LOGD("Generated random spawnpoint %i %i %i", (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ); + LOGINFO("Generated random spawnpoint position {%i, %i, %i}", (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ); } -- cgit v1.2.3 From 749c6092d3bff2cf6c22b6b3299d6883b070b08a Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 26 Sep 2014 14:31:52 +0200 Subject: Added type checking to map loading. --- src/WorldStorage/MapSerializer.cpp | 18 +++++++++--------- src/WorldStorage/MapSerializer.h | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/WorldStorage/MapSerializer.cpp b/src/WorldStorage/MapSerializer.cpp index 012fc52f3..4a913c81a 100644 --- a/src/WorldStorage/MapSerializer.cpp +++ b/src/WorldStorage/MapSerializer.cpp @@ -130,14 +130,14 @@ bool cMapSerializer::LoadMapFromNBT(const cParsedNBT & a_NBT) } int CurrLine = a_NBT.FindChildByName(Data, "scale"); - if (CurrLine >= 0) + if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Byte)) { - unsigned int Scale = a_NBT.GetByte(CurrLine); + unsigned int Scale = (unsigned int)a_NBT.GetByte(CurrLine); m_Map->SetScale(Scale); } CurrLine = a_NBT.FindChildByName(Data, "dimension"); - if (CurrLine >= 0) + if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Byte)) { eDimension Dimension = (eDimension) a_NBT.GetByte(CurrLine); @@ -149,9 +149,9 @@ bool cMapSerializer::LoadMapFromNBT(const cParsedNBT & a_NBT) } CurrLine = a_NBT.FindChildByName(Data, "width"); - if (CurrLine >= 0) + if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Short)) { - unsigned int Width = a_NBT.GetShort(CurrLine); + unsigned int Width = (unsigned int)a_NBT.GetShort(CurrLine); if (Width != 128) { return false; @@ -160,9 +160,9 @@ bool cMapSerializer::LoadMapFromNBT(const cParsedNBT & a_NBT) } CurrLine = a_NBT.FindChildByName(Data, "height"); - if (CurrLine >= 0) + if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Short)) { - unsigned int Height = a_NBT.GetShort(CurrLine); + unsigned int Height = (unsigned int)a_NBT.GetShort(CurrLine); if (Height >= 256) { return false; @@ -171,14 +171,14 @@ bool cMapSerializer::LoadMapFromNBT(const cParsedNBT & a_NBT) } CurrLine = a_NBT.FindChildByName(Data, "xCenter"); - if (CurrLine >= 0) + if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int)) { int CenterX = a_NBT.GetInt(CurrLine); m_Map->m_CenterX = CenterX; } CurrLine = a_NBT.FindChildByName(Data, "zCenter"); - if (CurrLine >= 0) + if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int)) { int CenterZ = a_NBT.GetInt(CurrLine); m_Map->m_CenterZ = CenterZ; diff --git a/src/WorldStorage/MapSerializer.h b/src/WorldStorage/MapSerializer.h index 4fa40f6f9..e13a75c8f 100644 --- a/src/WorldStorage/MapSerializer.h +++ b/src/WorldStorage/MapSerializer.h @@ -28,10 +28,10 @@ public: cMapSerializer(const AString& a_WorldName, cMap * a_Map); - /** Try to load the scoreboard */ + /** Try to load the map */ bool Load(void); - /** Try to save the scoreboard */ + /** Try to save the map */ bool Save(void); -- cgit v1.2.3 From 6ffb7835e7903bb97d747a80d25c8c72887ea11a Mon Sep 17 00:00:00 2001 From: Tycho Date: Fri, 26 Sep 2014 16:26:03 +0100 Subject: Removed a few unnessicary includes --- src/Bindings/DeprecatedBindings.cpp | 5 ----- src/Bindings/LuaChunkStay.cpp | 1 - src/Bindings/LuaChunkStay.h | 1 + src/Bindings/LuaState.h | 1 - src/Bindings/LuaWindow.cpp | 1 - src/Bindings/ManualBindings.cpp | 2 -- src/Bindings/Plugin.h | 14 +++++++++----- src/Bindings/PluginLua.cpp | 4 +++- src/Bindings/PluginManager.cpp | 2 -- src/Bindings/PluginManager.h | 6 +++--- 10 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/Bindings/DeprecatedBindings.cpp b/src/Bindings/DeprecatedBindings.cpp index 36243bc92..02aa15be4 100644 --- a/src/Bindings/DeprecatedBindings.cpp +++ b/src/Bindings/DeprecatedBindings.cpp @@ -5,11 +5,6 @@ #undef TOLUA_TEMPLATE_BIND #include "tolua++/include/tolua++.h" -#include "Plugin.h" -#include "PluginLua.h" -#include "PluginManager.h" -#include "LuaWindow.h" -#include "LuaChunkStay.h" #include "../BlockInfo.h" diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp index 154bcb200..a3d3a8090 100644 --- a/src/Bindings/LuaChunkStay.cpp +++ b/src/Bindings/LuaChunkStay.cpp @@ -6,7 +6,6 @@ #include "Globals.h" #include "LuaChunkStay.h" #include "PluginLua.h" -#include "../World.h" diff --git a/src/Bindings/LuaChunkStay.h b/src/Bindings/LuaChunkStay.h index 49ab9a0ad..d76b67de9 100644 --- a/src/Bindings/LuaChunkStay.h +++ b/src/Bindings/LuaChunkStay.h @@ -18,6 +18,7 @@ // fwd: class cPluginLua; +class cChunkMap; diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 44f187701..094a200e0 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -56,7 +56,6 @@ struct HTTPRequest; class cWebAdmin; struct HTTPTemplateRequest; class cTNTEntity; -class cCreeper; class cHopperEntity; class cBlockEntity; class cBoundingBox; diff --git a/src/Bindings/LuaWindow.cpp b/src/Bindings/LuaWindow.cpp index 1a2582ab0..c4d03b86b 100644 --- a/src/Bindings/LuaWindow.cpp +++ b/src/Bindings/LuaWindow.cpp @@ -6,7 +6,6 @@ #include "LuaWindow.h" #include "../UI/SlotArea.h" #include "PluginLua.h" -#include "../Entities/Player.h" #include "lua/src/lauxlib.h" // Needed for LUA_REFNIL diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index b7ea65759..d8134f159 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -5,7 +5,6 @@ #undef TOLUA_TEMPLATE_BIND #include "tolua++/include/tolua++.h" #include "polarssl/md5.h" -#include "Plugin.h" #include "PluginLua.h" #include "PluginManager.h" #include "LuaWindow.h" @@ -27,7 +26,6 @@ #include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/FlowerPotEntity.h" #include "../LineBlockTracer.h" -#include "../Protocol/Authenticator.h" #include "../WorldStorage/SchematicFileSerializer.h" #include "../CompositeChat.h" diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h index c9a53346d..9c10a1d56 100644 --- a/src/Bindings/Plugin.h +++ b/src/Bindings/Plugin.h @@ -1,23 +1,27 @@ #pragma once -#include "PluginManager.h" +//#include "PluginManager.h" +#include "Defines.h" +class cCommandOutputCallback; +class cItems; +class cHopperEntity; +class cBlockEntityWithItems; class cClientHandle; -class cPlayer; class cPickup; -class cItem; +class cPlayer; +class cProjectileEntity; class cEntity; +class cMonster; class cWorld; class cChunkDesc; struct TakeDamageInfo; -// fwd: cPlayer.h -class cPlayer; // fwd: CraftingRecipes.h class cCraftingGrid; diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index 2c2d05547..2629eb641 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -12,10 +12,12 @@ #endif #include "PluginLua.h" #include "../CommandOutput.h" +#include "PluginManager.h" +#include "../Item.h" extern "C" { - #include "lua/src/lualib.h" + #include "lua/src/lauxlib.h" } #undef TOLUA_TEMPLATE_BIND diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index f62e6ae02..e0faa838a 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -4,12 +4,10 @@ #include "PluginManager.h" #include "Plugin.h" #include "PluginLua.h" -#include "../WebAdmin.h" #include "../Item.h" #include "../Root.h" #include "../Server.h" #include "../CommandOutput.h" -#include "../ChatColor.h" #include "inifile/iniFile.h" #include "../Entities/Player.h" diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h index cef6619d7..fff3bc323 100644 --- a/src/Bindings/PluginManager.h +++ b/src/Bindings/PluginManager.h @@ -1,9 +1,8 @@ #pragma once -#include "../Item.h" - +#include "Defines.h" @@ -36,7 +35,6 @@ class cPickup; // fwd: Pawn.h struct TakeDamageInfo; -class cPawn; // fwd: CommandOutput.h class cCommandOutputCallback; @@ -49,6 +47,8 @@ class cBlockEntityWithItems; +class cItems; + // tolua_begin -- cgit v1.2.3 From d83d6456e8aedf84dcda89eb29d20d8ba834748e Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 26 Sep 2014 17:37:19 +0200 Subject: Fixed players custom name in 1.8 --- src/ClientHandle.cpp | 4 ++-- src/ClientHandle.h | 2 +- src/Entities/Player.cpp | 7 ++++--- src/Protocol/Protocol.h | 2 +- src/Protocol/Protocol125.cpp | 22 ++++------------------ src/Protocol/Protocol125.h | 2 +- src/Protocol/Protocol17x.cpp | 20 ++++---------------- src/Protocol/Protocol17x.h | 2 +- src/Protocol/Protocol18x.cpp | 21 +++++---------------- src/Protocol/Protocol18x.h | 2 +- src/Protocol/ProtocolRecognizer.cpp | 4 ++-- src/Protocol/ProtocolRecognizer.h | 2 +- src/World.cpp | 4 ++-- src/World.h | 2 +- 14 files changed, 30 insertions(+), 66 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 1e2f4ffad..878d309c9 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2453,9 +2453,9 @@ void cClientHandle::SendPlayerListUpdatePing(const cPlayer & a_Player) -void cClientHandle::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +void cClientHandle::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) { - m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_OldListName); + m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_CustomName); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index b91c3722c..0a936a2ca 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -172,7 +172,7 @@ public: void SendPlayerListRemovePlayer (const cPlayer & a_Player); void SendPlayerListUpdateGameMode (const cPlayer & a_Player); void SendPlayerListUpdatePing (const cPlayer & a_Player); - void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName); + 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); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 1bdb752c5..6875506ea 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -816,7 +816,8 @@ void cPlayer::SetCustomName(const AString & a_CustomName) { return; } - AString OldCustomName = m_CustomName; + + m_World->BroadcastPlayerListRemovePlayer(*this); m_CustomName = a_CustomName; if (m_CustomName.length() > 16) @@ -824,8 +825,8 @@ void cPlayer::SetCustomName(const AString & a_CustomName) m_CustomName = m_CustomName.substr(0, 16); } - m_World->BroadcastPlayerListUpdateDisplayName(*this, m_CustomName); - m_World->BroadcastSpawnEntity(*this, m_ClientHandle); + m_World->BroadcastPlayerListAddPlayer(*this); + m_World->BroadcastSpawnEntity(*this, GetClientHandle()); } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index f351ee4b9..b2ee92918 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -98,7 +98,7 @@ public: virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) = 0; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) = 0; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) = 0; - virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) = 0; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) = 0; virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+) virtual void SendPlayerMoveLook (void) = 0; virtual void SendPlayerPosition (void) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index ba4cfa7ef..8a5f26c8b 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -767,25 +767,11 @@ void cProtocol125::SendPlayerListUpdatePing(const cPlayer & a_Player) -void cProtocol125::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +void cProtocol125::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) { - if (a_OldListName == a_Player.GetPlayerListName()) - { - return; - } - - cCSLock Lock(m_CSPacket); - - // Remove the old name from the tablist: - { - WriteByte (PACKET_PLAYER_LIST_ITEM); - WriteString(a_OldListName); - WriteBool (false); - WriteShort (0); - Flush(); - } - - SendPlayerListAddPlayer(a_Player); + // Not implemented in this protocol version + UNUSED(a_Player); + UNUSED(a_CustomName); } diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 4241c1fd4..3ea116c3b 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -69,7 +69,7 @@ public: virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; - virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 73d2a74f9..ce4732471 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -838,23 +838,11 @@ void cProtocol172::SendPlayerListUpdatePing(const cPlayer & a_Player) -void cProtocol172::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +void cProtocol172::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) { - ASSERT(m_State == 3); // In game mode? - if (a_OldListName == a_Player.GetPlayerListName()) - { - return; - } - - // Remove the old name from the tablist: - { - cPacketizer Pkt(*this, 0x38); - Pkt.WriteString(a_OldListName); - Pkt.WriteBool(false); - Pkt.WriteShort(0); - } - - SendPlayerListAddPlayer(a_Player); + // Not implemented in this protocol version + UNUSED(a_Player); + UNUSED(a_CustomName); } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 7ec7d0fce..8f537f5d7 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -105,7 +105,7 @@ public: virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; - virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 896947d03..2ee50bb4a 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -802,7 +802,7 @@ void cProtocol180::SendPlayerListAddPlayer(const cPlayer & a_Player) Pkt.WriteVarInt(0); Pkt.WriteVarInt(1); Pkt.WriteUUID(a_Player.GetUUID()); - Pkt.WriteString(a_Player.GetName()); + Pkt.WriteString(a_Player.GetPlayerListName()); const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties(); Pkt.WriteVarInt(Properties.size()); @@ -824,17 +824,7 @@ void cProtocol180::SendPlayerListAddPlayer(const cPlayer & a_Player) Pkt.WriteVarInt((UInt32)a_Player.GetGameMode()); Pkt.WriteVarInt((UInt32)a_Player.GetClientHandle()->GetPing()); - - AString CustomName = a_Player.GetPlayerListName(); - if (CustomName != a_Player.GetName()) - { - Pkt.WriteBool(true); - Pkt.WriteString(Printf("{\"text\":\"%s\"}", CustomName.c_str())); - } - else - { - Pkt.WriteBool(false); - } + Pkt.WriteBool(false); } @@ -885,7 +875,7 @@ void cProtocol180::SendPlayerListUpdatePing(const cPlayer & a_Player) -void cProtocol180::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +void cProtocol180::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) { ASSERT(m_State == 3); // In game mode? @@ -894,15 +884,14 @@ void cProtocol180::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, con Pkt.WriteVarInt(1); Pkt.WriteUUID(a_Player.GetUUID()); - AString CustomName = a_Player.GetPlayerListName(); - if (CustomName == a_Player.GetName()) + if (a_CustomName.empty()) { Pkt.WriteBool(false); } else { Pkt.WriteBool(true); - Pkt.WriteString(Printf("{\"text\":\"%s\"}", CustomName.c_str())); + Pkt.WriteString(Printf("{\"text\":\"%s\"}", a_CustomName.c_str())); } } diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h index df188b70f..554edecc8 100644 --- a/src/Protocol/Protocol18x.h +++ b/src/Protocol/Protocol18x.h @@ -101,7 +101,7 @@ public: virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; - virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index a5b745c2f..fe53aede1 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -529,10 +529,10 @@ void cProtocolRecognizer::SendPlayerListUpdatePing(const cPlayer & a_Player) -void cProtocolRecognizer::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) +void cProtocolRecognizer::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) { ASSERT(m_Protocol != NULL); - m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_OldListName); + m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_CustomName); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 55348a758..e4419f6ae 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -105,7 +105,7 @@ public: virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing (const cPlayer & a_Player) override; - virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName) override; + virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerMaxSpeed (void) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/World.cpp b/src/World.cpp index 60d0ea723..1f3894978 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2236,7 +2236,7 @@ void cWorld::BroadcastPlayerListUpdatePing(const cPlayer & a_Player, const cClie -void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName, const cClientHandle * a_Exclude) +void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude) { cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) @@ -2246,7 +2246,7 @@ void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, cons { continue; } - ch->SendPlayerListUpdateDisplayName(a_Player, a_OldListName); + ch->SendPlayerListUpdateDisplayName(a_Player, a_CustomName); } } diff --git a/src/World.h b/src/World.h index eee0ced54..76c1d148d 100644 --- a/src/World.h +++ b/src/World.h @@ -244,7 +244,7 @@ public: void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); - void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName, const cClientHandle * a_Exclude = NULL); + void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); -- cgit v1.2.3 From ad5d0eda9c35a7f4a00e11743f545d057d188a8c Mon Sep 17 00:00:00 2001 From: tycho Date: Fri, 26 Sep 2014 17:00:34 +0100 Subject: Fixed issue with casting --- src/Chunk.cpp | 3 +++ src/Chunk.h | 4 ++-- src/Simulator/RedstoneSimulator.h | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index a7dec3fe3..06260bead 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -91,6 +91,7 @@ cChunk::cChunk( m_NeighborZP(a_NeighborZP), m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()), m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()), + m_RedstoneSimulatorData(NULL), m_AlwaysTicked(0) { if (a_NeighborXM != NULL) @@ -159,6 +160,8 @@ cChunk::~cChunk() m_WaterSimulatorData = NULL; delete m_LavaSimulatorData; m_LavaSimulatorData = NULL; + delete m_RedstoneSimulatorData; + m_RedstoneSimulatorData = NULL; } diff --git a/src/Chunk.h b/src/Chunk.h index a3de730dc..7a2e75685 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -416,7 +416,7 @@ public: cFluidSimulatorData * GetLavaSimulatorData (void) { return m_LavaSimulatorData; } cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; } - cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return &m_RedstoneSimulatorData; } + cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return m_RedstoneSimulatorData; } bool IsRedstoneDirty(void) const { return m_IsRedstoneDirty; } void SetIsRedstoneDirty(bool a_Flag) { m_IsRedstoneDirty = a_Flag; } @@ -501,7 +501,7 @@ private: cFluidSimulatorData * m_LavaSimulatorData; cSandSimulatorChunkData m_SandSimulatorData; - cRedstoneSimulatorChunkData m_RedstoneSimulatorData; + cRedstoneSimulatorChunkData * m_RedstoneSimulatorData; /** Indicates if simulate-once blocks should be updated by the redstone simulator */ diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h index 0e3dd495d..f6d36f869 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -7,10 +7,12 @@ class cRedstoneSimulatorChunkData { public: - virtual ~cRedstoneSimulatorChunkData() {} + virtual ~cRedstoneSimulatorChunkData() = 0; } ; +inline cRedstoneSimulatorChunkData::~cRedstoneSimulatorChunkData() {} + template class cRedstoneSimulator : public cSimulator -- cgit v1.2.3 From a3f940f47c8981146feed66225c1dd8066bac0e2 Mon Sep 17 00:00:00 2001 From: Tycho Date: Fri, 26 Sep 2014 18:13:19 +0100 Subject: Removed more unessicary includes --- lib/SQLiteCpp | 2 +- src/Bindings/WebPlugin.cpp | 1 - src/Bindings/WebPlugin.h | 1 - src/BlockEntities/BlockEntity.h | 5 ++--- src/BlockEntities/BlockEntityWithItems.h | 1 + src/BlockEntities/ChestEntity.cpp | 1 - src/BlockEntities/ChestEntity.h | 2 -- src/BlockEntities/CommandBlockEntity.cpp | 6 ++---- src/BlockEntities/DispenserEntity.cpp | 3 --- src/BlockEntities/DropSpenserEntity.cpp | 1 - src/BlockEntities/DropSpenserEntity.h | 1 - src/BlockEntities/DropperEntity.cpp | 2 -- src/BlockEntities/EnderChestEntity.cpp | 1 - src/BlockEntities/EnderChestEntity.h | 1 - src/BlockEntities/FlowerPotEntity.cpp | 1 - src/BlockEntities/FlowerPotEntity.h | 2 +- src/BlockEntities/FurnaceEntity.cpp | 2 -- src/BlockEntities/FurnaceEntity.h | 1 - src/BlockEntities/HopperEntity.cpp | 3 --- src/BlockEntities/JukeboxEntity.cpp | 4 ++-- src/BlockEntities/JukeboxEntity.h | 1 - src/BlockEntities/MobHeadEntity.cpp | 1 - src/BlockEntities/MobHeadEntity.h | 2 +- src/BlockEntities/NoteEntity.cpp | 2 +- src/BlockEntities/SignEntity.cpp | 4 ++-- src/Blocks/BlockBed.cpp | 9 +++++++++ src/Blocks/BlockBed.h | 8 +++++--- src/Blocks/BlockBigFlower.h | 2 +- src/Blocks/BlockDirt.h | 4 ++-- src/Blocks/BlockDoor.cpp | 1 - src/Blocks/BlockDoor.h | 1 + src/Blocks/BlockHandler.cpp | 4 ++-- src/Blocks/BlockHandler.h | 8 ++++---- src/Blocks/BlockPiston.cpp | 1 + src/Blocks/BlockRedstoneRepeater.h | 2 +- src/Blocks/BlockSlab.h | 1 + src/Blocks/BlockVine.h | 2 +- src/Blocks/ChunkInterface.cpp | 1 + src/Blocks/ChunkInterface.h | 3 ++- src/Chunk.cpp | 1 + src/Chunk.h | 6 +++++- src/ChunkMap.cpp | 2 +- src/ChunkSender.cpp | 1 + src/Entities/ArrowEntity.cpp | 1 - src/Entities/EnderCrystal.cpp | 2 +- src/Entities/Entity.cpp | 1 - src/Items/ItemBucket.h | 1 + src/Mobs/Villager.h | 2 +- src/Simulator/FloodyFluidSimulator.cpp | 1 + 49 files changed, 56 insertions(+), 60 deletions(-) diff --git a/lib/SQLiteCpp b/lib/SQLiteCpp index 203c2fb68..55edadd56 160000 --- a/lib/SQLiteCpp +++ b/lib/SQLiteCpp @@ -1 +1 @@ -Subproject commit 203c2fb68bbf871eaf4ca98756a113d74d620dea +Subproject commit 55edadd56d0d6f506954ad00c3b9a5d425814a2f diff --git a/src/Bindings/WebPlugin.cpp b/src/Bindings/WebPlugin.cpp index 4fa64d937..eca1c74e6 100644 --- a/src/Bindings/WebPlugin.cpp +++ b/src/Bindings/WebPlugin.cpp @@ -3,7 +3,6 @@ #include "WebPlugin.h" #include "../WebAdmin.h" -#include "../Server.h" #include "../Root.h" diff --git a/src/Bindings/WebPlugin.h b/src/Bindings/WebPlugin.h index 46bc0cd2d..9b825b918 100644 --- a/src/Bindings/WebPlugin.h +++ b/src/Bindings/WebPlugin.h @@ -1,7 +1,6 @@ #pragma once -struct lua_State; struct HTTPRequest; diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h index 5710f8543..066bbc696 100644 --- a/src/BlockEntities/BlockEntity.h +++ b/src/BlockEntities/BlockEntity.h @@ -1,8 +1,6 @@ #pragma once -#include "../ClientHandle.h" -#include "../World.h" @@ -13,8 +11,9 @@ namespace Json class Value; }; +class cChunk; class cPlayer; -class cPacket; +class cWorld; diff --git a/src/BlockEntities/BlockEntityWithItems.h b/src/BlockEntities/BlockEntityWithItems.h index 5f1639d45..e511ee8cb 100644 --- a/src/BlockEntities/BlockEntityWithItems.h +++ b/src/BlockEntities/BlockEntityWithItems.h @@ -12,6 +12,7 @@ #include "BlockEntity.h" #include "../ItemGrid.h" #include "../UI/WindowOwner.h" +#include "World.h" diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp index 21e1f6ba2..5447c7c49 100644 --- a/src/BlockEntities/ChestEntity.cpp +++ b/src/BlockEntities/ChestEntity.cpp @@ -5,7 +5,6 @@ #include "../Item.h" #include "../Entities/Player.h" #include "../UI/Window.h" -#include "json/json.h" diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h index cd06b3e2c..fa36e08be 100644 --- a/src/BlockEntities/ChestEntity.h +++ b/src/BlockEntities/ChestEntity.h @@ -13,8 +13,6 @@ namespace Json }; class cClientHandle; -class cServer; -class cNBTData; diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index 20702a9ac..318874a9b 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -4,16 +4,14 @@ // Implements the cCommandBlockEntity class representing a single command block in the world #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules -#include "json/json.h" #include "CommandBlockEntity.h" -#include "../Entities/Player.h" -#include "../WorldStorage/FastNBT.h" #include "../CommandOutput.h" #include "../Root.h" #include "../Server.h" // ExecuteConsoleCommand() -#include "../Chunk.h" #include "../ChatColor.h" +#include "../World.h" +#include "../ClientHandle.h" diff --git a/src/BlockEntities/DispenserEntity.cpp b/src/BlockEntities/DispenserEntity.cpp index 068891d66..4794375cf 100644 --- a/src/BlockEntities/DispenserEntity.cpp +++ b/src/BlockEntities/DispenserEntity.cpp @@ -2,13 +2,10 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "DispenserEntity.h" -#include "../Entities/Player.h" #include "../Simulator/FluidSimulator.h" #include "../Chunk.h" #include "../World.h" -#include "../Entities/ArrowEntity.h" -#include "../Entities/FireChargeEntity.h" #include "../Entities/ProjectileEntity.h" diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp index dc38e3e9b..260c71641 100644 --- a/src/BlockEntities/DropSpenserEntity.cpp +++ b/src/BlockEntities/DropSpenserEntity.cpp @@ -8,7 +8,6 @@ #include "DropSpenserEntity.h" #include "../Entities/Player.h" #include "../Chunk.h" -#include "json/json.h" diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h index be56447aa..c70cd0531 100644 --- a/src/BlockEntities/DropSpenserEntity.h +++ b/src/BlockEntities/DropSpenserEntity.h @@ -22,7 +22,6 @@ namespace Json } class cClientHandle; -class cServer; diff --git a/src/BlockEntities/DropperEntity.cpp b/src/BlockEntities/DropperEntity.cpp index 5d4a8ad97..5cbf6d56e 100644 --- a/src/BlockEntities/DropperEntity.cpp +++ b/src/BlockEntities/DropperEntity.cpp @@ -5,8 +5,6 @@ #include "Globals.h" #include "DropperEntity.h" -#include "../Entities/Player.h" -#include "../Simulator/FluidSimulator.h" diff --git a/src/BlockEntities/EnderChestEntity.cpp b/src/BlockEntities/EnderChestEntity.cpp index 17816d63e..b870f9e50 100644 --- a/src/BlockEntities/EnderChestEntity.cpp +++ b/src/BlockEntities/EnderChestEntity.cpp @@ -5,7 +5,6 @@ #include "../Item.h" #include "../Entities/Player.h" #include "../UI/Window.h" -#include "json/json.h" diff --git a/src/BlockEntities/EnderChestEntity.h b/src/BlockEntities/EnderChestEntity.h index ed178f6fc..311af8d76 100644 --- a/src/BlockEntities/EnderChestEntity.h +++ b/src/BlockEntities/EnderChestEntity.h @@ -3,7 +3,6 @@ #include "BlockEntity.h" #include "UI/WindowOwner.h" -#include "json/json.h" diff --git a/src/BlockEntities/FlowerPotEntity.cpp b/src/BlockEntities/FlowerPotEntity.cpp index e001634b8..d2bc59d34 100644 --- a/src/BlockEntities/FlowerPotEntity.cpp +++ b/src/BlockEntities/FlowerPotEntity.cpp @@ -4,7 +4,6 @@ // 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" #include "FlowerPotEntity.h" #include "../Entities/Player.h" #include "../Item.h" diff --git a/src/BlockEntities/FlowerPotEntity.h b/src/BlockEntities/FlowerPotEntity.h index 89901cf2d..b86f9c840 100644 --- a/src/BlockEntities/FlowerPotEntity.h +++ b/src/BlockEntities/FlowerPotEntity.h @@ -9,8 +9,8 @@ #pragma once #include "BlockEntity.h" +#include "Item.h" -class cItem; diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp index 72fd7f2b3..d7b2fd910 100644 --- a/src/BlockEntities/FurnaceEntity.cpp +++ b/src/BlockEntities/FurnaceEntity.cpp @@ -5,8 +5,6 @@ #include "../UI/Window.h" #include "../Entities/Player.h" #include "../Root.h" -#include "../Chunk.h" -#include "json/json.h" diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h index cf1a755e0..7ac25cf52 100644 --- a/src/BlockEntities/FurnaceEntity.h +++ b/src/BlockEntities/FurnaceEntity.h @@ -14,7 +14,6 @@ namespace Json } class cClientHandle; -class cServer; diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index 88e7b8e1b..444378c92 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -10,10 +10,7 @@ #include "../Entities/Pickup.h" #include "../Bindings/PluginManager.h" #include "ChestEntity.h" -#include "DropSpenserEntity.h" #include "FurnaceEntity.h" -#include "../BoundingBox.h" -#include "json/json.h" diff --git a/src/BlockEntities/JukeboxEntity.cpp b/src/BlockEntities/JukeboxEntity.cpp index c96253b11..1131b99b0 100644 --- a/src/BlockEntities/JukeboxEntity.cpp +++ b/src/BlockEntities/JukeboxEntity.cpp @@ -3,8 +3,8 @@ #include "JukeboxEntity.h" #include "../World.h" -#include "json/json.h" - +#include "json/value.h" +#include "Entities/Player.h" diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h index d677d340f..a6fdf3c7e 100644 --- a/src/BlockEntities/JukeboxEntity.h +++ b/src/BlockEntities/JukeboxEntity.h @@ -2,7 +2,6 @@ #pragma once #include "BlockEntity.h" -#include "../Entities/Player.h" diff --git a/src/BlockEntities/MobHeadEntity.cpp b/src/BlockEntities/MobHeadEntity.cpp index ce895eb6f..9a1a40abe 100644 --- a/src/BlockEntities/MobHeadEntity.cpp +++ b/src/BlockEntities/MobHeadEntity.cpp @@ -4,7 +4,6 @@ // Implements the cMobHeadEntity class representing a single skull/head in the world #include "Globals.h" -#include "json/json.h" #include "MobHeadEntity.h" #include "../Entities/Player.h" diff --git a/src/BlockEntities/MobHeadEntity.h b/src/BlockEntities/MobHeadEntity.h index f91a3cc9e..45fa0d951 100644 --- a/src/BlockEntities/MobHeadEntity.h +++ b/src/BlockEntities/MobHeadEntity.h @@ -9,7 +9,7 @@ #pragma once #include "BlockEntity.h" - +#include "Defines.h" diff --git a/src/BlockEntities/NoteEntity.cpp b/src/BlockEntities/NoteEntity.cpp index 95145c117..ecbedbcb1 100644 --- a/src/BlockEntities/NoteEntity.cpp +++ b/src/BlockEntities/NoteEntity.cpp @@ -3,7 +3,7 @@ #include "NoteEntity.h" #include "../World.h" -#include "json/json.h" +#include "json/value.h" diff --git a/src/BlockEntities/SignEntity.cpp b/src/BlockEntities/SignEntity.cpp index 23d9ef926..423d254d2 100644 --- a/src/BlockEntities/SignEntity.cpp +++ b/src/BlockEntities/SignEntity.cpp @@ -4,9 +4,9 @@ // Implements the cSignEntity class representing a single sign in the world #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules -#include "json/json.h" +#include "json/value.h" #include "SignEntity.h" -#include "../Entities/Player.h" +#include "../ClientHandle.h" diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index cd1cc2a5f..3b6328b38 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -4,6 +4,15 @@ +#include "BroadcastInterface.h" +#include "ChunkInterface.h" +#include "Entities/../World.h" +#include "Entities/Player.h" +#include "WorldInterface.h" + + + + void cBlockBedHandler::OnPlacedByPlayer( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h index bf9d9c01d..9fd45644b 100644 --- a/src/Blocks/BlockBed.h +++ b/src/Blocks/BlockBed.h @@ -2,12 +2,14 @@ #pragma once #include "BlockHandler.h" -#include "ChunkInterface.h" -#include "WorldInterface.h" #include "MetaRotator.h" -#include "../Entities/Player.h" +#include "Item.h" +class cChunkInterface; +class cPlayer; +class cWorldInterface; + diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h index 89ffc864d..3577bdd40 100644 --- a/src/Blocks/BlockBigFlower.h +++ b/src/Blocks/BlockBigFlower.h @@ -2,7 +2,7 @@ #pragma once #include "BlockHandler.h" - +#include "ChunkInterface.h" diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h index 23e5a3cde..60d81db72 100644 --- a/src/Blocks/BlockDirt.h +++ b/src/Blocks/BlockDirt.h @@ -3,8 +3,8 @@ #include "BlockHandler.h" #include "../FastRandom.h" - - +#include "Root.h" +#include "Bindings/PluginManager.h" diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp index 1a277f071..96345a2df 100644 --- a/src/Blocks/BlockDoor.cpp +++ b/src/Blocks/BlockDoor.cpp @@ -1,7 +1,6 @@ #include "Globals.h" #include "BlockDoor.h" -#include "../Item.h" #include "../Entities/Player.h" diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h index 69e30d9c8..b2f9e4dcd 100644 --- a/src/Blocks/BlockDoor.h +++ b/src/Blocks/BlockDoor.h @@ -5,6 +5,7 @@ #include "../Entities/Player.h" #include "Chunk.h" #include "MetaRotator.h" +#include "ChunkInterface.h" diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 30b303cfd..3e7de123c 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -3,8 +3,6 @@ #include "BlockHandler.h" #include "../Item.h" #include "../World.h" -#include "../Root.h" -#include "../Bindings/PluginManager.h" #include "../Chunk.h" #include "BlockAnvil.h" #include "BlockBed.h" @@ -84,6 +82,8 @@ #include "BlockWorkbench.h" +#include "BlockPluginInterface.h" + diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h index 3a8115da0..83de836cb 100644 --- a/src/Blocks/BlockHandler.h +++ b/src/Blocks/BlockHandler.h @@ -2,10 +2,6 @@ #pragma once #include "../Defines.h" -#include "../Item.h" -#include "WorldInterface.h" -#include "ChunkInterface.h" -#include "BlockPluginInterface.h" @@ -14,6 +10,10 @@ // fwd: class cPlayer; class cChunk; +class cBlockPluginInterface; +class cChunkInterface; +class cWorldInterface; +class cItems; diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp index 0169fb266..34d11f675 100644 --- a/src/Blocks/BlockPiston.cpp +++ b/src/Blocks/BlockPiston.cpp @@ -5,6 +5,7 @@ #include "../World.h" #include "../Entities/Player.h" #include "BlockInServerPluginInterface.h" +#include "ChunkInterface.h" diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h index 3e5259c56..1eb67f714 100644 --- a/src/Blocks/BlockRedstoneRepeater.h +++ b/src/Blocks/BlockRedstoneRepeater.h @@ -4,7 +4,7 @@ #include "BlockHandler.h" #include "Chunk.h" #include "MetaRotator.h" - +#include "ChunkInterface.h" diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h index 0ad30bb2b..fb92db8fe 100644 --- a/src/Blocks/BlockSlab.h +++ b/src/Blocks/BlockSlab.h @@ -12,6 +12,7 @@ #include "BlockHandler.h" #include "../Items/ItemHandler.h" #include "Root.h" +#include "ChunkInterface.h" diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h index b61673cc5..06d84f2d4 100644 --- a/src/Blocks/BlockVine.h +++ b/src/Blocks/BlockVine.h @@ -2,7 +2,7 @@ #include "BlockHandler.h" #include "MetaRotator.h" - +#include "Bindings/PluginManager.h" diff --git a/src/Blocks/ChunkInterface.cpp b/src/Blocks/ChunkInterface.cpp index 5ac4dcf80..e22a1410e 100644 --- a/src/Blocks/ChunkInterface.cpp +++ b/src/Blocks/ChunkInterface.cpp @@ -4,6 +4,7 @@ #include "ChunkInterface.h" #include "ChunkMap.h" #include "BlockHandler.h" +#include "WorldInterface.h" diff --git a/src/Blocks/ChunkInterface.h b/src/Blocks/ChunkInterface.h index 51647dc04..2f0cfea11 100644 --- a/src/Blocks/ChunkInterface.h +++ b/src/Blocks/ChunkInterface.h @@ -2,11 +2,12 @@ #pragma once #include "../ForEachChunkProvider.h" -#include "WorldInterface.h" class cChunkMap; +class cWorldInterface; +class cPlayer; class cChunkInterface: public cForEachChunkProvider diff --git a/src/Chunk.cpp b/src/Chunk.cpp index a7dec3fe3..74e18de17 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -38,6 +38,7 @@ #include "BlockInServerPluginInterface.h" #include "SetChunkData.h" #include "BoundingBox.h" +#include "Blocks/ChunkInterface.h" #include "json/json.h" diff --git a/src/Chunk.h b/src/Chunk.h index a3de730dc..1d62ff73f 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -11,7 +11,7 @@ #include "Blocks/GetHandlerCompileTimeTemplate.h" - +#include "ChunkMap.h" @@ -31,7 +31,10 @@ class MTRand; class cPlayer; class cChunkMap; class cBeaconEntity; +class cBoundingBox; class cChestEntity; +class cCHunkDataCallback; +class cCommandBlockEntity; class cDispenserEntity; class cFurnaceEntity; class cNoteEntity; @@ -46,6 +49,7 @@ class cFluidSimulatorData; class cMobCensus; class cMobSpawner; class cRedstonePoweredEntity; +class cSetChunkData; typedef std::list cClientHandleList; typedef cItemCallback cEntityCallback; diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 828d8f164..38a7d9bd4 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -17,7 +17,7 @@ #include "MobSpawner.h" #include "BoundingBox.h" #include "SetChunkData.h" - +#include "Blocks/ChunkInterface.h" #include "Entities/Pickup.h" #ifndef _WIN32 diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp index 95c4d03d2..a3151eb3f 100644 --- a/src/ChunkSender.cpp +++ b/src/ChunkSender.cpp @@ -12,6 +12,7 @@ #include "World.h" #include "BlockEntities/BlockEntity.h" #include "Protocol/ChunkDataSerializer.h" +#include "ClientHandle.h" diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp index 954e0a267..c265c5043 100644 --- a/src/Entities/ArrowEntity.cpp +++ b/src/Entities/ArrowEntity.cpp @@ -3,7 +3,6 @@ #include "Player.h" #include "ArrowEntity.h" #include "../Chunk.h" -#include "FastRandom.h" diff --git a/src/Entities/EnderCrystal.cpp b/src/Entities/EnderCrystal.cpp index c17bb608e..30df2c110 100644 --- a/src/Entities/EnderCrystal.cpp +++ b/src/Entities/EnderCrystal.cpp @@ -3,8 +3,8 @@ #include "EnderCrystal.h" #include "ClientHandle.h" -#include "Player.h" #include "../Chunk.h" +#include "../World.h" diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index c733d60ad..da85dec50 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -3,7 +3,6 @@ #include "Entity.h" #include "../World.h" -#include "../Server.h" #include "../Root.h" #include "../Matrix4.h" #include "../ClientHandle.h" diff --git a/src/Items/ItemBucket.h b/src/Items/ItemBucket.h index a17c4838b..3a533958f 100644 --- a/src/Items/ItemBucket.h +++ b/src/Items/ItemBucket.h @@ -7,6 +7,7 @@ #include "../Blocks/BlockHandler.h" #include "../LineBlockTracer.h" #include "../BlockInServerPluginInterface.h" +#include "../Blocks/ChunkInterface.h" diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index aa81f0790..d3a38dbf0 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -2,7 +2,7 @@ #pragma once #include "PassiveMonster.h" - +#include "Blocks/ChunkInterface.h" diff --git a/src/Simulator/FloodyFluidSimulator.cpp b/src/Simulator/FloodyFluidSimulator.cpp index 2c5c4b658..b839aa746 100644 --- a/src/Simulator/FloodyFluidSimulator.cpp +++ b/src/Simulator/FloodyFluidSimulator.cpp @@ -12,6 +12,7 @@ #include "../BlockArea.h" #include "../Blocks/BlockHandler.h" #include "../BlockInServerPluginInterface.h" +#include "../Blocks/ChunkInterface.h" -- cgit v1.2.3 From 4105be0bec76a7643c6527de46411f980a0a9e50 Mon Sep 17 00:00:00 2001 From: Masy98 Date: Fri, 26 Sep 2014 19:44:06 +0200 Subject: Re-added 1.8 blocks to the redstone simulator --- src/Simulator/IncrementalRedstoneSimulator.inc | 55 +++++++++++++++++++++----- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.inc b/src/Simulator/IncrementalRedstoneSimulator.inc index 3fa973463..6fda9824c 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.inc +++ b/src/Simulator/IncrementalRedstoneSimulator.inc @@ -220,25 +220,36 @@ private: { switch (Block) { + case E_BLOCK_ACACIA_DOOR: + case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_BIRCH_DOOR: + case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_COMMAND_BLOCK: - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: + case E_BLOCK_DARK_OAK_DOOR: + case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_FENCE_GATE: case E_BLOCK_HOPPER: + case E_BLOCK_IRON_DOOR: + case E_BLOCK_IRON_TRAPDOOR: + case E_BLOCK_JUNGLE_DOOR: + case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_NOTE_BLOCK: - case E_BLOCK_TNT: - case E_BLOCK_TRAPDOOR: + case E_BLOCK_PISTON: + case E_BLOCK_POWERED_RAIL: case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: - case E_BLOCK_WOODEN_DOOR: - case E_BLOCK_IRON_DOOR: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_POWERED_RAIL: case E_BLOCK_REDSTONE_WIRE: + case E_BLOCK_SPRUCE_DOOR: + case E_BLOCK_SPRUCE_FENCE_GATE: + case E_BLOCK_STICKY_PISTON: + case E_BLOCK_TNT: + case E_BLOCK_TRAPDOOR: + case E_BLOCK_WOODEN_DOOR: { return true; } @@ -279,19 +290,28 @@ private: switch (Block) { // All redstone devices, please alpha sort + case E_BLOCK_ACACIA_DOOR: + case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_ACTIVE_COMPARATOR: + case E_BLOCK_BIRCH_DOOR: + case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_COMMAND_BLOCK: + case E_BLOCK_DARK_OAK_DOOR: + case E_BLOCK_DARK_OAK_FENCE_GATE: + case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DISPENSER: - case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DROPPER: case E_BLOCK_FENCE_GATE: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HOPPER: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_IRON_DOOR: + case E_BLOCK_IRON_TRAPDOOR: + case E_BLOCK_JUNGLE_DOOR: + case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_NOTE_BLOCK: @@ -303,6 +323,8 @@ private: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: + case E_BLOCK_SPRUCE_DOOR: + case E_BLOCK_SPRUCE_FENCE_GATE: case E_BLOCK_STICKY_PISTON: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: @@ -595,8 +617,8 @@ void cIncrementalRedstoneSimulatorx, dataitr->y, dataitr->z); break; case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break; @@ -607,12 +629,27 @@ void cIncrementalRedstoneSimulatorx, dataitr->y, dataitr->z, dataitr->Data); break; } + case E_BLOCK_ACACIA_DOOR: + case E_BLOCK_BIRCH_DOOR: + case E_BLOCK_DARK_OAK_DOOR: + case E_BLOCK_JUNGLE_DOOR: + case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_WOODEN_DOOR: case E_BLOCK_IRON_DOOR: { HandleDoor(dataitr->x, dataitr->y, dataitr->z); break; } + case E_BLOCK_ACACIA_FENCE_GATE: + case E_BLOCK_BIRCH_FENCE_GATE: + case E_BLOCK_DARK_OAK_FENCE_GATE: + case E_BLOCK_FENCE_GATE: + case E_BLOCK_JUNGLE_FENCE_GATE: + case E_BLOCK_SPRUCE_FENCE_GATE: + { + HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); + break; + } case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: { -- cgit v1.2.3 From 9106a8c29bb07e73e223336e49ee9f3f1366b01a Mon Sep 17 00:00:00 2001 From: Masy98 Date: Fri, 26 Sep 2014 19:45:03 +0200 Subject: Moved curly brace to seperate line --- src/Items/ItemDoor.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Items/ItemDoor.h b/src/Items/ItemDoor.h index 402cef6c6..cd5baf44f 100644 --- a/src/Items/ItemDoor.h +++ b/src/Items/ItemDoor.h @@ -30,7 +30,8 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - switch (m_ItemType) { + switch (m_ItemType) + { case E_ITEM_WOODEN_DOOR: a_BlockType = E_BLOCK_WOODEN_DOOR; break; case E_ITEM_IRON_DOOR: a_BlockType = E_BLOCK_IRON_DOOR; break; case E_ITEM_SPRUCE_DOOR: a_BlockType = E_BLOCK_SPRUCE_DOOR; break; -- cgit v1.2.3 From 02db79d7251adb95ae84971674e68b9a2ff703ab Mon Sep 17 00:00:00 2001 From: worktycho Date: Fri, 26 Sep 2014 19:00:26 +0100 Subject: Update Plugin.h --- src/Bindings/Plugin.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h index 9c10a1d56..fb22dd33e 100644 --- a/src/Bindings/Plugin.h +++ b/src/Bindings/Plugin.h @@ -1,8 +1,6 @@ #pragma once -//#include "PluginManager.h" - #include "Defines.h" class cCommandOutputCallback; -- cgit v1.2.3 From a817243e3fc0115da3fc499ae108b4cdc9dd0a4e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 26 Sep 2014 21:42:55 +0100 Subject: Updated Core --- MCServer/Plugins/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core index bd23915df..9de860603 160000 --- a/MCServer/Plugins/Core +++ b/MCServer/Plugins/Core @@ -1 +1 @@ -Subproject commit bd23915df763b182610c6163c5ff2d64a0756560 +Subproject commit 9de86060388b515642c55d58b44b4281285efc00 -- cgit v1.2.3 From 0d83477540d9eb62c7a4f22f1f5f2b8cd79363ac Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 26 Sep 2014 22:53:11 +0200 Subject: Fixed UNUSED macro so that it doesn't require type knowledge. Introduced new UNUSED_VAR macro that is used when type knowledge is available (for local variables). --- src/Globals.h | 11 ++++++++++- src/WorldStorage/FastNBT.h | 8 ++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Globals.h b/src/Globals.h index c75c4e99b..0926457da 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -162,8 +162,17 @@ template class SizeChecker; TypeName(const TypeName &); \ void operator =(const TypeName &) +// A macro that is used to mark unused local variables, to avoid pedantic warnings in gcc / clang / MSVC +// Note that in MSVC it requires the full type of X to be known +#define UNUSED_VAR(X) (void)(X) + // A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc -#define UNUSED(X) (void)(X) +// Written so that the full type of param needn't be known +#ifdef _MSC_VER + #define UNUSED(X) +#else + #define UNUSED UNUSED_VAR +#endif diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h index ebf99103f..c6225eacf 100644 --- a/src/WorldStorage/FastNBT.h +++ b/src/WorldStorage/FastNBT.h @@ -213,8 +213,8 @@ public: // If your platform produces a compiler error here, you'll need to add code that manually decodes 32-bit floats char Check1[5 - sizeof(float)]; // Fails if sizeof(float) > 4 char Check2[sizeof(float) - 3]; // Fails if sizeof(float) < 4 - UNUSED(Check1); - UNUSED(Check2); + UNUSED_VAR(Check1); + UNUSED_VAR(Check2); Int32 i = GetBEInt(m_Data + m_Tags[(size_t)a_Tag].m_DataStart); float f; @@ -229,8 +229,8 @@ public: // If your platform produces a compiler error here, you'll need to add code that manually decodes 64-bit doubles char Check1[9 - sizeof(double)]; // Fails if sizeof(double) > 8 char Check2[sizeof(double) - 7]; // Fails if sizeof(double) < 8 - UNUSED(Check1); - UNUSED(Check2); + UNUSED_VAR(Check1); + UNUSED_VAR(Check2); ASSERT(m_Tags[(size_t)a_Tag].m_Type == TAG_Double); return NetworkToHostDouble8(m_Data + m_Tags[(size_t)a_Tag].m_DataStart); -- cgit v1.2.3