Skip to content

Commit

Permalink
feat: split GenomeAuthoritySystem based on modules (#120)
Browse files Browse the repository at this point in the history
* feat: split GenomeAuthoritySystem based on modules
* feat: add 'requiresOptional' annotation metadata to genome extension systems

The integration with Genome and BasicCrafting is optional for SimpleFarming.

As a component system can only be loaded properly if all it's dependencies are also active, this means that the combined `GenomeAuthoritySystem` is only loaded if **both** Genome and BasicCrafting are active.

By splitting the authority system into `GenomeExtensionAuthoritySystem` and `GenomeCraftingExtensionAuthoritySystem` each extension system can run with the minimal set of required modules.

- `GenomeExtensionAuthoritySystem` (works if at least Genome is loaded)
- `GenomeCraftingExtensionAuthoritySystem` (works if both Genome and Basic Crafting are loaded)

Fixes #119

Co-authored-by: vedant-shroff <[email protected]>
  • Loading branch information
skaldarnar and vedant-shroff authored Aug 16, 2021
1 parent b3c691b commit 636c7a2
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2021 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0

package org.terasology.simpleFarming.systems;

import org.terasology.crafting.events.OnRecipeCrafted;
import org.terasology.engine.entitySystem.entity.EntityRef;
import org.terasology.engine.entitySystem.event.ReceiveEvent;
import org.terasology.engine.entitySystem.systems.BaseComponentSystem;
import org.terasology.engine.entitySystem.systems.RegisterMode;
import org.terasology.engine.entitySystem.systems.RegisterSystem;
import org.terasology.engine.registry.In;
import org.terasology.genome.GenomeRegistry;
import org.terasology.genome.component.GenomeComponent;
import org.terasology.genome.system.SimpleGenomeManager;

/**
* Extension system integrating genetics with basic crafting.
*
* This component system is only loaded if both "Genome" and "BasicCrafting" are enabled.
*/
@RegisterSystem(value = RegisterMode.AUTHORITY, requiresOptional = {"Genome", "BasicCrafting"})
public class GenomeCraftingExtensionAuthoritySystem extends BaseComponentSystem {

@In
private GenomeRegistry genomeRegistry;

/**
* Adds genes to the crafted entity if breeding is possible.
* @param event the OnRecipeCrafted event
* @param entity the crafted entity which is to be modified
*/
@ReceiveEvent
public void onRecipeCraftedEvent(OnRecipeCrafted event, EntityRef entity) {
EntityRef[] ingredients = event.getIngredients();
if (ingredients.length != 2) {
return;
}

if (!(ingredients[0].hasComponent(GenomeComponent.class) || ingredients[1].hasComponent(GenomeComponent.class))) {
return;
}

SimpleGenomeManager genomeManager = new SimpleGenomeManager();
boolean result = genomeManager.applyBreeding(ingredients[0], ingredients[1], entity);
if (entity.hasComponent(GenomeComponent.class)) {
GenomeUtil.updateFilling(genomeRegistry, entity);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// Copyright 2020 The Terasology Foundation
// Copyright 2021 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0
package org.terasology.simpleFarming.systems;

import com.google.common.base.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.crafting.events.OnRecipeCrafted;
import org.terasology.engine.entitySystem.entity.EntityRef;
import org.terasology.engine.entitySystem.event.ReceiveEvent;
import org.terasology.engine.entitySystem.systems.BaseComponentSystem;
Expand All @@ -22,37 +21,34 @@
import org.terasology.genome.breed.mutator.GeneMutator;
import org.terasology.genome.breed.mutator.VocabularyGeneMutator;
import org.terasology.genome.component.GenomeComponent;
import org.terasology.genome.genomeMap.GenomeMap;
import org.terasology.genome.genomeMap.SeedBasedGenomeMap;
import org.terasology.genome.system.SimpleGenomeManager;
import org.terasology.simpleFarming.components.BushDefinitionComponent;
import org.terasology.simpleFarming.events.AddGenomeRetention;
import org.terasology.simpleFarming.events.BeforePlanted;
import org.terasology.simpleFarming.events.ModifyFilling;
import org.terasology.simpleFarming.events.ModifyTint;
import org.terasology.simpleFarming.events.ProduceCreated;
import org.terasology.simpleFarming.events.TransferGenomeEvent;

import javax.annotation.Nullable;

/**
* System managing genetics of all plants
* Extension system managing genetics of all plants.
*
* This component system is only loaded if the "Genome" module is active.
*/
@RegisterSystem(RegisterMode.AUTHORITY)
public class GenomeAuthoritySystem extends BaseComponentSystem {
@RegisterSystem(value = RegisterMode.AUTHORITY, requiresOptional = "Genome")
public class GenomeExtensionAuthoritySystem extends BaseComponentSystem {
private static final Logger LOGGER = LoggerFactory.getLogger(GenomeExtensionAuthoritySystem.class);

@In
private GenomeRegistry genomeRegistry;
@In
private WorldProvider worldProvider;

private static final Logger LOGGER = LoggerFactory.getLogger(GenomeAuthoritySystem.class);

/**
* Called immediately after a bush has been harvested.
* <p>
* Checks the genome component of the bush and assigns it to the seed if it had genes already.
* If the bush did not have a GenomeComponent, it is assigned as this is the first harvest
* A new Genome Definition is created for the family
* Checks the genome component of the bush and assigns it to the seed if it had genes already. If the bush did not have a
* GenomeComponent, it is assigned as this is the first harvest A new Genome Definition is created for the family
*
* @param event the Produce created event
* @param creator the creator(bush) of the produce
Expand Down Expand Up @@ -82,19 +78,14 @@ public void onProduceCreated(ProduceCreated event, EntityRef creator) {
}
produce.addOrSaveComponent(genomeComponent);

GenomeMap genomeMap =
genomeRegistry.getGenomeDefinition(produce.getComponent(GenomeComponent.class).genomeId).getGenomeMap();
float fillingModifier = genomeMap.getProperty("filling", produce.getComponent(GenomeComponent.class).genes,
Float.class);
float newFilling = produce.send(new ModifyFilling(fillingModifier)).filling.getValue();
produce.send(new ModifyTint(newFilling));
GenomeUtil.updateFilling(genomeRegistry, produce);
}

/**
* Called immediately after a bush has been harvested.
* <p>
* Checks the genome component of the seed and transfers it to the plant that was planted
* if the seed does not contain a genome component, the component is assigned on first harvest
* Checks the genome component of the seed and transfers it to the plant that was planted if the seed does not contain a genome
* component, the component is assigned on first harvest
*
* @param event the Before Planted event
* @param plant the plant that is being planted
Expand Down Expand Up @@ -122,8 +113,7 @@ public void onTransferGenomeEvent(TransferGenomeEvent event, EntityRef bush,
}

/**
* Adds the GenomeComponent to the RetainComponentsComponent of an entity Event handler added to maintain Genome
* optional dependency
* Adds the GenomeComponent to the RetainComponentsComponent of an entity Event handler added to maintain Genome optional dependency
*
* @param event the AddGenomeRetention event
* @param entity the entity whose RetainComponentsComponent is to be modified
Expand All @@ -135,34 +125,6 @@ public void addGenomeRetentionEvent(AddGenomeRetention event, EntityRef entity)
entity.addOrSaveComponent(retainComponentsComponent);
}

/**
* Adds genes to the crafted entity if breeding is possible.
* @param event the OnRecipeCrafted event
* @param entity the crafted entity which is to be modified
*/
@ReceiveEvent
public void onRecipeCraftedEvent(OnRecipeCrafted event, EntityRef entity) {
EntityRef ingredients[] = event.getIngredients();
if (ingredients.length != 2) {
return;
}

if (!(ingredients[0].hasComponent(GenomeComponent.class) || ingredients[1].hasComponent(GenomeComponent.class))) {
return;
}

SimpleGenomeManager genomeManager = new SimpleGenomeManager();
boolean result = genomeManager.applyBreeding(ingredients[0], ingredients[1], entity);
if (entity.hasComponent(GenomeComponent.class)) {
GenomeMap genomeMap =
genomeRegistry.getGenomeDefinition(entity.getComponent(GenomeComponent.class).genomeId).getGenomeMap();
float fillingModifier = genomeMap.getProperty("filling", entity.getComponent(GenomeComponent.class).genes,
Float.class);
float newFilling = entity.send(new ModifyFilling(fillingModifier)).filling.getValue();
entity.send(new ModifyTint(newFilling));
}
}

private void addPropertyMap(EntityRef entity, String genomeId) {
SeedBasedGenomeMap genomeMap = new SeedBasedGenomeMap(worldProvider.getSeed().hashCode());
String geneVocabulary = "ABCDEFGHIJK";
Expand All @@ -173,7 +135,7 @@ private void addPropertyMap(EntityRef entity, String genomeId) {
@Nullable
@Override
public Float apply(@Nullable String input) {
return (input.charAt(0) - 'A' + 5f)/5f;
return (input.charAt(0) - 'A' + 5f) / 5f;
}
});
GenomeDefinition genomeDefinition = new GenomeDefinition(continuousBreedingAlgorithm, genomeMap);
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/org/terasology/simpleFarming/systems/GenomeUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2021 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0

package org.terasology.simpleFarming.systems;

import org.terasology.engine.entitySystem.entity.EntityRef;
import org.terasology.genome.GenomeRegistry;
import org.terasology.genome.component.GenomeComponent;
import org.terasology.genome.genomeMap.GenomeMap;
import org.terasology.simpleFarming.events.ModifyFilling;
import org.terasology.simpleFarming.events.ModifyTint;

public final class GenomeUtil {

private GenomeUtil() {
}

public static void updateFilling(GenomeRegistry genomeRegistry, EntityRef entity) {
GenomeComponent genome = entity.getComponent(GenomeComponent.class);
GenomeMap genomeMap = genomeRegistry.getGenomeDefinition(genome.genomeId).getGenomeMap();
float fillingModifier = genomeMap.getProperty("filling", genome.genes, Float.class);

float newFilling = entity.send(new ModifyFilling(fillingModifier)).filling.getValue();

entity.send(new ModifyTint(newFilling));
}
}

0 comments on commit 636c7a2

Please sign in to comment.