osb/source/frontend/StarContainerInterface.cpp
Kai Blaschke 431a9c00a5
Fixed a huge amount of Clang warnings
On Linux and macOS, using Clang to compile OpenStarbound produces about 400 MB worth of warnings during the build, making the compiler output unreadable and slowing the build down considerably.

99% of the warnings were unqualified uses of std::move and std::forward, which are now all properly qualified.

Fixed a few other minor warnings about non-virtual destructors and some uses of std::move preventing copy elision on temporary objects.

Most remaining warnings are now unused parameters.
2024-02-19 16:55:19 +01:00

304 lines
10 KiB
C++

#include "StarContainerInterface.hpp"
#include "StarCasting.hpp"
#include "StarContainerEntity.hpp"
#include "StarWorldClient.hpp"
#include "StarRoot.hpp"
#include "StarItemTooltip.hpp"
#include "StarItemGridWidget.hpp"
#include "StarLabelWidget.hpp"
#include "StarImageWidget.hpp"
#include "StarPaneManager.hpp"
#include "StarFuelWidget.hpp"
#include "StarPlayer.hpp"
#include "StarItemDatabase.hpp"
#include "StarObject.hpp"
#include "StarPlayerInventory.hpp"
#include "StarConfigLuaBindings.hpp"
#include "StarPlayerLuaBindings.hpp"
#include "StarStatusControllerLuaBindings.hpp"
#include "StarWidgetLuaBindings.hpp"
#include "StarAugmentItem.hpp"
namespace Star {
ContainerPane::ContainerPane(WorldClientPtr worldClient, PlayerPtr player, ContainerInteractorPtr containerInteractor) {
m_worldClient = worldClient;
m_player = player;
m_containerInteractor = std::move(containerInteractor);
auto container = m_containerInteractor->openContainer();
auto guiConfig = container->containerGuiConfig();
if (auto scripts = guiConfig.opt("scripts").apply(jsonToStringList)) {
if (!m_script) {
m_script.emplace();
m_script->setScripts(*scripts);
}
m_script->addCallbacks("widget", LuaBindings::makeWidgetCallbacks(this));
m_script->addCallbacks("config", LuaBindings::makeConfigCallbacks( [guiConfig](String const& name, Json const& def) {
return guiConfig.query(name, def);
}));
m_script->addCallbacks("player", LuaBindings::makePlayerCallbacks(m_player.get()));
m_script->addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_player->statusController()));
LuaCallbacks containerPaneCallbacks;
containerPaneCallbacks.registerCallback("containerEntityId", [this]() -> Maybe<EntityId> {
return m_containerInteractor->openContainerId();
});
containerPaneCallbacks.registerCallback("playerEntityId", [this]() { return m_player->entityId(); });
containerPaneCallbacks.registerCallback("dismiss", [this]() { dismiss(); });
m_script->addCallbacks("pane", containerPaneCallbacks);
m_script->setUpdateDelta(guiConfig.getUInt("scriptDelta", 1));
}
auto rightClickCallback = [this](size_t index) {
if (m_expectingSwap != ExpectingSwap::None)
return;
if (ItemPtr slotItem = m_containerInteractor->openContainer()->itemBag()->at(index)) {
auto swapItem = m_player->inventory()->swapSlotItem();
if (!swapItem || swapItem->empty() || swapItem->couldStack(slotItem)) {
size_t count = swapItem ? swapItem->couldStack(slotItem) : slotItem->maxStack();
if (context()->shiftHeld())
count = max(1, min<int>(count, slotItem->count() / 2));
else
count = 1;
m_containerInteractor->takeFromContainerSlot(index, count);
m_expectingSwap = ExpectingSwap::SwapSlotStack;
} else if (is<AugmentItem>(swapItem)) {
m_containerInteractor->applyAugmentInContainer(index, swapItem);
m_player->inventory()->setSwapSlotItem({});
m_expectingSwap = ExpectingSwap::SwapSlot;
}
}
};
m_reader.registerCallback("close", [this](Widget*) { dismiss(); });
m_reader.registerCallback("itemGrid", [=](Widget* paneObj) {
if (auto itemGrid = as<ItemGridWidget>(paneObj))
swapSlot(itemGrid);
else
throw GuiException("Invalid object type, expected ItemGridWidget.");
});
m_reader.registerCallback("itemGrid.right", [=](Widget* paneObj) {
if (auto itemGrid = as<ItemGridWidget>(paneObj))
rightClickCallback(itemGrid->selectedIndex());
else
throw GuiException("Invalid object type, expected ItemGridWidget.");
});
m_reader.registerCallback("itemGrid2", [=](Widget* paneObj) {
if (auto itemGrid = as<ItemGridWidget>(paneObj))
swapSlot(itemGrid);
else
throw GuiException("Invalid object type, expected ItemGridWidget.");
});
m_reader.registerCallback("itemGrid2.right", [=](Widget* paneObj) {
if (auto itemGrid = as<ItemGridWidget>(paneObj))
rightClickCallback(itemGrid->selectedIndex());
else
throw GuiException("Invalid object type, expected ItemGridWidget.");
});
m_reader.registerCallback("outputItemGrid", [=](Widget* paneObj) {
if (auto itemGrid = as<ItemGridWidget>(paneObj))
swapSlot(itemGrid);
else
throw GuiException("Invalid object type, expected ItemGridWidget.");
});
m_reader.registerCallback("outputItemGrid.right", [=](Widget* paneObj) {
if (auto itemGrid = as<ItemGridWidget>(paneObj))
rightClickCallback(itemGrid->selectedIndex());
else
throw GuiException("Invalid object type, expected ItemGridWidget.");
});
m_reader.registerCallback("toggleCrafting", [=](Widget*) { toggleCrafting(); });
m_reader.registerCallback("clear", [=](Widget*) { clear(); });
m_reader.registerCallback("burn", [=](Widget*) { burn(); });
for (auto const& callbackName : jsonToStringList(guiConfig.get("scriptWidgetCallbacks", JsonArray{}))) {
m_reader.registerCallback(callbackName, [this, callbackName](Widget* widget) {
m_script->invoke(callbackName, widget->name(), widget->data());
});
}
m_reader.construct(guiConfig.get("gui"), this);
if (auto countWidget = fetchChild<LabelWidget>("count"))
countWidget->setText(countWidget->text().replace("<slots>", toString(container->containerSize())));
m_itemBag = make_shared<ItemBag>(container->containerSize());
auto items = container->containerItems();
fetchChild<ItemGridWidget>("itemGrid")->setItemBag(m_itemBag);
if (containsChild("itemGrid2"))
fetchChild<ItemGridWidget>("itemGrid2")->setItemBag(m_itemBag);
if (containsChild("outputItemGrid"))
fetchChild<ItemGridWidget>("outputItemGrid")->setItemBag(m_itemBag);
if (container->iconItem()) {
auto itemDatabase = Root::singleton().itemDatabase();
auto iconItem = itemDatabase->itemShared(container->iconItem());
auto icon = make_shared<ItemSlotWidget>(iconItem, "/interface/inventory/portrait.png");
icon->showDurability(false);
icon->showRarity(false);
icon->setBackingImageAffinity(true, true);
setTitle(icon, container->containerDescription(), container->containerSubTitle());
}
if (containsChild("objectImage"))
if (auto containerObject = as<Object>(m_containerInteractor->openContainer()))
fetchChild<ImageWidget>("objectImage")->setDrawables(containerObject->cursorHintDrawables());
m_expectingSwap = ExpectingSwap::None;
}
void ContainerPane::displayed() {
Pane::displayed();
m_expectingSwap = ExpectingSwap::None;
if (m_script) {
if (m_worldClient && m_worldClient->inWorld())
m_script->init(m_worldClient.get());
m_script->invoke("displayed");
}
}
void ContainerPane::dismissed() {
Pane::dismissed();
if (m_script) {
m_script->invoke("dismissed");
m_script->uninit();
}
}
bool ContainerPane::giveContainerResult(ContainerResult result) {
if (m_expectingSwap == ExpectingSwap::None)
return false;
for (auto item : result) {
auto inv = m_player->inventory();
m_player->triggerPickupEvents(item);
if (m_expectingSwap == ExpectingSwap::SwapSlot) {
m_player->clearSwap();
inv->setSwapSlotItem(item);
} else if (m_expectingSwap == ExpectingSwap::SwapSlotStack) {
auto swapItem = inv->swapSlotItem();
if (swapItem && swapItem->stackWith(item)) {
continue;
} else {
inv->clearSwap();
inv->setSwapSlotItem(item);
}
} else {
m_containerInteractor->addToContainer(inv->addItems(item));
}
}
m_expectingSwap = ExpectingSwap::None;
return true;
}
PanePtr ContainerPane::createTooltip(Vec2I const& screenPosition) {
ItemPtr item;
if (auto child = getChildAt(screenPosition)) {
if (auto itemSlot = as<ItemSlotWidget>(child))
item = itemSlot->item();
if (auto itemGrid = as<ItemGridWidget>(child))
item = itemGrid->itemAt(screenPosition);
}
if (item)
return ItemTooltipBuilder::buildItemTooltip(item, m_player);
return {};
}
void ContainerPane::swapSlot(ItemGridWidget* grid) {
auto inv = m_player->inventory();
if (context()->shiftHeld()) {
auto containerItem = grid->selectedItem();
if (containerItem && inv->itemsCanFit(containerItem) >= containerItem->count()) {
m_containerInteractor->swapInContainer(grid->selectedIndex(), {});
m_expectingSwap = ExpectingSwap::Inventory;
}
} else {
m_containerInteractor->swapInContainer(grid->selectedIndex(), inv->swapSlotItem());
inv->setSwapSlotItem({});
m_expectingSwap = ExpectingSwap::SwapSlot;
}
}
void ContainerPane::startCrafting() {
m_containerInteractor->startCraftingInContainer();
}
void ContainerPane::stopCrafting() {
m_containerInteractor->stopCraftingInContainer();
}
void ContainerPane::toggleCrafting() {
if (m_containerInteractor->openContainer()->isCrafting())
stopCrafting();
else
startCrafting();
}
void ContainerPane::clear() {
m_containerInteractor->clearContainer();
}
void ContainerPane::burn() {
m_containerInteractor->burnContainer();
}
void ContainerPane::update(float dt) {
Pane::update(dt);
if (m_script)
m_script->update(m_script->updateDt(dt));
m_itemBag->clearItems();
if (!m_containerInteractor->containerOpen()) {
dismiss();
} else {
auto container = m_containerInteractor->openContainer();
for (size_t i = 0; i < m_itemBag->size(); ++i)
m_itemBag->putItems(i, container->containerItems()[i]);
if (container->isInteractive()) {
if (auto itemGrid = fetchChild<ItemGridWidget>("itemGrid")) {
itemGrid->setProgress(container->craftingProgress());
itemGrid->updateAllItemSlots();
}
if (auto itemGrid = fetchChild<ItemGridWidget>("itemGrid2")) {
itemGrid->setProgress(container->craftingProgress());
itemGrid->updateAllItemSlots();
}
if (auto fuelGauge = fetchChild<FuelWidget>("fuelGauge")) {
fuelGauge->setCurrentFuelLevel(m_worldClient->getProperty("ship.fuel", 0).toUInt());
fuelGauge->setMaxFuelLevel(m_worldClient->getProperty("ship.maxFuel", 0).toUInt());
float totalFuelAmount = 0;
for (auto& item : container->containerItems()) {
if (item)
totalFuelAmount += item->instanceValue("fuelAmount", 0).toUInt() * item->count();
}
fuelGauge->setPotentialFuelAmount(totalFuelAmount);
fuelGauge->setRequestedFuelAmount(0);
}
}
}
}
}