Improve MapObject to support CompletableFuture actions

This commit is contained in:
2022-08-31 23:46:12 +02:00
parent 5d9c7e6de2
commit 6678c352bb
3 changed files with 98 additions and 48 deletions

View File

@@ -4,6 +4,8 @@ import com.bartlomiejpluta.demo.world.item.Item;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
public class Chest extends MapObject { public class Chest extends MapObject {
@Getter @Getter
private final Item[] content = new Item[Enemy.MAX_LOOT]; private final Item[] content = new Item[Enemy.MAX_LOOT];
@@ -13,13 +15,8 @@ public class Chest extends MapObject {
} }
@Override @Override
protected void interact() { protected CompletableFuture<?> interact() {
runner.getGuiManager().openChestWindow(this); return runner.getGuiManager().openChestWindow(this);
}
@Override
protected boolean shouldGoFurther(MapObject object) {
return runner.getGuiManager().openedWindows() == 0;
} }
public Chest addItem(Item item) { public Chest addItem(Item item) {

View File

@@ -4,6 +4,8 @@ import A.maps;
import com.bartlomiejpluta.demo.runner.DemoRunner; import com.bartlomiejpluta.demo.runner.DemoRunner;
import lombok.NonNull; import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
public class Door extends MapObject { public class Door extends MapObject {
private final String mapUid; private final String mapUid;
private final int targetX; private final int targetX;
@@ -22,14 +24,13 @@ public class Door extends MapObject {
} }
@Override @Override
protected void interact() { protected CompletableFuture<?> interact() {
context.openMap(mapUid); context.openMap(mapUid);
context.getMap().getObjectLayer(layerId).addEntity(player); context.getMap().getObjectLayer(layerId).addEntity(player);
player.setCoordinates(targetX, targetY); player.setCoordinates(targetX, targetY);
}
@Override reset();
protected boolean shouldGoFurther(MapObject object) {
return true; return CompletableFuture.completedFuture(null);
} }
} }

View File

@@ -7,16 +7,29 @@ import com.bartlomiejpluta.base.util.path.PathExecutor;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.CompletableFuture.completedFuture;
public abstract class MapObject extends NamedCharacter { public abstract class MapObject extends NamedCharacter {
private final PathExecutor<MapObject> pathExecutor = new PathExecutor<>(this); private static final float INTERVAL = 0.05f;
private final DB.model.MapObjectModel template; private static final float COOLDOWN = 0.5f;
private final Short frame; protected final PathExecutor<MapObject> pathExecutor = new PathExecutor<>(this);
private final String interactSound; private final String interactSound;
protected boolean interacting = false;
private Supplier<CompletableFuture<?>> beforeAll;
private Supplier<CompletableFuture<?>> before;
private Supplier<CompletableFuture<?>> after;
private Supplier<CompletableFuture<?>> afterAll;
private CompletableFuture<?> future;
@Getter @Getter
private final String name; private final String name;
private boolean interacting = false;
public MapObject(@NonNull String id) { public MapObject(@NonNull String id) {
this(DB.dao.map_object.find(id)); this(DB.dao.map_object.find(id));
@@ -24,59 +37,90 @@ public abstract class MapObject extends NamedCharacter {
public MapObject(@NonNull DB.model.MapObjectModel template) { public MapObject(@NonNull DB.model.MapObjectModel template) {
super(ContextHolder.INSTANCE.getContext().createCharacter(A.charsets.get(template.getCharset()).uid)); super(ContextHolder.INSTANCE.getContext().createCharacter(A.charsets.get(template.getCharset()).uid));
this.template = template; short frame = requireNonNull(template.getFrame());
this.frame = template.getFrame();
this.name = template.getName(); this.name = template.getName();
this.interactSound = A.sounds.get(template.getInteractSound()).uid; this.interactSound = A.sounds.get(template.getInteractSound()).uid;
setBlocking(true); setBlocking(true);
disableAnimation(); disableAnimation();
if (frame != null) { setAnimationFrame(frame);
setAnimationFrame(frame); pathExecutor.setRepeat(1);
}
pathExecutor.setPath( pathExecutor.setPath(new CharacterPath<MapObject>()
frame != null .run(this::startInteraction)
? new CharacterPath<MapObject>() .turn(Direction.LEFT, frame)
.run(this::startInteraction) .wait(INTERVAL)
.turn(Direction.LEFT, frame) .turn(Direction.RIGHT, frame)
.wait(0.05f) .wait(INTERVAL)
.turn(Direction.RIGHT, frame) .turn(Direction.UP, frame)
.wait(0.05f) .wait(INTERVAL)
.turn(Direction.UP, frame) .run(this::runInteraction)
.wait(0.25f) .suspend(() -> future)
.run(this::interact) .wait(INTERVAL)
.suspend(this::shouldGoFurther) .turn(Direction.RIGHT, frame)
.wait(0.25f) .wait(INTERVAL)
.turn(Direction.RIGHT, frame) .turn(Direction.LEFT, frame)
.wait(0.05f) .wait(INTERVAL)
.turn(Direction.LEFT, frame) .turn(Direction.DOWN, frame)
.wait(0.05f) .run(this::finishInteraction)
.turn(Direction.DOWN, frame) .suspend(() -> future)
.wait(0.5f) .wait(COOLDOWN)
.run(this::finishInteraction) .run(this::completeInteraction)
: new CharacterPath<>()
); );
} }
protected boolean shouldGoFurther(MapObject object) { public MapObject beforeAll(@NonNull Supplier<CompletableFuture<?>> action) {
return true; this.beforeAll = action;
return this;
}
public MapObject before(@NonNull Supplier<CompletableFuture<?>> action) {
this.before = action;
return this;
}
public MapObject after(@NonNull Supplier<CompletableFuture<?>> action) {
this.after = action;
return this;
}
public MapObject afterAll(@NonNull Supplier<CompletableFuture<?>> action) {
this.afterAll = action;
return this;
} }
public void triggerInteraction() { public void triggerInteraction() {
interacting = true; if (interacting) {
return;
}
pathExecutor.reset();
if (beforeAll != null) {
beforeAll.get().thenRun(() -> interacting = true);
} else {
interacting = true;
}
} }
protected abstract void interact(); private void runInteraction() {
this.future = (before != null ? before.get() : completedFuture(null))
.thenCompose(v -> interact())
.thenCompose(v -> (after != null ? after.get() : completedFuture(null)));
}
protected void startInteraction() { private void startInteraction() {
if (interactSound != null) { if (interactSound != null) {
context.playSound(interactSound); context.playSound(interactSound);
} }
} }
protected void finishInteraction() { private void finishInteraction() {
this.future = afterAll != null ? afterAll.get() : completedFuture(null);
}
private void completeInteraction() {
interacting = false; interacting = false;
} }
@@ -86,4 +130,12 @@ public abstract class MapObject extends NamedCharacter {
pathExecutor.execute(getLayer(), dt); pathExecutor.execute(getLayer(), dt);
} }
} }
protected final void reset() {
setFaceDirection(Direction.DOWN);
pathExecutor.reset();
interacting = false;
}
protected abstract CompletableFuture<?> interact();
} }