package net.zomis.cardshifter.ecs.effects;
import java.util.function.*;
import com.cardshifter.modapi.base.Component;
import com.cardshifter.modapi.base.ECSGame;
import com.cardshifter.modapi.base.ECSSystem;
import com.cardshifter.modapi.base.Entity;
import com.cardshifter.modapi.cards.BattlefieldComponent;
import com.cardshifter.modapi.cards.ZoneChangeEvent;
import com.cardshifter.modapi.events.EntityRemoveEvent;
import com.cardshifter.modapi.events.IEvent;
import com.cardshifter.modapi.resources.ECSResource;
import com.cardshifter.modapi.resources.ECSResourceData;
import com.cardshifter.modapi.resources.ResourceRetriever;
public class Effects {
public <T extends IEvent> Function<Entity, ECSSystem> triggerSystem(Class<T> eventClass, BiPredicate<Entity, T> interestingEvents, BiConsumer<Entity, T> handler) {
return e -> new ECSSystem() {
@Override
public void startGame(ECSGame game) {
game.getEvents().registerHandlerAfter(this, eventClass, this::event);
}
private void event(T event) {
if (interestingEvents.test(e, event)) {
handler.accept(e, event);
}
}
};
}
public <T extends IEvent> Function<Entity, ECSSystem> triggerSystemBefore(Class<T> eventClass, BiPredicate<Entity, T> interestingEvents, BiConsumer<Entity, T> handler) {
return e -> new ECSSystem() {
@Override
public void startGame(ECSGame game) {
game.getEvents().registerHandlerBefore(this, eventClass, this::event);
}
private void event(T event) {
if (interestingEvents.test(e, event)) {
handler.accept(e, event);
}
}
};
}
public EffectComponent giveTarget(ECSResource resource, int value, IntUnaryOperator operator) {
ResourceRetriever res = ResourceRetriever.forResource(resource);
GameEffect effect = (entity, event) -> event.getAction().getAllTargets().forEach(e -> {
ECSResourceData data = res.resFor(e);
data.change(value);
data.set(operator.applyAsInt(data.get()));
});
return new EffectComponent("Give target " + value + " " + resource, effect);
}
public <T extends IEvent> EffectComponent giveSelf(Function<Entity, ECSSystem> system) {
GameEffect effect = (entity, event) -> entity.getGame().addSystem(new InGameSystem(entity, system.apply(entity)));
return new EffectComponent("Give target " + system, effect);
}
public EffectComponent toSelf(Consumer<Entity> effect) {
return new EffectComponent(effect.toString(), (entity, event) -> effect.accept(event.getEntity()));
}
public Component described(String description, EffectComponent effectComponent) {
return new EffectComponent(description, effectComponent.getEffect());
}
public static class InGameSystem implements ECSSystem {
private final Entity owningEntity;
private final ECSSystem systemToRemove;
public InGameSystem(Entity owningEntity, ECSSystem system) {
this.owningEntity = owningEntity;
this.systemToRemove = system;
}
@Override
public void startGame(ECSGame game) {
game.getEvents().registerHandlerAfter(systemToRemove, EntityRemoveEvent.class, this::removeCheck);
game.getEvents().registerHandlerAfter(systemToRemove, ZoneChangeEvent.class, this::removeCheck);
game.addSystem(systemToRemove);
}
private void removeCheck(EntityRemoveEvent event) {
if (event.getEntity() == owningEntity) {
event.getEntity().getGame().removeSystem(systemToRemove);
}
}
private void removeCheck(ZoneChangeEvent event) {
if (event.getDestination() instanceof BattlefieldComponent) {
return;
}
if (event.getCard() == owningEntity) {
event.getCard().getGame().removeSystem(systemToRemove);
}
}
}
}