JavaECS/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentArray.java

114 lines
4.1 KiB
Java

package nz.ac.massey.javaecs;
/**
* Component Array
* Defines the data structure that component data is stored under.
* Has a list of defined objects, and two associative maps that link
* the position of the data with the entity number.
*
* Therefore, every entity in entityComponentDataMap is valid, so
* no additional sorting is required
*
*
* Contributors:
* Brychan Dempsey - brychand@hotmail.com
*
*/
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
class ComponentArray{
// The object data array
private List<Object> componentArray = new ArrayList<>();
// The mappings between data and entity
private Map<Integer, Integer> entityComponentDataMap = new HashMap<>();
private Map<Integer, Integer> componentDataEntityMap = new HashMap<>();
/**
* Gets the data Object associated with the entity.
* @param entity the entity to find data for
* @return the Object if the data exists, else null
*/
protected Object getData(int entity){
try{
return componentArray.get(entityComponentDataMap.get(entity));
}
catch (NullPointerException ex){
ECS.writeErr("Attempted to retrieve non-existent data");
return null;
}
catch (IndexOutOfBoundsException e){
ECS.writeErr("Index out-of-bounds");
return null;
}
}
/**
* Inserts the provided component and associates it with the entity.
* @param entity the entity to associate data to
* @param component the component data
* @return true if successful, false if the entity is already subscribed to the component
*/
protected boolean insertData(int entity, Object component){
if (entityComponentDataMap.containsKey(entity)){
ECS.writeErr("Entity is already subscribed to the component");
return false;
}
// Put data at the end of the componentArray
int index = componentArray.size();
entityComponentDataMap.put(entity, index);
componentDataEntityMap.put(index, entity);
componentArray.add(component);
return true;
}
/**
* Moves component data to another entity. (Copies, deletes and inserts data)
* @param sourceEntity
* @param destinationEntity
* @return 0 if successful, -1 if the object is null, -2 if a NullPointerException occurred, and -3 if inserting data failed
*/
protected int moveData(int sourceEntity, int destinationEntity){
try{
Object data = entityComponentDataMap.get(sourceEntity);
if (data == null) return -1;
else if (insertData(destinationEntity, data))
{
removeData(sourceEntity);
return 0;
}
else return -3;
}
catch (NullPointerException e){
return -2;
}
}
/**
* Removes the data associated with the entity.
* @param entity the entity to remove the data from
* @return true if the data was removed. If the data isn't found then returns false
*/
protected boolean removeData(int entity){
if (!entityComponentDataMap.containsKey(entity)){
ECS.writeErr("Attempted to remove non-existent entity");
return false;
}
// Get the componentData index of the entity
int removedComponentDataIndex = entityComponentDataMap.get(entity);
// Replace the removed component with the last component in the array
componentArray.set(removedComponentDataIndex, componentArray.get(componentArray.size() -1));
// update the data positions in the map
int lastEntity = componentDataEntityMap.get(componentArray.size()-1);
entityComponentDataMap.replace(lastEntity, removedComponentDataIndex);
componentDataEntityMap.replace(removedComponentDataIndex, lastEntity);
// Finally, remomve the last elements
entityComponentDataMap.remove(entity);
componentDataEntityMap.remove(componentArray.size() -1);
componentArray.remove(componentArray.size() -1);
return true;
}
}