diff --git a/Minecraft.Client/Common/UI/UIControl_BeaconEffectButton.cpp b/Minecraft.Client/Common/UI/UIControl_BeaconEffectButton.cpp index 7ee79307..98aa4d96 100644 --- a/Minecraft.Client/Common/UI/UIControl_BeaconEffectButton.cpp +++ b/Minecraft.Client/Common/UI/UIControl_BeaconEffectButton.cpp @@ -9,6 +9,7 @@ UIControl_BeaconEffectButton::UIControl_BeaconEffectButton() m_selected = false; m_active = false; m_focus = false; + m_lastState = eState_Disabled; } bool UIControl_BeaconEffectButton::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) diff --git a/Minecraft.Client/PlayerConnection.cpp b/Minecraft.Client/PlayerConnection.cpp index c43489b8..a436c187 100644 --- a/Minecraft.Client/PlayerConnection.cpp +++ b/Minecraft.Client/PlayerConnection.cpp @@ -2132,12 +2132,21 @@ void PlayerConnection::handleCustomPayload(shared_ptr custo BeaconMenu *beaconMenu = static_cast(player->containerMenu); Slot *slot = beaconMenu->getSlot(0); - if (slot->hasItem()) + if (slot != nullptr && slot->hasItem()) { - slot->remove(1); shared_ptr beacon = beaconMenu->getBeacon(); + int prevPrimary = beacon->getPrimaryPower(); + int prevSecondary = beacon->getSecondaryPower(); + beacon->setPrimaryPower(primary); beacon->setSecondaryPower(secondary); + + // Only consume the payment item if the powers actually changed + if (beacon->getPrimaryPower() != prevPrimary || beacon->getSecondaryPower() != prevSecondary) + { + slot->remove(1); + } + beacon->setChanged(); } } diff --git a/Minecraft.Client/ServerPlayer.cpp b/Minecraft.Client/ServerPlayer.cpp index eab1a380..bbf08ef4 100644 --- a/Minecraft.Client/ServerPlayer.cpp +++ b/Minecraft.Client/ServerPlayer.cpp @@ -1431,7 +1431,6 @@ bool ServerPlayer::openBeacon(shared_ptr beacon) nextContainerCounter(); containerMenu = new BeaconMenu(inventory, beacon); containerMenu->containerId = containerCounter; - containerMenu->addSlotListener(this); #if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD) if (FourKitBridge::FireInventoryOpen(entityId, ContainerOpenPacket::BEACON, beacon->getCustomName(), beacon->getContainerSize())) { @@ -1439,7 +1438,10 @@ bool ServerPlayer::openBeacon(shared_ptr beacon) return true; } #endif + // Send the open packet BEFORE addSlotListener so the client has the + // menu ready when the beacon data (levels, powers) arrives. connection->send(std::make_shared(containerCounter, ContainerOpenPacket::BEACON, beacon->getCustomName(), beacon->getContainerSize(), beacon->hasCustomName())); + containerMenu->addSlotListener(this); refreshContainer(containerMenu); } else diff --git a/Minecraft.World/BeaconMenu.cpp b/Minecraft.World/BeaconMenu.cpp index 0d7e54b4..f88ded24 100644 --- a/Minecraft.World/BeaconMenu.cpp +++ b/Minecraft.World/BeaconMenu.cpp @@ -39,6 +39,29 @@ void BeaconMenu::addSlotListener(ContainerListener *listener) listener->setContainerData(this, 2, secondaryPower); } +void BeaconMenu::broadcastChanges() +{ + AbstractContainerMenu::broadcastChanges(); + + int currentLevels = beacon->getLevels(); + int currentPrimary = beacon->getPrimaryPower(); + int currentSecondary = beacon->getSecondaryPower(); + + for (auto& listener : containerListeners) + { + if (levels != currentLevels) + listener->setContainerData(this, 0, currentLevels); + if (primaryPower != currentPrimary) + listener->setContainerData(this, 1, currentPrimary); + if (secondaryPower != currentSecondary) + listener->setContainerData(this, 2, currentSecondary); + } + + levels = currentLevels; + primaryPower = currentPrimary; + secondaryPower = currentSecondary; +} + void BeaconMenu::setData(int id, int value) { if (id == 0) beacon->setLevels(value); diff --git a/Minecraft.World/BeaconMenu.h b/Minecraft.World/BeaconMenu.h index 9394d83f..f9f1a02b 100644 --- a/Minecraft.World/BeaconMenu.h +++ b/Minecraft.World/BeaconMenu.h @@ -36,7 +36,8 @@ private: public: BeaconMenu(shared_ptr inventory, shared_ptr beacon); - void addSlotListener(ContainerListener *listener); + void addSlotListener(ContainerListener *listener) override; + void broadcastChanges() override; void setData(int id, int value); shared_ptr getBeacon(); bool stillValid(shared_ptr player);