Skip to content
33 changes: 33 additions & 0 deletions engine/src/main/java/org/destinationsol/components/Health.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2020 The Terasology Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.destinationsol.components;

import org.terasology.gestalt.entitysystem.component.Component;

/**
* Contains information about the health of an entity.
*/
public final class Health implements Component<Health> {

public int maxHealth = 30;
public int currentHealth = 30;

@Override
public void copy(Health other) {
this.maxHealth = other.maxHealth;
this.currentHealth = other.currentHealth;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
public class EntitySystemManager {

private static EntityManager entityManager;
private static EventSystem eventSystem = new EventSystemImpl();
private EventSystem eventSystem = new EventSystemImpl();
private static EventReceiverMethodSupport eventReceiverMethodSupport = new EventReceiverMethodSupport();

public EntitySystemManager(ModuleEnvironment environment, ComponentManager componentManager){
public EntitySystemManager(ModuleEnvironment environment, ComponentManager componentManager) {

List<ComponentStore<?>> stores = Lists.newArrayList();
for (Class<? extends Component> componentType : environment.getSubtypesOf(Component.class)) {
Expand All @@ -51,9 +51,9 @@ public EntitySystemManager(ModuleEnvironment environment, ComponentManager compo

entityManager = new CoreEntityManager(stores);

for (Class<?> eventReceivers : environment.getTypesAnnotatedWith(RegisterEventReceivers.class)) {
for (Class<? extends EventReceiver> eventReceiver : environment.getSubtypesOf(EventReceiver.class)) {
try {
eventReceiverMethodSupport.register(eventReceivers.newInstance(), eventSystem);
eventReceiverMethodSupport.register(eventReceiver.newInstance(), eventSystem);
} catch (Exception e) {
e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
*/
package org.destinationsol.entitysystem;

public @interface RegisterEventReceivers {
public interface EventReceiver {
}
34 changes: 34 additions & 0 deletions engine/src/main/java/org/destinationsol/events/DamageEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2020 The Terasology Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.destinationsol.events;

import org.terasology.gestalt.entitysystem.event.Event;

/**
* Event that contains information about the damage an entity receives.
*/
public class DamageEvent implements Event {

private int damage;

public DamageEvent(int damage) {
this.damage = damage;
}

public int getDamage() {
return damage;
}
}
56 changes: 56 additions & 0 deletions engine/src/main/java/org/destinationsol/systems/DamageSystem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2020 The Terasology Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.destinationsol.systems;

import org.destinationsol.components.Health;
import org.destinationsol.entitysystem.ComponentSystem;
import org.destinationsol.entitysystem.EventReceiver;
import org.destinationsol.events.DamageEvent;
import org.terasology.gestalt.entitysystem.entity.EntityRef;
import org.terasology.gestalt.entitysystem.event.EventResult;
import org.terasology.gestalt.entitysystem.event.ReceiveEvent;

/**
* When a damage event happens to an entity with a health component, this system reads the damage from that event and
* lowers its health by that amount. If it would lower the health to less than zero, it's reduced to zero instead. If
* the damage is a negative amount, nothing happens.
*/
public class DamageSystem implements EventReceiver {

/**
* Handles a damage event done to an entity with a Health component.
*
* @param event the damage event that is occurring
* @param entity the entity that the damage is happening to
* @return the event should be processed by other systems, if there are
*/
@ReceiveEvent(components = Health.class)
public EventResult onDamage(DamageEvent event, EntityRef entity) {
if (event.getDamage() <= 0) {
return EventResult.CONTINUE;
}
if (entity.getComponent(Health.class).isPresent()) {
Health health = entity.getComponent(Health.class).get();
int newHealthAmount = health.currentHealth - event.getDamage();
if (newHealthAmount < 0) {
newHealthAmount = 0;
}
health.currentHealth = newHealthAmount;
entity.setComponent(health);
}
return EventResult.CONTINUE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2020 The Terasology Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.destinationsol.systems.DamageSystemTests;

import org.destinationsol.components.Health;
import org.destinationsol.entitysystem.EntitySystemManager;
import org.destinationsol.events.DamageEvent;
import org.destinationsol.modules.ModuleManager;
import org.junit.Before;
import org.junit.Test;
import org.terasology.gestalt.entitysystem.component.management.ComponentManager;
import org.terasology.gestalt.entitysystem.entity.EntityRef;

import static org.junit.Assert.assertEquals;

/**
* Test to ensure that a damage event with a negative amount of damage doesn't add health.
*/
public class NonNegativeDamageTest {

private ModuleManager moduleManager;
private EntitySystemManager entitySystemManager;

@Before
public void setUp() throws Exception {
moduleManager = new ModuleManager();
moduleManager.init();
entitySystemManager = new EntitySystemManager(moduleManager.getEnvironment(), new ComponentManager());
}

@Test
public void testNegativeDamageHasNoEffect() {
EntityRef entity = entitySystemManager.getEntityManager().createEntity(new Health());
if (entity.getComponent(Health.class).isPresent()) {
Health health = entity.getComponent(Health.class).get();
health.maxHealth = 50;
health.currentHealth = 50;
entity.setComponent(health);
}
DamageEvent event = new DamageEvent(-30);

entitySystemManager.sendEvent(event, new Health());

assertEquals(50, entity.getComponent(Health.class).get().currentHealth);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2020 The Terasology Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.destinationsol.systems.DamageSystemTests;

import org.destinationsol.components.Health;
import org.destinationsol.entitysystem.EntitySystemManager;
import org.destinationsol.events.DamageEvent;
import org.destinationsol.modules.ModuleManager;
import org.junit.Before;
import org.junit.Test;
import org.terasology.gestalt.entitysystem.component.management.ComponentManager;
import org.terasology.gestalt.entitysystem.entity.EntityRef;

import static org.junit.Assert.assertEquals;

/**
* Test to ensure that a damage event that would make the health become negative reduces it to zero instead.
*/
public class NonNegativeHealthTest {
private ModuleManager moduleManager;
private EntitySystemManager entitySystemManager;

@Before
public void setUp() throws Exception {
moduleManager = new ModuleManager();
moduleManager.init();
entitySystemManager = new EntitySystemManager(moduleManager.getEnvironment(), new ComponentManager());
}

@Test
public void testDamageDoesntMakeHealthBecomeNegative() {
EntityRef entity = entitySystemManager.getEntityManager().createEntity(new Health());
if (entity.getComponent(Health.class).isPresent()) {
Health health = entity.getComponent(Health.class).get();
health.maxHealth = 50;
health.currentHealth = 50;
entity.setComponent(health);
}
DamageEvent event = new DamageEvent(60);

entitySystemManager.sendEvent(event, new Health());

assertEquals(0, entity.getComponent(Health.class).get().currentHealth);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2020 The Terasology Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.destinationsol.systems.DamageSystemTests;

import org.destinationsol.components.Health;
import org.destinationsol.entitysystem.EntitySystemManager;
import org.destinationsol.events.DamageEvent;
import org.destinationsol.modules.ModuleManager;
import org.junit.Before;
import org.junit.Test;
import org.terasology.gestalt.entitysystem.component.management.ComponentManager;
import org.terasology.gestalt.entitysystem.entity.EntityRef;

import static org.junit.Assert.assertEquals;

/**
* Test to ensure that a damage event to an entity lowers that entity's health by that amount.
*/
public class OnDamageTest {

private ModuleManager moduleManager;
private EntitySystemManager entitySystemManager;

@Before
public void setUp() throws Exception {
moduleManager = new ModuleManager();
moduleManager.init();
entitySystemManager = new EntitySystemManager(moduleManager.getEnvironment(), new ComponentManager());
}

@Test
public void testOnDamage() {
EntityRef entity = entitySystemManager.getEntityManager().createEntity(new Health());
if (entity.getComponent(Health.class).isPresent()) {
Health health = entity.getComponent(Health.class).get();
health.maxHealth = 50;
health.currentHealth = 50;
entity.setComponent(health);
}
DamageEvent event = new DamageEvent(30);

entitySystemManager.sendEvent(event, new Health());

assertEquals(20, entity.getComponent(Health.class).get().currentHealth);
}

}