diff --git a/scripts/SimulationParameters/MicrobeStage/Compounds.json b/scripts/SimulationParameters/MicrobeStage/Compounds.json index 3fe9f27558c..7d6032e0da4 100644 --- a/scripts/SimulationParameters/MicrobeStage/Compounds.json +++ b/scripts/SimulationParameters/MicrobeStage/Compounds.json @@ -51,7 +51,7 @@ "name": "Glucose", "volume": 1, "isCloud": true, - "isUseful": true, + "isUseful": false, "colour": { "r": 0.9, "g": 0.9, diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as index 8ab6e2e9219..2d9c1c3f16e 100644 --- a/scripts/microbe_stage/microbe_operations.as +++ b/scripts/microbe_stage/microbe_operations.as @@ -1036,8 +1036,9 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, LOG_ERROR("Microbe species '" + microbeComponent.speciesName + "' doesn't have a processor component"); } else { - - compoundBag.setProcessor(processor, microbeComponent.speciesName); + // Each microbe now has their own processor component to allow + // the process system to run safely while species are deleted + Species::copyProcessesFromSpecies(world, species, entity); } if(microbeComponent.organelles.length() > 0) @@ -1045,6 +1046,11 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, // Apply the template // auto shape = world.GetPhysicalWorld().CreateCompound(); + + // TODO: as now each microbe has a separate processor component they no longer stay + // up to date with the species so either this should apply the species processes OR + // there should be a ProcessConfiguration object that would be shared between the + // ProcessorComponent both in the species and individual cells Species::applyTemplate(world, entity, species, shape); // ------------------------------------ // diff --git a/scripts/microbe_stage/setup.as b/scripts/microbe_stage/setup.as index 815d389af2a..6b3c5cdb6a1 100644 --- a/scripts/microbe_stage/setup.as +++ b/scripts/microbe_stage/setup.as @@ -216,7 +216,7 @@ void onReturnFromEditor(CellStageWorld@ world) playerSpecies.population += 30; ++playerSpecies.generation; - //Call event that checks win conditions + // Call event that checks win conditions GenericEvent@ event = GenericEvent("CheckWin"); NamedVars@ vars = event.GetNamedVars(); vars.AddValue(ScriptSafeVariableBlock("generation", playerSpecies.generation)); @@ -234,6 +234,9 @@ void onReturnFromEditor(CellStageWorld@ world) // Call this before creating the clone. Species::initProcessorComponent(world, player, ourActualSpecies); + // Can probabbly wrap this into the usual init to keep things clean + // This makes sure that the player's processer are up to date with their species + Species::copyProcessesFromSpecies(world, ourActualSpecies, player); PlayerSpeciesSpawner factory("Default"); auto spawned = factory.factorySpawn(world, pos._Position); diff --git a/scripts/microbe_stage/species_system.as b/scripts/microbe_stage/species_system.as index 1e85db83de5..2f2d00548fa 100644 --- a/scripts/microbe_stage/species_system.as +++ b/scripts/microbe_stage/species_system.as @@ -1382,6 +1382,33 @@ void initProcessorComponent(CellStageWorld@ world, } } +//! This function copies process data from a species to an entity with a ProcessorComponent +void copyProcessesFromSpecies(CellStageWorld@ world, + SpeciesComponent@ speciesComponent, ObjectID entity) +{ + ProcessorComponent@ cellProcessorComponent = world.GetComponent_ProcessorComponent( + entity); + + if(cellProcessorComponent is null) + { + LOG_ERROR("Entity doesn't have a ProcessorComponent for process copy target"); + return; + } + + auto speciesEntity = findSpeciesEntityByName(world, speciesComponent.name); + + ProcessorComponent@ speciesProcessor = world.GetComponent_ProcessorComponent( + speciesEntity); + + if(speciesProcessor is null){ + LOG_ERROR("Species lacks processor component for copying processes from"); + return; + } + + // Use assignment operator to copy all data + cellProcessorComponent = speciesProcessor; +} + //! Creates a species from the initial template. This doesn't register with SpeciesSystem //! because this is (currently) only used for the player's species which isn't managed by it ObjectID createSpecies(CellStageWorld@ world, const string &in name, diff --git a/src/microbe_stage/process_system.cpp b/src/microbe_stage/process_system.cpp index 277c6fb79f6..19c2fb0ada8 100644 --- a/src/microbe_stage/process_system.cpp +++ b/src/microbe_stage/process_system.cpp @@ -16,48 +16,27 @@ using namespace thrive; ProcessorComponent::ProcessorComponent() : Leviathan::Component(TYPE) {} -/* -void -ProcessorComponent::load(const StorageContainer& storage) -{ - Component::load(storage); - StorageContainer processes = storage.get("processes"); - for (const std::string& id : processes.keys()) - { - this->process_capacities[std::atoi(id.c_str())] = -processes.get(id); - } -} - -StorageContainer -ProcessorComponent::storage() const -{ - StorageContainer storage = Component::storage(); - - StorageContainer processes; - for (auto entry : this->process_capacities) { - processes.set(std::to_string(static_cast(entry.first)), -entry.second); - } - storage.set("processes", processes); - - - return storage; -} -*/ - -void - ProcessorComponent::setCapacity(BioProcessId id, double capacity) +ProcessorComponent::ProcessorComponent(ProcessorComponent&& other) noexcept : + Leviathan::Component(TYPE), + m_processCapacities(std::move(other.m_processCapacities)) +{} +// ------------------------------------ // +ProcessorComponent& + ProcessorComponent::operator=(const ProcessorComponent& other) { - this->process_capacities[id] = capacity; + m_processCapacities = other.m_processCapacities; + return *this; } -double - ProcessorComponent::getCapacity(BioProcessId id) +ProcessorComponent& + ProcessorComponent::operator=(ProcessorComponent&& other) noexcept { - return this->process_capacities[id]; + m_processCapacities = std::move(other.m_processCapacities); + return *this; } +// ------------------------------------ // +// CompoundBagComponent CompoundBagComponent::CompoundBagComponent() : Leviathan::Component(TYPE) { storageSpace = 0; @@ -100,13 +79,6 @@ demand.get(id); Game::instance().engine().getCurrentGameStateFromLua()). getComponent(ProcessorComponent::TYPE_ID)); }*/ -void - CompoundBagComponent::setProcessor(ProcessorComponent* processor, - const std::string& speciesName) -{ - this->processor = processor; - this->speciesName = speciesName; -} // helper methods for integrating compound bags with current, un-refactored, lua // microbes @@ -176,12 +148,7 @@ void for(auto& value : CachedComponents.GetIndex()) { CompoundBagComponent& bag = std::get<0>(*value.second); - ProcessorComponent* processor = bag.processor; - - if(!processor) { - LOG_ERROR("Compound Bag Lacks Processor component"); - continue; - } + ProcessorComponent& processor = std::get<1>(*value.second); // Set all compounds to price 0 initially, set used ones to 1, this way // we can purge unused compounds, I think we may be able to merge this @@ -191,20 +158,18 @@ void compoundData.price = 0; } - // LOG_INFO("Capacities:" + - // std::to_string(processor->process_capacities.size())); - for(const auto& process : processor->process_capacities) { + for(const auto& process : processor.m_processCapacities) { const BioProcessId processId = process.first; const double processCapacity = process.second; - // Processes are now every second - const double processLimitCapacity = logicTime; - - // If capcity is 0 dont do it + // If capacity is 0 dont do it if(processCapacity <= 0.0f) continue; - // TODO: this is a sanity check for incorrect process configuration + // Processes are now every second + const double processLimitCapacity = logicTime; + + // This is a sanity check for incorrect process configuration if(processId >= SimulationParameters::bioProcessRegistry.getSize()) { @@ -310,7 +275,7 @@ void } // TODO: fix this comment I (hhyyrylainen) have no idea - // what this does or why this is here + // what this does or why this is here: // That way we always have a running tally of what process was set // to what despite clearing the price every run cycle compoundData.usedLastTime = compoundData.price; diff --git a/src/microbe_stage/process_system.h b/src/microbe_stage/process_system.h index 3a3a595c2cc..38743bb9fd7 100644 --- a/src/microbe_stage/process_system.h +++ b/src/microbe_stage/process_system.h @@ -23,30 +23,39 @@ namespace thrive { class CellStageWorld; +//! \brief Specifies what processes a cell can perform +//! \todo To reduce duplication and excess memory usage the processes should +//! be moved to a new class ProcessConfiguration +//! which would be ReferenceCounted and shared +//! `ProcessConfiguration::pointer m_processes` class ProcessorComponent : public Leviathan::Component { - public: ProcessorComponent(); - /* - void - load( - const StorageContainer& storage - ) override; + ProcessorComponent(ProcessorComponent&& other) noexcept; - StorageContainer - storage() const override; - */ + ProcessorComponent& + operator=(const ProcessorComponent& other); + ProcessorComponent& + operator=(ProcessorComponent&& other) noexcept; - std::unordered_map process_capacities; - void - setCapacity(BioProcessId id, double capacity); - double - getCapacity(BioProcessId id); + inline void + setCapacity(BioProcessId id, double capacity) + { + m_processCapacities[id] = capacity; + } + + inline double + getCapacity(BioProcessId id) + { + return m_processCapacities[id]; + } REFERENCE_HANDLE_UNCOUNTED_TYPE(ProcessorComponent); static constexpr auto TYPE = componentTypeConvert(THRIVE_COMPONENT::PROCESSOR); + + std::unordered_map m_processCapacities; }; // Helper structure to store the economic information of the compounds. @@ -56,32 +65,15 @@ struct CompoundData { double usedLastTime; }; -//! \todo This component depends on an instance of processor so that needs -//! registering +//! \brief A thing that holds compounds class CompoundBagComponent : public Leviathan::Component { public: CompoundBagComponent(); - /* - void - load( - const StorageContainer& storage - ) override; - - StorageContainer - storage() const override; - */ - double storageSpace; double storageSpaceOccupied; - ProcessorComponent* processor = nullptr; - std::string speciesName; std::unordered_map compounds; - void - setProcessor(ProcessorComponent* processor, - const std::string& speciesName); - double getCompoundAmount(CompoundId); double diff --git a/src/scripting/script_initializer.cpp b/src/scripting/script_initializer.cpp index d72551653e4..825947beb53 100644 --- a/src/scripting/script_initializer.cpp +++ b/src/scripting/script_initializer.cpp @@ -484,6 +484,14 @@ bool engine, "ProcessorComponent", &ProcessorComponentTYPEProxy)) return false; + if(engine->RegisterObjectMethod("ProcessorComponent", + "ProcessorComponent& opAssign(const ProcessorComponent &in other)", + asMETHODPR(ProcessorComponent, operator=,(const ProcessorComponent&), + ProcessorComponent&), + asCALL_THISCALL) < 0) { + ANGELSCRIPT_REGISTERFAIL; + } + if(engine->RegisterObjectMethod("ProcessorComponent", "void setCapacity(BioProcessId id, double capacity)", asMETHOD(ProcessorComponent, setCapacity), asCALL_THISCALL) < 0) { @@ -742,13 +750,6 @@ bool ANGELSCRIPT_REGISTERFAIL; } - if(engine->RegisterObjectMethod("CompoundBagComponent", - "void setProcessor(ProcessorComponent@ processor, const string &in " - "speciesName)", - asMETHOD(CompoundBagComponent, setProcessor), asCALL_THISCALL) < 0) { - ANGELSCRIPT_REGISTERFAIL; - } - if(engine->RegisterObjectProperty("CompoundBagComponent", "double storageSpace", asOFFSET(CompoundBagComponent, storageSpace)) < 0) { @@ -761,12 +762,6 @@ bool ANGELSCRIPT_REGISTERFAIL; } - if(engine->RegisterObjectProperty("CompoundBagComponent", - "string speciesName", - asOFFSET(CompoundBagComponent, speciesName)) < 0) { - ANGELSCRIPT_REGISTERFAIL; - } - // ------------------------------------ // // CompoundAbsorberComponent if(engine->RegisterObjectType(