Improve MapObject to support CompletableFuture actions
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user