package coffee.liz.ecs.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; @Getter @Builder @RequiredArgsConstructor @AllArgsConstructor @Data public class Entity { /** Unique id. */ private final int id; /** Instances of {@link Component}s. */ @Builder.Default private Map, Component> componentMap = Collections.synchronizedMap(new HashMap<>()); /** * Check if entity has component type. * * @param componentType * the {@link Component} class * @return true if component exists */ public boolean has(final Class componentType) { return componentMap.containsKey(componentType); } /** * Check if entity has all component types. * * @param components * collection of {@link Component} classes * @return true if all components exist */ public boolean hasAll(final Collection> components) { return components.stream().allMatch(this::has); } /** * Get component by type. * * @param componentType * the {@link Component} class * @param * component type * @return the component or throw {@link IllegalArgumentException} */ @SuppressWarnings("unchecked") public C get(final Class componentType) { final C component = (C) componentMap.get(componentType); if (component == null) { throw new IllegalArgumentException( "Entity with id " + getId() + " does not have required component " + componentType.getSimpleName()); } return component; } /** * Add component to entity. * * @param component * the {@link Component} to add * @param * component type * @return this {@link Entity} for chaining */ public Entity add(final C component) { componentMap.put(component.getKey(), component); return this; } /** * Remove component from entity. * * @param componentType * the {@link Component} class to remove * @param * component type * @return this {@link Entity} for chaining */ public Entity remove(final Class componentType) { componentMap.remove(componentType); return this; } /** * Get all component types. * * @return set of {@link Component} classes */ public Set> componentTypes() { return componentMap.keySet(); } }