Perfectly Generic Item improvements

spawnitem won't create generic items unless you intend to

generic items will retain the data for what item they were if a mod is uninstalled, and will attempt to restore themselves if re-installed
This commit is contained in:
WasabiRaptor 2024-03-08 18:14:40 -05:00
parent 7bc9eaa432
commit 84fe2dfd4c
3 changed files with 28 additions and 10 deletions

View File

@ -183,7 +183,7 @@ String CommandProcessor::warpRandom(ConnectionId connectionId, String const& typ
} }
} }
} }
if (size.magnitude() > 1024) if (size.magnitude() > 1024)
return "could not find a matching world"; return "could not find a matching world";
size *= 2; size *= 2;
@ -296,7 +296,7 @@ String CommandProcessor::spawnItem(ConnectionId connectionId, String const& argu
bool done = m_universe->executeForClient(connectionId, [&](WorldServer* world, PlayerPtr const& player) { bool done = m_universe->executeForClient(connectionId, [&](WorldServer* world, PlayerPtr const& player) {
auto itemDatabase = Root::singleton().itemDatabase(); auto itemDatabase = Root::singleton().itemDatabase();
world->addEntity(ItemDrop::createRandomizedDrop(itemDatabase->item(ItemDescriptor(kind, amount, parameters), level, seed), player->aimPosition())); world->addEntity(ItemDrop::createRandomizedDrop(itemDatabase->item(ItemDescriptor(kind, amount, parameters), level, seed, true), player->aimPosition()));
}); });
return done ? "" : "Invalid client state"; return done ? "" : "Invalid client state";

View File

@ -232,11 +232,11 @@ ItemPtr ItemDatabase::itemShared(ItemDescriptor descriptor, Maybe<float> level,
} }
} }
ItemPtr ItemDatabase::item(ItemDescriptor descriptor, Maybe<float> level, Maybe<uint64_t> seed) const { ItemPtr ItemDatabase::item(ItemDescriptor descriptor, Maybe<float> level, Maybe<uint64_t> seed, bool ignoreInvalid) const {
if (!descriptor) if (!descriptor)
return {}; return {};
else else
return tryCreateItem(descriptor, level, seed); return tryCreateItem(descriptor, level, seed, ignoreInvalid);
} }
bool ItemDatabase::hasRecipeToMake(ItemDescriptor const& item) const { bool ItemDatabase::hasRecipeToMake(ItemDescriptor const& item) const {
@ -499,14 +499,32 @@ ItemPtr ItemDatabase::createItem(ItemType type, ItemConfig const& config) {
} }
} }
ItemPtr ItemDatabase::tryCreateItem(ItemDescriptor const& descriptor, Maybe<float> level, Maybe<uint64_t> seed) const { ItemPtr ItemDatabase::tryCreateItem(ItemDescriptor const& descriptor, Maybe<float> level, Maybe<uint64_t> seed, bool ignoreInvalid) const {
ItemPtr result; ItemPtr result;
String name = descriptor.name();
Json parameters = descriptor.parameters();
try { try {
result = createItem(m_items.get(descriptor.name()).type, itemConfig(descriptor.name(), descriptor.parameters(), level, seed)); if ((name == "perfectlygenericitem") && parameters.contains("genericItemStorage")) {
Json storage = parameters.get("genericItemStorage");
name = storage.getString("name");
parameters = storage.get("parameters");
}
result = createItem(m_items.get(name).type, itemConfig(name, parameters, level, seed));
} }
catch (std::exception const& e) { catch (std::exception const& e) {
Logger::error("Could not instantiate item '{}'. {}", descriptor, outputException(e, false)); if (descriptor.name() == "perfectlygenericitem") {
result = createItem(m_items.get("perfectlygenericitem").type, itemConfig("perfectlygenericitem", JsonObject(), {}, {})); Logger::error("Could not re-instantiate item '{}'. {}", descriptor, outputException(e, false));
result = createItem(m_items.get("perfectlygenericitem").type, itemConfig("perfectlygenericitem", descriptor.parameters(), level, seed));
} else if (!ignoreInvalid) {
Logger::error("Could not instantiate item '{}'. {}", descriptor, outputException(e, false));
result = createItem(m_items.get("perfectlygenericitem").type, itemConfig("perfectlygenericitem", JsonObject({
{"genericItemStorage", descriptor.toJson()},
{"shortdescription", descriptor.name()},
{"description", "Reinstall the parent mod to return this item to normal\n^red;(to retain data, do not place as object)"}
}), {}, {}));
} else
throw e;
} }
result->setCount(descriptor.count()); result->setCount(descriptor.count());

View File

@ -117,7 +117,7 @@ public:
// The returned item pointer will be shared. Either call ->clone() or use item() instead for a copy. // The returned item pointer will be shared. Either call ->clone() or use item() instead for a copy.
ItemPtr itemShared(ItemDescriptor descriptor, Maybe<float> level = {}, Maybe<uint64_t> seed = {}) const; ItemPtr itemShared(ItemDescriptor descriptor, Maybe<float> level = {}, Maybe<uint64_t> seed = {}) const;
// Same as itemShared, but makes a copy instead. Does not cache. // Same as itemShared, but makes a copy instead. Does not cache.
ItemPtr item(ItemDescriptor descriptor, Maybe<float> level = {}, Maybe<uint64_t> seed = {}) const; ItemPtr item(ItemDescriptor descriptor, Maybe<float> level = {}, Maybe<uint64_t> seed = {}, bool ignoreInvalid = false) const;
bool hasRecipeToMake(ItemDescriptor const& item) const; bool hasRecipeToMake(ItemDescriptor const& item) const;
@ -159,7 +159,7 @@ private:
}; };
static ItemPtr createItem(ItemType type, ItemConfig const& config); static ItemPtr createItem(ItemType type, ItemConfig const& config);
ItemPtr tryCreateItem(ItemDescriptor const& descriptor, Maybe<float> level = {}, Maybe<uint64_t> seed = {}) const; ItemPtr tryCreateItem(ItemDescriptor const& descriptor, Maybe<float> level = {}, Maybe<uint64_t> seed = {}, bool ignoreInvalid = false) const;
ItemData const& itemData(String const& name) const; ItemData const& itemData(String const& name) const;
ItemRecipe makeRecipe(List<ItemDescriptor> inputs, ItemDescriptor output, float duration, StringSet groups) const; ItemRecipe makeRecipe(List<ItemDescriptor> inputs, ItemDescriptor output, float duration, StringSet groups) const;