Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shearing system #50

Merged
merged 6 commits into from
Jul 6, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions deltas/WildAnimals/prefabs/animals/sheep.prefab
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"Shearable": {
"lastShearingTimestamp": -1,
"isSheared": false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2021 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0

package org.terasology.manualLabor.components;

import org.terasology.engine.entitySystem.Component;

/**
* Attached to entities that can be sheared.
meetcshah19 marked this conversation as resolved.
Show resolved Hide resolved
*/
public class ShearableComponent implements Component {

/**
* Stores the last time the shearing took place. Default -1 for no previous shearing event.
*/
public long lastShearingTimestamp = -1;

/**
* Stores the current state of shearing i.e. whether sheared or not.
*/
public boolean isSheared;
}
112 changes: 112 additions & 0 deletions src/main/java/org/terasology/manualLabor/systems/ShearingSystem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright 2021 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0

package org.terasology.manualLabor.systems;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.engine.core.Time;
import org.terasology.engine.entitySystem.entity.EntityManager;
import org.terasology.engine.entitySystem.entity.EntityRef;
import org.terasology.engine.entitySystem.event.ReceiveEvent;
import org.terasology.engine.entitySystem.prefab.Prefab;
import org.terasology.engine.entitySystem.systems.BaseComponentSystem;
import org.terasology.engine.entitySystem.systems.RegisterSystem;
import org.terasology.engine.logic.characters.events.AttackEvent;
import org.terasology.engine.logic.delay.DelayManager;
import org.terasology.engine.logic.delay.PeriodicActionTriggeredEvent;
import org.terasology.engine.registry.In;
import org.terasology.engine.rendering.assets.material.Material;
import org.terasology.engine.rendering.assets.skeletalmesh.SkeletalMesh;
import org.terasology.engine.rendering.logic.SkeletalMeshComponent;
import org.terasology.gestalt.assets.ResourceUrn;
import org.terasology.gestalt.assets.management.AssetManager;
import org.terasology.manualLabor.components.ShearableComponent;

import java.util.Optional;

/**
* This system is responsible for handling the logic for shearing. A sheep shearing cycle consists of a shearing switching to the model for
* sheared state and switching back to the non sheared state after a certain amount of time.
meetcshah19 marked this conversation as resolved.
Show resolved Hide resolved
*/
@RegisterSystem
public class ShearingSystem extends BaseComponentSystem {
public static final String SHEARING_ITEM = "ManualLabor:CrudeShears";
public static final int HAIR_REGROWTH_TIME = 3 * 60 * 1000; // 3 minutes in ms
public static final String HAIR_REGROWTH_ACTION_ID = "ManualLabor:HairRegrowthAction";
public static final String SHEARED_SHEEP_MESH = "WildAnimals:shearedSheep";
public static final String SHEARED_SHEEP_MATERIAL = "WildAnimals:shearedSheepSkin";
public static final String SHEEP_MESH = "WildAnimals:sheep";
public static final String SHEEP_MATERIAL = "WildAnimals:sheepSkin";
private static final Logger logger = LoggerFactory.getLogger(ShearingSystem.class);

@In
protected Time time;

@In
private EntityManager entityManager;

@In
private AssetManager assetManager;

@In
private DelayManager delayManager;

/**
* Executes changes occurring in event of shearing that is changing the sheared state if the entity is attacked by an appropriate shearing item.
* Also sets a periodic action responsible for triggering hair regrowth.
meetcshah19 marked this conversation as resolved.
Show resolved Hide resolved
*
* @param entityRef Entity being sheared
*/
@ReceiveEvent(components = {ShearableComponent.class})
public void onShearing(AttackEvent event, EntityRef entityRef) {
ShearableComponent component = entityRef.getComponent(ShearableComponent.class);
EntityRef heldItem = event.getDirectCause();
Prefab parentPrefab = heldItem.getParentPrefab();
if (parentPrefab != null && !component.isSheared && parentPrefab.getUrn().equals(new ResourceUrn(SHEARING_ITEM))) {
component.isSheared = true;
component.lastShearingTimestamp = time.getGameTimeInMs();
delayManager.addPeriodicAction(entityRef, HAIR_REGROWTH_ACTION_ID, 0, HAIR_REGROWTH_TIME / 20);
switchPrefab(entityRef, SHEARED_SHEEP_MESH, SHEARED_SHEEP_MATERIAL);
}
}

/**
* Periodically checks if enough time has elapsed for hair regrowth and executes events to regrow.
*
* @param entity Entity to regrow hair
*/
@ReceiveEvent
public void onPeriodicActionTriggered(PeriodicActionTriggeredEvent event, EntityRef entity) {
if (event.getActionId().equals(HAIR_REGROWTH_ACTION_ID)) {
ShearableComponent shearableComponent = entity.getComponent(ShearableComponent.class);
if (shearableComponent.isSheared && (time.getGameTimeInMs() - shearableComponent.lastShearingTimestamp) > HAIR_REGROWTH_TIME) {
shearableComponent.isSheared = false;
delayManager.cancelPeriodicAction(entity, HAIR_REGROWTH_ACTION_ID);
switchPrefab(entity, SHEEP_MESH, SHEEP_MATERIAL);
}
}
}

/**
* Switches the model for the provided entity
*
* @param entity entity whose model is to be switched
* @param meshURI mesh URI for the new model
* @param materialURI material URI for the new model
*/
private void switchPrefab(EntityRef entity, String meshURI, String materialURI) {
SkeletalMeshComponent skeletalMeshComponent = entity.getComponent(SkeletalMeshComponent.class);
if (skeletalMeshComponent != null) {
Optional<SkeletalMesh> skeletalMesh = assetManager.getAsset(meshURI,
SkeletalMesh.class);
Optional<Material> shearedMaterial = assetManager.getAsset(materialURI,
Material.class);
if (skeletalMesh.isPresent() && shearedMaterial.isPresent()) {
skeletalMeshComponent.mesh = skeletalMesh.get();
skeletalMeshComponent.material = shearedMaterial.get();
}
entity.saveComponent(skeletalMeshComponent);
}
}
}