Armor optimizations

This commit is contained in:
Kae 2023-06-24 23:38:27 +10:00
parent 7eb010d4a1
commit 2bd399fd00
7 changed files with 94 additions and 27 deletions

View File

@ -2,6 +2,7 @@
#include "StarImageProcessing.hpp" #include "StarImageProcessing.hpp"
#include "StarDirectives.hpp" #include "StarDirectives.hpp"
#include "StarXXHash.hpp" #include "StarXXHash.hpp"
#include "StarLogging.hpp"
namespace Star { namespace Star {
@ -20,17 +21,17 @@ Directives::Entry::Entry(Entry const& other) {
string = other.string; string = other.string;
} }
Directives::Directives() {} Directives::Directives() : hash(0) {}
Directives::Directives(String const& directives) { Directives::Directives(String const& directives) : hash(0) {
parse(directives); parse(directives);
} }
Directives::Directives(String&& directives) { Directives::Directives(String&& directives) : hash(0) {
String mine = move(directives); String mine = move(directives);
parse(mine); parse(mine);
} }
Directives::Directives(const char* directives) { Directives::Directives(const char* directives) : hash(0) {
String string(directives); String string(directives);
parse(string); parse(string);
} }
@ -42,6 +43,9 @@ Directives::Directives(List<Entry>&& newEntries) {
} }
void Directives::parse(String const& directives) { void Directives::parse(String const& directives) {
if (directives.empty())
return;
List<Entry> newList; List<Entry> newList;
StringList split = directives.split('?'); StringList split = directives.split('?');
newList.reserve(split.size()); newList.reserve(split.size());
@ -51,25 +55,35 @@ void Directives::parse(String const& directives) {
newList.emplace_back(move(operation), move(str)); newList.emplace_back(move(operation), move(str));
} }
} }
if (newList.empty())
return;
entries = std::make_shared<List<Entry> const>(move(newList)); entries = std::make_shared<List<Entry> const>(move(newList));
hash = XXH3_64bits(directives.utf8Ptr(), directives.utf8Size()); hash = XXH3_64bits(directives.utf8Ptr(), directives.utf8Size());
//if (directives.utf8Size() > 1000)
// Logger::logf(LogLevel::Debug, "Directives: Parsed %u character long string", directives.utf8Size());
} }
void Directives::buildString(String& out) const { void Directives::buildString(String& out) const {
for (auto& entry : *entries) { if (entries) {
out += "?"; for (auto& entry : *entries) {
out += entry.string; out += "?";
out += entry.string;
}
} }
} }
String Directives::toString() const { String Directives::toString() const {
String result; String result;
buildString(result); buildString(result);
//if (result.utf8Size() > 1000)
// Logger::logf(LogLevel::Debug, "Directives: Rebuilt %u character long string", result.utf8Size());
return result; return result;
} }
inline bool Directives::empty() const { inline bool Directives::empty() const {
return entries->empty(); return !entries || entries->empty();
} }
@ -114,7 +128,8 @@ inline bool DirectivesGroup::compare(DirectivesGroup const& other) const {
void DirectivesGroup::append(Directives const& directives) { void DirectivesGroup::append(Directives const& directives) {
m_directives.emplace_back(directives); m_directives.emplace_back(directives);
m_count += m_directives.back().entries->size(); if (directives.entries)
m_count += m_directives.back().entries->size();
} }
void DirectivesGroup::append(List<Directives::Entry>&& entries) { void DirectivesGroup::append(List<Directives::Entry>&& entries) {
@ -146,16 +161,20 @@ void DirectivesGroup::addToString(String& string) const {
void DirectivesGroup::forEach(DirectivesCallback callback) const { void DirectivesGroup::forEach(DirectivesCallback callback) const {
for (auto& directives : m_directives) { for (auto& directives : m_directives) {
for (auto& entry : *directives.entries) if (directives.entries) {
callback(entry); for (auto& entry : *directives.entries)
callback(entry);
}
} }
} }
bool DirectivesGroup::forEachAbortable(AbortableDirectivesCallback callback) const { bool DirectivesGroup::forEachAbortable(AbortableDirectivesCallback callback) const {
for (auto& directives : m_directives) { for (auto& directives : m_directives) {
for (auto& entry : *directives.entries) { if (directives.entries) {
if (!callback(entry)) for (auto& entry : *directives.entries) {
return false; if (!callback(entry))
return false;
}
} }
} }

View File

@ -16,7 +16,7 @@
namespace Star { namespace Star {
ArmorWearer::ArmorWearer() { ArmorWearer::ArmorWearer() : m_lastNude(true), m_needsHumanoidSync(true) {
addNetElement(&m_headItemDataNetState); addNetElement(&m_headItemDataNetState);
addNetElement(&m_chestItemDataNetState); addNetElement(&m_chestItemDataNetState);
addNetElement(&m_legsItemDataNetState); addNetElement(&m_legsItemDataNetState);
@ -27,7 +27,14 @@ ArmorWearer::ArmorWearer() {
addNetElement(&m_backCosmeticItemDataNetState); addNetElement(&m_backCosmeticItemDataNetState);
} }
void ArmorWearer::setupHumanoidClothingDrawables(Humanoid& humanoid, bool forceNude) const { void ArmorWearer::setupHumanoidClothingDrawables(Humanoid& humanoid, bool forceNude) {
if (m_lastNude != forceNude)
m_lastNude = forceNude;
else if (!m_needsHumanoidSync)
return;
m_needsHumanoidSync = false;
bool bodyHidden = false; bool bodyHidden = false;
if (m_headCosmeticItem && !forceNude) { if (m_headCosmeticItem && !forceNude) {
humanoid.setHeadArmorFrameset(m_headCosmeticItem->frameset(humanoid.identity().gender)); humanoid.setHeadArmorFrameset(m_headCosmeticItem->frameset(humanoid.identity().gender));
@ -161,35 +168,59 @@ List<PersistentStatusEffect> ArmorWearer::statusEffects() const {
} }
void ArmorWearer::setHeadItem(HeadArmorPtr headItem) { void ArmorWearer::setHeadItem(HeadArmorPtr headItem) {
if (!Item::itemsEqual(m_headItem, headItem))
return;
m_headItem = headItem; m_headItem = headItem;
m_needsHumanoidSync = true;
} }
void ArmorWearer::setHeadCosmeticItem(HeadArmorPtr headCosmeticItem) { void ArmorWearer::setHeadCosmeticItem(HeadArmorPtr headCosmeticItem) {
if (!Item::itemsEqual(m_headCosmeticItem, headCosmeticItem))
return;
m_headCosmeticItem = headCosmeticItem; m_headCosmeticItem = headCosmeticItem;
m_needsHumanoidSync = true;
} }
void ArmorWearer::setChestCosmeticItem(ChestArmorPtr chestCosmeticItem) { void ArmorWearer::setChestCosmeticItem(ChestArmorPtr chestCosmeticItem) {
if (!Item::itemsEqual(m_chestCosmeticItem, chestCosmeticItem))
return;
m_chestCosmeticItem = chestCosmeticItem; m_chestCosmeticItem = chestCosmeticItem;
m_needsHumanoidSync = true;
} }
void ArmorWearer::setChestItem(ChestArmorPtr chestItem) { void ArmorWearer::setChestItem(ChestArmorPtr chestItem) {
if (!Item::itemsEqual(m_chestItem, chestItem))
return;
m_chestItem = chestItem; m_chestItem = chestItem;
m_needsHumanoidSync = true;
} }
void ArmorWearer::setLegsItem(LegsArmorPtr legsItem) { void ArmorWearer::setLegsItem(LegsArmorPtr legsItem) {
if (!Item::itemsEqual(m_legsItem, legsItem))
return;
m_legsItem = legsItem; m_legsItem = legsItem;
m_needsHumanoidSync = true;
} }
void ArmorWearer::setLegsCosmeticItem(LegsArmorPtr legsCosmeticItem) { void ArmorWearer::setLegsCosmeticItem(LegsArmorPtr legsCosmeticItem) {
if (!Item::itemsEqual(m_legsCosmeticItem, legsCosmeticItem))
return;
m_legsCosmeticItem = legsCosmeticItem; m_legsCosmeticItem = legsCosmeticItem;
m_needsHumanoidSync = true;
} }
void ArmorWearer::setBackItem(BackArmorPtr backItem) { void ArmorWearer::setBackItem(BackArmorPtr backItem) {
if (!Item::itemsEqual(m_backItem, backItem))
return;
m_backItem = backItem; m_backItem = backItem;
m_needsHumanoidSync = true;
} }
void ArmorWearer::setBackCosmeticItem(BackArmorPtr backCosmeticItem) { void ArmorWearer::setBackCosmeticItem(BackArmorPtr backCosmeticItem) {
if (!Item::itemsEqual(m_backCosmeticItem, backCosmeticItem))
return;
m_backCosmeticItem = backCosmeticItem; m_backCosmeticItem = backCosmeticItem;
m_needsHumanoidSync = true;
} }
HeadArmorPtr ArmorWearer::headItem() const { HeadArmorPtr ArmorWearer::headItem() const {
@ -275,23 +306,26 @@ ItemDescriptor ArmorWearer::backCosmeticItemDescriptor() const {
void ArmorWearer::netElementsNeedLoad(bool) { void ArmorWearer::netElementsNeedLoad(bool) {
auto itemDatabase = Root::singleton().itemDatabase(); auto itemDatabase = Root::singleton().itemDatabase();
bool changed = false;
if (m_headItemDataNetState.pullUpdated()) if (m_headItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_headItemDataNetState.get(), m_headItem); changed |= itemDatabase->loadItem(m_headItemDataNetState.get(), m_headItem);
if (m_chestItemDataNetState.pullUpdated()) if (m_chestItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_chestItemDataNetState.get(), m_chestItem); changed |= itemDatabase->loadItem(m_chestItemDataNetState.get(), m_chestItem);
if (m_legsItemDataNetState.pullUpdated()) if (m_legsItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_legsItemDataNetState.get(), m_legsItem); changed |= itemDatabase->loadItem(m_legsItemDataNetState.get(), m_legsItem);
if (m_backItemDataNetState.pullUpdated()) if (m_backItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_backItemDataNetState.get(), m_backItem); changed |= itemDatabase->loadItem(m_backItemDataNetState.get(), m_backItem);
if (m_headCosmeticItemDataNetState.pullUpdated()) if (m_headCosmeticItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_headCosmeticItemDataNetState.get(), m_headCosmeticItem); changed |= itemDatabase->loadItem(m_headCosmeticItemDataNetState.get(), m_headCosmeticItem);
if (m_chestCosmeticItemDataNetState.pullUpdated()) if (m_chestCosmeticItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_chestCosmeticItemDataNetState.get(), m_chestCosmeticItem); changed |= itemDatabase->loadItem(m_chestCosmeticItemDataNetState.get(), m_chestCosmeticItem);
if (m_legsCosmeticItemDataNetState.pullUpdated()) if (m_legsCosmeticItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_legsCosmeticItemDataNetState.get(), m_legsCosmeticItem); changed |= itemDatabase->loadItem(m_legsCosmeticItemDataNetState.get(), m_legsCosmeticItem);
if (m_backCosmeticItemDataNetState.pullUpdated()) if (m_backCosmeticItemDataNetState.pullUpdated())
itemDatabase->loadItem(m_backCosmeticItemDataNetState.get(), m_backCosmeticItem); changed |= itemDatabase->loadItem(m_backCosmeticItemDataNetState.get(), m_backCosmeticItem);
m_needsHumanoidSync = changed;
} }
void ArmorWearer::netElementsNeedStore() { void ArmorWearer::netElementsNeedStore() {

View File

@ -26,7 +26,7 @@ class ArmorWearer : public NetElementSyncGroup {
public: public:
ArmorWearer(); ArmorWearer();
void setupHumanoidClothingDrawables(Humanoid& humanoid, bool forceNude) const; void setupHumanoidClothingDrawables(Humanoid& humanoid, bool forceNude);
void effects(EffectEmitter& effectEmitter); void effects(EffectEmitter& effectEmitter);
List<PersistentStatusEffect> statusEffects() const; List<PersistentStatusEffect> statusEffects() const;
@ -82,6 +82,9 @@ private:
NetElementData<ItemDescriptor> m_chestCosmeticItemDataNetState; NetElementData<ItemDescriptor> m_chestCosmeticItemDataNetState;
NetElementData<ItemDescriptor> m_legsCosmeticItemDataNetState; NetElementData<ItemDescriptor> m_legsCosmeticItemDataNetState;
NetElementData<ItemDescriptor> m_backCosmeticItemDataNetState; NetElementData<ItemDescriptor> m_backCosmeticItemDataNetState;
bool m_lastNude;
bool m_needsHumanoidSync;
}; };
} }

View File

@ -10,7 +10,7 @@
namespace Star { namespace Star {
Drawable::ImagePart& Drawable::ImagePart::addDirectives(Directives const& directives, bool keepImageCenterPosition) { Drawable::ImagePart& Drawable::ImagePart::addDirectives(Directives const& directives, bool keepImageCenterPosition) {
if (directives.entries->empty()) if (!directives.entries || directives.entries->empty())
return *this; return *this;
if (keepImageCenterPosition) { if (keepImageCenterPosition) {

View File

@ -285,4 +285,13 @@ ItemPtr GenericItem::clone() const {
return make_shared<GenericItem>(*this); return make_shared<GenericItem>(*this);
} }
bool Item::itemsEqual(ItemConstPtr const& a, ItemConstPtr const& b) {
if (!a && !b) // Both are null
return true;
if (a && b) // Both aren't null, compare
return a->stackableWith(b);
else // One is null, so not equal
return true;
}
} }

View File

@ -114,6 +114,8 @@ public:
// Returns just the dynamic parameters // Returns just the dynamic parameters
Json parameters() const; Json parameters() const;
static bool itemsEqual(ItemConstPtr const& a, ItemConstPtr const& b);
protected: protected:
void setMaxStack(uint64_t maxStack); void setMaxStack(uint64_t maxStack);
void setDescription(String const& description); void setDescription(String const& description);

View File

@ -21,7 +21,7 @@ ArmorItem::ArmorItem(Json const& config, String const& directory, Json const& da
m_directives = instanceValue("directives", "").toString(); m_directives = instanceValue("directives", "").toString();
m_colorOptions = colorDirectivesFromConfig(config.getArray("colorOptions", JsonArray{""})); m_colorOptions = colorDirectivesFromConfig(config.getArray("colorOptions", JsonArray{""}));
if (m_directives.entries->empty()) if (!m_directives.entries || m_directives.entries->empty())
m_directives = "?" + m_colorOptions.wrap(instanceValue("colorIndex", 0).toUInt()); m_directives = "?" + m_colorOptions.wrap(instanceValue("colorIndex", 0).toUInt());
refreshIconDrawables(); refreshIconDrawables();