feat: Make Dialog serializable
This commit is contained in:
@@ -170,31 +170,35 @@ public class DialogEventHandler extends AbstractEventHandler<Dialog> {
|
||||
}
|
||||
|
||||
private void next(OnEnd onEnd, TerminalPosition start, TerminalSize size) throws InterruptedException {
|
||||
Thread.sleep(1000);
|
||||
if (onEnd instanceof OnEnd.Continue(Dialog nextDialog)) {
|
||||
Thread.sleep(1000);
|
||||
for (int y = start.getRow(); y < start.getRow() + size.getRows(); y++) {
|
||||
for (int x = start.getColumn(); x < start.getColumn() + size.getColumns(); x++) {
|
||||
screenBuffer.getGlobalOverrideBuffer()[y][x] = new Empty();
|
||||
}
|
||||
}
|
||||
|
||||
if (nextDialog == null) {
|
||||
dialogState.setCurrentDialog(null);
|
||||
eventManager.emitEvent(
|
||||
new RerenderScreen(
|
||||
new RerenderScreen.ScreenPart(
|
||||
start,
|
||||
new TerminalPosition(start.getColumn() + size.getColumns(), start.getRow() + size.getRows())
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
eventManager.emitEvent(nextDialog);
|
||||
}
|
||||
eventManager.emitEvent(nextDialog);
|
||||
} else if (onEnd instanceof OnEnd.RunCode(Runnable runnable, OnEnd end)) {
|
||||
dependencyManager.inject(runnable);
|
||||
runnable.run();
|
||||
next(end, start, size);
|
||||
} else if (onEnd instanceof OnEnd.End) {
|
||||
for (int y = start.getRow(); y < start.getRow() + size.getRows(); y++) {
|
||||
for (int x = start.getColumn(); x < start.getColumn() + size.getColumns(); x++) {
|
||||
screenBuffer.getGlobalOverrideBuffer()[y][x] = new Empty();
|
||||
}
|
||||
}
|
||||
|
||||
dialogState.setCurrentDialog(null);
|
||||
eventManager.emitEvent(
|
||||
new RerenderScreen(
|
||||
new RerenderScreen.ScreenPart(
|
||||
start,
|
||||
new TerminalPosition(start.getColumn() + size.getColumns(), start.getRow() + size.getRows())
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
package cz.jzitnik.client.game.dialog;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import cz.jzitnik.client.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class Dialog implements Event {
|
||||
/**
|
||||
* Characters per second
|
||||
*/
|
||||
private int typingSpeed = 10;
|
||||
private final int typingSpeed = 10;
|
||||
private final String text;
|
||||
private final OnEnd onEnd;
|
||||
|
||||
@JsonCreator
|
||||
public Dialog(
|
||||
@JsonProperty("text") String text,
|
||||
@JsonProperty("onEnd") OnEnd onEnd
|
||||
) {
|
||||
this.text = text;
|
||||
this.onEnd = onEnd;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,46 @@
|
||||
package cz.jzitnik.client.game.dialog;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
@JsonTypeInfo(
|
||||
use = JsonTypeInfo.Id.NAME,
|
||||
property = "type"
|
||||
)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = OnEnd.Continue.class, name = "continue"),
|
||||
@JsonSubTypes.Type(value = OnEnd.AskQuestion.class, name = "ask_question"),
|
||||
@JsonSubTypes.Type(value = OnEnd.End.class, name = "end"),
|
||||
})
|
||||
public interface OnEnd {
|
||||
record RunCode(Runnable runnable, OnEnd onEnd) implements OnEnd {}
|
||||
record End() implements OnEnd {}
|
||||
|
||||
record RunCode(Runnable runnable, OnEnd onEnd) implements OnEnd {} // TODO: Serialize
|
||||
|
||||
record Continue(Dialog nextDialog) implements OnEnd {
|
||||
@JsonCreator
|
||||
public Continue(@JsonProperty("nextDialog") Dialog nextDialog) {
|
||||
this.nextDialog = nextDialog;
|
||||
}
|
||||
}
|
||||
|
||||
record AskQuestion(Answer[] answers) implements OnEnd {
|
||||
@JsonCreator
|
||||
public AskQuestion(@JsonProperty("answers") Answer[] answers) {
|
||||
this.answers = answers;
|
||||
}
|
||||
|
||||
public record Answer(String answer, Dialog dialog) {
|
||||
@JsonCreator
|
||||
public Answer(
|
||||
@JsonProperty("answer") String answer,
|
||||
@JsonProperty("dialog") Dialog dialog
|
||||
) {
|
||||
this.answer = answer;
|
||||
this.dialog = dialog;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package cz.jzitnik.client.game.mobs;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import cz.jzitnik.client.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.client.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.client.game.ResourceManager;
|
||||
import cz.jzitnik.common.models.coordinates.RoomPart;
|
||||
import cz.jzitnik.client.game.dialog.Dialog;
|
||||
import cz.jzitnik.client.game.mobs.tasks.MobRoomTask;
|
||||
@@ -10,14 +14,20 @@ import cz.jzitnik.client.states.DialogState;
|
||||
import cz.jzitnik.client.utils.events.EventManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
@Slf4j
|
||||
public abstract class DialogMob extends Mob {
|
||||
public class DialogMob extends Mob {
|
||||
protected Dialog dialog;
|
||||
|
||||
public DialogMob(BufferedImage texture, MobRoomTask[] tasks, RoomCords cords, RoomPart collider, Dialog dialog) {
|
||||
super(texture, tasks, cords, collider);
|
||||
@JsonCreator
|
||||
public DialogMob(
|
||||
@JsonProperty("texture") ResourceManager.Resource texture,
|
||||
@JsonProperty("tasks") MobRoomTask[] tasks,
|
||||
@JsonProperty("cords") RoomCords cords,
|
||||
@JsonProperty("collider") RoomPart collider,
|
||||
@JsonProperty("dialog") Dialog dialog,
|
||||
@JacksonInject ResourceManager resourceManager
|
||||
) {
|
||||
super(resourceManager.getResource(texture), tasks, cords, collider);
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,216 +1,367 @@
|
||||
# =========================
|
||||
# START ROOM
|
||||
# Intro NPC explains the goal + starter chest
|
||||
# =========================
|
||||
- id: "spawn"
|
||||
texture: "ROOM1"
|
||||
#mobs:
|
||||
# - type: "hittable_drops"
|
||||
# texture: "PLAYER_FRONT"
|
||||
# cords:
|
||||
# x: 100
|
||||
# y: 100
|
||||
# collider:
|
||||
# start:
|
||||
# x: 0
|
||||
# y: 52
|
||||
# end:
|
||||
# x: 44
|
||||
# y: 78
|
||||
# health: 10
|
||||
# itemsDrops:
|
||||
# - name: "Apple"
|
||||
# type:
|
||||
# name: "food"
|
||||
# addHealth: 1
|
||||
# texture: "APPLE"
|
||||
# tasks:
|
||||
# - type: "blind_following_player"
|
||||
# speed: 1
|
||||
# updateRateMs: 100
|
||||
# - type: "attacking_player"
|
||||
# damage: 5
|
||||
# reach: 15
|
||||
# updateRateMs: 500
|
||||
west: "empty"
|
||||
mobs:
|
||||
- type: "dialog"
|
||||
texture: "OLD_MAN"
|
||||
cords: { x: 90, y: 90 }
|
||||
collider:
|
||||
start: { x: 0, y: 52 }
|
||||
end: { x: 44, y: 78 }
|
||||
dialog:
|
||||
text: "You fell down here too? This cave is cursed..."
|
||||
onEnd:
|
||||
type: continue
|
||||
nextDialog:
|
||||
text: "The only way out is guarded by a beast deep inside."
|
||||
onEnd:
|
||||
type: continue
|
||||
nextDialog:
|
||||
text: "Kill it. Bring its skin to the Key Keeper."
|
||||
onEnd:
|
||||
type: continue
|
||||
nextDialog:
|
||||
text: "He will give you the key to the final gate."
|
||||
onEnd: { type: end }
|
||||
|
||||
objects:
|
||||
- objectType: "chest"
|
||||
cords: { x: 120, y: 50 }
|
||||
items:
|
||||
- id: 100
|
||||
name: "Rusty Sword"
|
||||
type: { name: "weapon_sword", dealDamage: 2 }
|
||||
texture: "RUSTY_SWORD"
|
||||
- id: 101
|
||||
name: "Apple"
|
||||
type: { name: "food", addHealth: 2 }
|
||||
texture: "APPLE"
|
||||
|
||||
west: "empty_a"
|
||||
east: "truhlaright"
|
||||
north: null
|
||||
north: "filler_entrance_north"
|
||||
south: null
|
||||
|
||||
|
||||
|
||||
# =========================
|
||||
# LOOT ROOM 1
|
||||
# =========================
|
||||
- id: "truhlaright"
|
||||
texture: "ROOM1"
|
||||
objects:
|
||||
- objectType: "chest"
|
||||
cords:
|
||||
x: 100
|
||||
y: 45
|
||||
cords: { x: 100, y: 45 }
|
||||
items:
|
||||
- id: 1
|
||||
name: "Wooden sword"
|
||||
type:
|
||||
name: "weapon_sword"
|
||||
dealDamage: 1
|
||||
texture: "WOODEN_SWORD"
|
||||
name: "Dagger"
|
||||
type: { name: "weapon_dagger", dealDamage: 2, attackCooldownMs: 300 }
|
||||
texture: "DAGGER"
|
||||
- id: 2
|
||||
name: "Apple"
|
||||
type:
|
||||
name: "food"
|
||||
addHealth: 1
|
||||
texture: "APPLE"
|
||||
name: "Bread"
|
||||
type: { name: "food", addHealth: 3 }
|
||||
texture: "BREAD"
|
||||
- id: 9
|
||||
name: "Shiny Rock"
|
||||
type: { name: "junk" }
|
||||
texture: "ROCK"
|
||||
colliders:
|
||||
- start:
|
||||
x: 100
|
||||
y: 45
|
||||
end:
|
||||
x: 140
|
||||
y: 67
|
||||
- start: { x: 100, y: 45 }
|
||||
end: { x: 140, y: 67 }
|
||||
west: "spawn"
|
||||
east: null
|
||||
east: "filler_1"
|
||||
north: "klicnik"
|
||||
south: null
|
||||
south: "filler_south_1"
|
||||
|
||||
- id: "empty"
|
||||
|
||||
|
||||
# =========================
|
||||
# KEY KEEPER (QUEST NPC)
|
||||
# =========================
|
||||
- id: "klicnik"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "spawn"
|
||||
north: "truhlatop"
|
||||
south: null
|
||||
mobs:
|
||||
- type: "dialog"
|
||||
texture: "KEY_KEEPER"
|
||||
cords: { x: 100, y: 100 }
|
||||
collider:
|
||||
start: { x: 0, y: 52 }
|
||||
end: { x: 44, y: 78 }
|
||||
dialog:
|
||||
text: "Want to leave? Bring me the beast's skin."
|
||||
onEnd:
|
||||
type: ask_question
|
||||
answers:
|
||||
- answer: "I have it"
|
||||
requirement:
|
||||
item: "quest_item_boss_skin"
|
||||
dialog:
|
||||
text: "Well done. Here is the key."
|
||||
giveItem:
|
||||
id: 300
|
||||
name: "Cave Exit Key"
|
||||
type: { name: "quest_item_final_key" }
|
||||
texture: "KEY"
|
||||
onEnd: { type: end }
|
||||
- answer: "Not yet"
|
||||
dialog:
|
||||
text: "Then go back before it finds you."
|
||||
onEnd: { type: end }
|
||||
|
||||
- id: "truhlatop"
|
||||
texture: "ROOM1"
|
||||
objects:
|
||||
- objectType: "chest"
|
||||
cords:
|
||||
x: 100
|
||||
y: 45
|
||||
items:
|
||||
- id: 3
|
||||
name: "Wooden sword"
|
||||
type:
|
||||
name: "weapon_sword"
|
||||
dealDamage: 1
|
||||
texture: "WOODEN_SWORD"
|
||||
- id: 4
|
||||
name: "Apple"
|
||||
type:
|
||||
name: "food"
|
||||
addHealth: 1
|
||||
texture: "APPLE"
|
||||
colliders:
|
||||
- start:
|
||||
x: 100
|
||||
y: 45
|
||||
end:
|
||||
x: 140
|
||||
y: 67
|
||||
west: "empty2"
|
||||
east: null
|
||||
north: null
|
||||
south: "empty"
|
||||
west: "filler_k_west"
|
||||
east: "truhlarightright"
|
||||
north: "final_room"
|
||||
south: "truhlaright"
|
||||
|
||||
- id: "empty2"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "truhlatop"
|
||||
north: "boss"
|
||||
south: null
|
||||
|
||||
|
||||
# =========================
|
||||
# BOSS ROOM
|
||||
# =========================
|
||||
- id: "boss"
|
||||
texture: "ROOM1"
|
||||
mobs:
|
||||
- type: "hittable_drops"
|
||||
texture: "PLAYER_FRONT"
|
||||
cords:
|
||||
x: 100
|
||||
y: 100
|
||||
texture: "CAVE_BEAST"
|
||||
cords: { x: 100, y: 100 }
|
||||
collider:
|
||||
start:
|
||||
x: 0
|
||||
y: 52
|
||||
end:
|
||||
x: 44
|
||||
y: 78
|
||||
health: 10
|
||||
start: { x: 0, y: 52 }
|
||||
end: { x: 44, y: 78 }
|
||||
health: 40
|
||||
itemsDrops:
|
||||
- id: 5
|
||||
name: "Apple"
|
||||
type:
|
||||
name: "food"
|
||||
addHealth: 1
|
||||
texture: "APPLE"
|
||||
- id: 200
|
||||
name: "Beast Skin"
|
||||
type: { name: "quest_item_boss_skin" }
|
||||
texture: "BOSS_SKIN"
|
||||
tasks:
|
||||
- type: "following_player"
|
||||
speed: 1
|
||||
updateRateMs: 100
|
||||
speed: 2
|
||||
updateRateMs: 80
|
||||
- type: "attacking_player"
|
||||
damage: 20
|
||||
reach: 15
|
||||
updateRateMs: 500
|
||||
damage: 8
|
||||
reach: 18
|
||||
updateRateMs: 400
|
||||
west: "filler_boss_west"
|
||||
east: null
|
||||
north: null
|
||||
south: "empty_c"
|
||||
|
||||
|
||||
|
||||
# =========================
|
||||
# FINAL ROOM / EXIT
|
||||
# =========================
|
||||
- id: "final_room"
|
||||
texture: "ROOM_EXIT"
|
||||
requirement:
|
||||
item: "quest_item_final_key"
|
||||
objects:
|
||||
- objectType: "exit"
|
||||
cords: { x: 140, y: 40 }
|
||||
west: null
|
||||
east: null
|
||||
north: null
|
||||
south: "empty2"
|
||||
south: "klicnik"
|
||||
|
||||
- id: "klicnik"
|
||||
|
||||
|
||||
# =========================
|
||||
# COMBAT FILLER A (zombie)
|
||||
# =========================
|
||||
- id: "empty_a"
|
||||
texture: "ROOM1"
|
||||
mobs:
|
||||
- type: "hittable_drops"
|
||||
texture: "PLAYER_FRONT"
|
||||
cords:
|
||||
x: 100
|
||||
y: 100
|
||||
texture: "ZOMBIE"
|
||||
cords: { x: 110, y: 100 }
|
||||
collider:
|
||||
start:
|
||||
x: 0
|
||||
y: 52
|
||||
end:
|
||||
x: 44
|
||||
y: 78
|
||||
health: 10
|
||||
itemsDrops:
|
||||
- id: 6
|
||||
name: "Apple"
|
||||
type:
|
||||
name: "food"
|
||||
addHealth: 1
|
||||
texture: "APPLE"
|
||||
start: { x: 0, y: 52 }
|
||||
end: { x: 44, y: 78 }
|
||||
health: 6
|
||||
tasks:
|
||||
- type: "following_player"
|
||||
speed: 1
|
||||
updateRateMs: 120
|
||||
- type: "attacking_player"
|
||||
damage: 2
|
||||
reach: 15
|
||||
updateRateMs: 700
|
||||
west: "filler_2"
|
||||
east: "spawn"
|
||||
north: null
|
||||
south: "filler_deadend_1"
|
||||
|
||||
|
||||
|
||||
# =========================
|
||||
# COMBAT FILLER B (blind hunter)
|
||||
# =========================
|
||||
- id: "empty_c"
|
||||
texture: "ROOM1"
|
||||
mobs:
|
||||
- type: "hittable_drops"
|
||||
texture: "BLIND_HUNTER"
|
||||
cords: { x: 100, y: 100 }
|
||||
collider:
|
||||
start: { x: 0, y: 52 }
|
||||
end: { x: 44, y: 78 }
|
||||
health: 20
|
||||
tasks:
|
||||
- type: "blind_following_player"
|
||||
speed: 1
|
||||
updateRateMs: 100
|
||||
- type: "attacking_player"
|
||||
damage: 5
|
||||
damage: 6
|
||||
reach: 15
|
||||
updateRateMs: 500
|
||||
west: null
|
||||
east: "truhlarightright"
|
||||
north: null
|
||||
south: "truhlaright"
|
||||
west: "filler_c_west"
|
||||
east: null
|
||||
north: "boss"
|
||||
south: null
|
||||
|
||||
|
||||
|
||||
# =========================
|
||||
# LOOT ROOM 2
|
||||
# =========================
|
||||
- id: "truhlarightright"
|
||||
texture: "ROOM1"
|
||||
objects:
|
||||
- objectType: "chest"
|
||||
cords: { x: 100, y: 45 }
|
||||
items:
|
||||
- id: 7
|
||||
name: "Axe"
|
||||
type: { name: "weapon_axe", dealDamage: 4, attackCooldownMs: 800 }
|
||||
texture: "AXE"
|
||||
- id: 8
|
||||
name: "Apple"
|
||||
type: { name: "food", addHealth: 2 }
|
||||
texture: "APPLE"
|
||||
colliders:
|
||||
- start: { x: 100, y: 45 }
|
||||
end: { x: 140, y: 67 }
|
||||
west: "klicnik"
|
||||
east: "filler_rr_east"
|
||||
north: null
|
||||
south: null
|
||||
|
||||
|
||||
|
||||
# =========================
|
||||
# EXTRA FILLER ROOMS (maze / dead ends)
|
||||
# =========================
|
||||
- id: "filler_1"
|
||||
texture: "ROOM1"
|
||||
west: "truhlaright"
|
||||
east: "filler_1b"
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_1b"
|
||||
texture: "ROOM1"
|
||||
west: "filler_1"
|
||||
east: null
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_2"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "empty_a"
|
||||
north: "filler_loop_1"
|
||||
south: null
|
||||
|
||||
- id: "filler_loop_1"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: null
|
||||
north: "filler_loop_2"
|
||||
south: "filler_2"
|
||||
|
||||
- id: "filler_loop_2"
|
||||
texture: "ROOM1"
|
||||
west: "filler_loop_3"
|
||||
east: null
|
||||
north: null
|
||||
south: "filler_loop_1"
|
||||
|
||||
- id: "filler_loop_3"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "filler_loop_2"
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_deadend_1"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: null
|
||||
north: "empty_a"
|
||||
south: null
|
||||
|
||||
- id: "filler_k_west"
|
||||
texture: "ROOM1"
|
||||
west: "filler_k_west_2"
|
||||
east: "klicnik"
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_k_west_2"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "filler_k_west"
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_boss_west"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "boss"
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_c_west"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "empty_c"
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_rr_east"
|
||||
texture: "ROOM1"
|
||||
west: "truhlarightright"
|
||||
east: null
|
||||
north: null
|
||||
south: null
|
||||
|
||||
- id: "filler_south_1"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: null
|
||||
north: "truhlaright"
|
||||
south: "filler_south_2"
|
||||
|
||||
- id: "filler_south_2"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: null
|
||||
north: "filler_south_1"
|
||||
south: null
|
||||
|
||||
- id: "filler_entrance_north"
|
||||
texture: "ROOM1"
|
||||
west: null
|
||||
east: "filler_north_2"
|
||||
north: null
|
||||
south: "spawn"
|
||||
|
||||
- id: "filler_north_2"
|
||||
texture: "ROOM1"
|
||||
west: "filler_entrance_north"
|
||||
east: null
|
||||
north: null
|
||||
south: null
|
||||
objects:
|
||||
- objectType: "chest"
|
||||
cords:
|
||||
x: 100
|
||||
y: 45
|
||||
items:
|
||||
- id: 7
|
||||
name: "Wooden sword"
|
||||
type:
|
||||
name: "weapon_sword"
|
||||
dealDamage: 1
|
||||
texture: "WOODEN_SWORD"
|
||||
- id: 8
|
||||
name: "Apple"
|
||||
type:
|
||||
name: "food"
|
||||
addHealth: 1
|
||||
texture: "APPLE"
|
||||
colliders:
|
||||
- start:
|
||||
x: 100
|
||||
y: 45
|
||||
end:
|
||||
x: 140
|
||||
y: 67
|
||||
|
||||
Reference in New Issue
Block a user