From 8b2e1c44bc858a659e7497d93d0d18196ccb9c2c Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Mon, 31 Dec 2018 14:23:31 -0600 Subject: [PATCH 1/5] cells now use their local processor component instea dof the specie sone, which means they now dfo no processes, i need to make it so it copies the capcitie sinto teh local processor component instead of using the species processor component now --- scripts/microbe_stage/microbe_operations.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as index 8ab6e2e9219..f702df533ae 100644 --- a/scripts/microbe_stage/microbe_operations.as +++ b/scripts/microbe_stage/microbe_operations.as @@ -1030,7 +1030,7 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, return entity; } - auto processor = world.GetComponent_ProcessorComponent(speciesEntity); + auto processor = world.GetComponent_ProcessorComponent(entity); if(processor is null){ LOG_ERROR("Microbe species '" + microbeComponent.speciesName + From 2bdb4a285a6387e40587d6006c3ddc1223561032 Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Mon, 31 Dec 2018 14:40:38 -0600 Subject: [PATCH 2/5] Cells now use their local processor component, which is also now set, instead of the species one. --- scripts/microbe_stage/microbe_operations.as | 9 ++- scripts/microbe_stage/setup.as | 2 + scripts/microbe_stage/species_system.as | 69 +++++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as index f702df533ae..a48a9a9a9e1 100644 --- a/scripts/microbe_stage/microbe_operations.as +++ b/scripts/microbe_stage/microbe_operations.as @@ -1030,14 +1030,16 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, return entity; } - auto processor = world.GetComponent_ProcessorComponent(entity); + auto processor = world.GetComponent_ProcessorComponent(speciesEntity); if(processor is null){ LOG_ERROR("Microbe species '" + microbeComponent.speciesName + "' doesn't have a processor component"); } else { - - compoundBag.setProcessor(processor, microbeComponent.speciesName); + //Safely initiate processor component + //may wrap this into apply template or something else + Species::initLocalProcessorComponent(world,species,entity); + compoundBag.setProcessor(processorComponent,microbeComponent.speciesName); } if(microbeComponent.organelles.length() > 0) @@ -1045,6 +1047,7 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, // Apply the template // auto shape = world.GetPhysicalWorld().CreateCompound(); + //Maybe wrap it into applytemplate Species::applyTemplate(world, entity, species, shape); // ------------------------------------ // diff --git a/scripts/microbe_stage/setup.as b/scripts/microbe_stage/setup.as index 815d389af2a..52cf4e63a7e 100644 --- a/scripts/microbe_stage/setup.as +++ b/scripts/microbe_stage/setup.as @@ -234,6 +234,8 @@ 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 + Species::initLocalProcessorComponent(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..03688caee9b 100644 --- a/scripts/microbe_stage/species_system.as +++ b/scripts/microbe_stage/species_system.as @@ -1382,6 +1382,75 @@ void initProcessorComponent(CellStageWorld@ world, } } +void initLocalProcessorComponent(CellStageWorld@ world, + SpeciesComponent@ speciesComponent, ObjectID entity) +{ + assert(speciesComponent.organelles.length() > 0, "initProcessorComponent given a " + "species that has no organelles"); + auto speciesEntity = findSpeciesEntityByName(world, speciesComponent.name); + + ProcessorComponent@ cellProcessorComponent = world.GetComponent_ProcessorComponent( + entity); + + if (cellProcessorComponent is null) + { + LOG_ERROR("Species lacks processor component for new cell"); + //Exit safely + return; + } + dictionary capacities; + for(uint i = 0; i < speciesComponent.organelles.length(); i++){ + + const Organelle@ organelleDefinition = cast(speciesComponent.organelles[i]).organelle; + if(organelleDefinition is null){ + + LOG_ERROR("Organelle table has a null organelle in it, position: " + i + + "', that was added to a species entity"); + continue; + } + + for(uint processNumber = 0; + processNumber < organelleDefinition.processes.length(); ++processNumber) + { + // This name needs to match the one in bioProcessRegistry + TweakedProcess@ process = organelleDefinition.processes[processNumber]; + + if(!capacities.exists(process.process.internalName)){ + capacities[process.process.internalName] = double(0.0f); + } + + // Here the second capacities[process.name] was initially capacities[process] + // but the processes are just strings inside the Organelle class + capacities[process.process.internalName] = double(capacities[ + process.process.internalName]) + + process.capacity; + } + } + + uint64 processCount = SimulationParameters::bioProcessRegistry().getSize(); + for(BioProcessId bioProcessId = 0; bioProcessId < processCount; ++bioProcessId){ + auto processName = SimulationParameters::bioProcessRegistry().getInternalName( + bioProcessId); + + if(capacities.exists(processName)){ + double capacity; + if(!capacities.get(processName, capacity)){ + LOG_ERROR("capacities has invalid value"); + continue; + } + + // LOG_INFO("Process: " + processName + " Capacity: " + capacity); + cellProcessorComponent.setCapacity(bioProcessId, capacity); + } else { + // If it doesnt exist: + capacities.set(processName, 0.0f); + + // This is related to https://github.com/Revolutionary-Games/Thrive/issues/599 + cellProcessorComponent.setCapacity(bioProcessId, 0.0f); + } + } +} + //! 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, From e3f290c302e23419fa3b71c6079bdf81051eca93 Mon Sep 17 00:00:00 2001 From: Untrustedlife Date: Mon, 31 Dec 2018 16:05:22 -0600 Subject: [PATCH 3/5] removed temp change i made awhile ago that stopped glucose from being ejected from extinct cells --- scripts/SimulationParameters/MicrobeStage/Compounds.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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, From 51ae6458d7141a44f8b783850af28cd11ff85265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henri=20Hyyryl=C3=A4inen?= Date: Tue, 1 Jan 2019 16:46:25 +0200 Subject: [PATCH 4/5] Improved the process system fix: now runs properly like a system and compound bags no longer have an unsafe pointer. Also cleaned up the script side and made the process copy method way cheaper and renamed it to reflect what it does. I didn't see any problems after these changes. --- scripts/microbe_stage/microbe_operations.as | 13 ++-- scripts/microbe_stage/setup.as | 5 +- scripts/microbe_stage/species_system.as | 70 ++++-------------- src/microbe_stage/process_system.cpp | 81 ++++++--------------- src/microbe_stage/process_system.h | 56 ++++++-------- src/scripting/script_initializer.cpp | 15 ++-- 6 files changed, 80 insertions(+), 160 deletions(-) diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as index a48a9a9a9e1..2d9c1c3f16e 100644 --- a/scripts/microbe_stage/microbe_operations.as +++ b/scripts/microbe_stage/microbe_operations.as @@ -1036,10 +1036,9 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, LOG_ERROR("Microbe species '" + microbeComponent.speciesName + "' doesn't have a processor component"); } else { - //Safely initiate processor component - //may wrap this into apply template or something else - Species::initLocalProcessorComponent(world,species,entity); - compoundBag.setProcessor(processorComponent,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) @@ -1047,7 +1046,11 @@ ObjectID _createMicrobeEntity(CellStageWorld@ world, bool aiControlled, // Apply the template // auto shape = world.GetPhysicalWorld().CreateCompound(); - //Maybe wrap it into applytemplate + + // 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 52cf4e63a7e..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)); @@ -235,7 +235,8 @@ 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 - Species::initLocalProcessorComponent(world,ourActualSpecies,player); + // 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 03688caee9b..2f2d00548fa 100644 --- a/scripts/microbe_stage/species_system.as +++ b/scripts/microbe_stage/species_system.as @@ -1382,73 +1382,31 @@ void initProcessorComponent(CellStageWorld@ world, } } -void initLocalProcessorComponent(CellStageWorld@ world, +//! This function copies process data from a species to an entity with a ProcessorComponent +void copyProcessesFromSpecies(CellStageWorld@ world, SpeciesComponent@ speciesComponent, ObjectID entity) { - assert(speciesComponent.organelles.length() > 0, "initProcessorComponent given a " - "species that has no organelles"); - auto speciesEntity = findSpeciesEntityByName(world, speciesComponent.name); - ProcessorComponent@ cellProcessorComponent = world.GetComponent_ProcessorComponent( entity); - if (cellProcessorComponent is null) - { - LOG_ERROR("Species lacks processor component for new cell"); - //Exit safely + if(cellProcessorComponent is null) + { + LOG_ERROR("Entity doesn't have a ProcessorComponent for process copy target"); return; - } - dictionary capacities; - for(uint i = 0; i < speciesComponent.organelles.length(); i++){ - - const Organelle@ organelleDefinition = cast(speciesComponent.organelles[i]).organelle; - if(organelleDefinition is null){ - - LOG_ERROR("Organelle table has a null organelle in it, position: " + i + - "', that was added to a species entity"); - continue; - } - - for(uint processNumber = 0; - processNumber < organelleDefinition.processes.length(); ++processNumber) - { - // This name needs to match the one in bioProcessRegistry - TweakedProcess@ process = organelleDefinition.processes[processNumber]; - - if(!capacities.exists(process.process.internalName)){ - capacities[process.process.internalName] = double(0.0f); - } - - // Here the second capacities[process.name] was initially capacities[process] - // but the processes are just strings inside the Organelle class - capacities[process.process.internalName] = double(capacities[ - process.process.internalName]) + - process.capacity; - } } - uint64 processCount = SimulationParameters::bioProcessRegistry().getSize(); - for(BioProcessId bioProcessId = 0; bioProcessId < processCount; ++bioProcessId){ - auto processName = SimulationParameters::bioProcessRegistry().getInternalName( - bioProcessId); - - if(capacities.exists(processName)){ - double capacity; - if(!capacities.get(processName, capacity)){ - LOG_ERROR("capacities has invalid value"); - continue; - } + auto speciesEntity = findSpeciesEntityByName(world, speciesComponent.name); - // LOG_INFO("Process: " + processName + " Capacity: " + capacity); - cellProcessorComponent.setCapacity(bioProcessId, capacity); - } else { - // If it doesnt exist: - capacities.set(processName, 0.0f); + ProcessorComponent@ speciesProcessor = world.GetComponent_ProcessorComponent( + speciesEntity); - // This is related to https://github.com/Revolutionary-Games/Thrive/issues/599 - cellProcessorComponent.setCapacity(bioProcessId, 0.0f); - } + 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 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..65d850991f3 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) { From a956794371d4b1e786ec00f9fea3953914834bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henri=20Hyyryl=C3=A4inen?= Date: Tue, 1 Jan 2019 17:02:02 +0200 Subject: [PATCH 5/5] Removed script register for compound bag species name. Forgot to include this change before --- src/scripting/script_initializer.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/scripting/script_initializer.cpp b/src/scripting/script_initializer.cpp index 65d850991f3..825947beb53 100644 --- a/src/scripting/script_initializer.cpp +++ b/src/scripting/script_initializer.cpp @@ -762,12 +762,6 @@ bool ANGELSCRIPT_REGISTERFAIL; } - if(engine->RegisterObjectProperty("CompoundBagComponent", - "string speciesName", - asOFFSET(CompoundBagComponent, speciesName)) < 0) { - ANGELSCRIPT_REGISTERFAIL; - } - // ------------------------------------ // // CompoundAbsorberComponent if(engine->RegisterObjectType(