Actual parsing of EventGraphCollection
This commit is contained in:
parent
f0fe7622b2
commit
e84cad1f79
8 changed files with 173 additions and 69 deletions
100
gameserver/src/data/event_graph.rs
Normal file
100
gameserver/src/data/event_graph.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use std::collections::{BTreeMap, HashSet};
|
||||||
|
|
||||||
|
use protocol::{HollowEventType, NodeState, NodeVisible};
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub struct ConfigEventGraph {
|
||||||
|
#[serde(rename = "ID")]
|
||||||
|
pub id: i32,
|
||||||
|
pub events: BTreeMap<ConfigEventType, ConfigEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ConfigValue {
|
||||||
|
Constant(i32),
|
||||||
|
Expression(String),
|
||||||
|
#[default]
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub enum ConfigEventType {
|
||||||
|
OnStart,
|
||||||
|
OnEnd,
|
||||||
|
#[serde(other)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub struct ConfigEvent {
|
||||||
|
#[serde(default)]
|
||||||
|
pub actions: Vec<ConfigAction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
pub enum HollowPositionOffsetType {
|
||||||
|
#[default]
|
||||||
|
Relative = 0,
|
||||||
|
Absolute = 1,
|
||||||
|
EventPos = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(tag = "$type")]
|
||||||
|
pub enum ConfigAction {
|
||||||
|
#[serde(rename = "Share.CConfigEmpty")]
|
||||||
|
ConfigEmpty,
|
||||||
|
#[serde(rename = "Share.CConfigSetMapState")]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
ConfigSetMapState {
|
||||||
|
#[serde(default)]
|
||||||
|
x: ConfigValue,
|
||||||
|
#[serde(default)]
|
||||||
|
y: ConfigValue,
|
||||||
|
#[serde(default)]
|
||||||
|
position: HollowPositionOffsetType,
|
||||||
|
radius: Option<ConfigValue>,
|
||||||
|
count: Option<ConfigValue>,
|
||||||
|
#[serde(default)]
|
||||||
|
r#type: HashSet<HollowEventType>,
|
||||||
|
event_type_tag: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
from_visible_state: HashSet<NodeVisible>,
|
||||||
|
#[serde(default)]
|
||||||
|
to_visible_state: Vec<NodeVisible>,
|
||||||
|
#[serde(default)]
|
||||||
|
from_state: HashSet<NodeState>,
|
||||||
|
#[serde(default)]
|
||||||
|
to_state: Vec<NodeState>,
|
||||||
|
#[serde(default)]
|
||||||
|
exclude_player_pos: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
index_list: Vec<ConfigValue>,
|
||||||
|
#[serde(default)]
|
||||||
|
use_perform: bool,
|
||||||
|
},
|
||||||
|
#[serde(rename = "Share.CConfigTriggerBattle")]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
ConfigTriggerBattle {
|
||||||
|
#[serde(rename = "BattleID")]
|
||||||
|
battle_id: ConfigValue,
|
||||||
|
on_success: Option<String>,
|
||||||
|
on_failure: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
end_hollow: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
goto_next_hollow: bool,
|
||||||
|
},
|
||||||
|
#[serde(rename = "Share.CConfigFinishHollow")]
|
||||||
|
ConfigFinishHollow,
|
||||||
|
#[default]
|
||||||
|
#[serde(other)]
|
||||||
|
ConfigUnknown,
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
|
mod event_graph;
|
||||||
mod templates;
|
mod templates;
|
||||||
mod tsv_util;
|
mod tsv_util;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::{collections::HashMap, path::Path};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
pub use event_graph::*;
|
||||||
use paste::paste;
|
use paste::paste;
|
||||||
pub use templates::*;
|
pub use templates::*;
|
||||||
use tokio::sync::OnceCell;
|
use tokio::sync::OnceCell;
|
||||||
|
@ -38,6 +40,15 @@ template_collections! {
|
||||||
MainCityObject;
|
MainCityObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EVENT_GRAPH_COLLECTION: OnceCell<HashMap<i32, ConfigEventGraph>> = OnceCell::const_new();
|
||||||
|
|
||||||
|
fn init_binoutput() -> Result<()> {
|
||||||
|
let _ = EVENT_GRAPH_COLLECTION.set(serde_json::from_str(
|
||||||
|
std::fs::read_to_string("assets/BinOutput/EventGraphCollection.json")?.as_str(),
|
||||||
|
)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_assets() -> Result<()> {
|
pub fn init_assets() -> Result<()> {
|
||||||
if !Path::new("assets/").exists() {
|
if !Path::new("assets/").exists() {
|
||||||
bail!(
|
bail!(
|
||||||
|
@ -46,9 +57,13 @@ pub fn init_assets() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
init_template_collections()?;
|
init_template_collections()?;
|
||||||
Ok(())
|
init_binoutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_main_city_object(tag_id: i32, npc_id: i32) -> Option<&'static MainCityObjectTemplate> {
|
pub fn get_main_city_object(tag_id: i32, npc_id: i32) -> Option<&'static MainCityObjectTemplate> {
|
||||||
iter_main_city_object_collection().find(|o| o.tag_id == tag_id && o.npc_id == npc_id)
|
iter_main_city_object_collection().find(|o| o.tag_id == tag_id && o.npc_id == npc_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_event_graph(id: i32) -> Option<&'static ConfigEventGraph> {
|
||||||
|
EVENT_GRAPH_COLLECTION.get().unwrap().get(&id)
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
use std::sync::LazyLock;
|
|
||||||
|
|
||||||
use serde_json::{Map, Value};
|
|
||||||
|
|
||||||
pub const EVENT_GRAPH_COLLECTION: &str = include_str!("../../EventGraphCollection.json");
|
|
||||||
|
|
||||||
static EVENT_MAP: LazyLock<Map<String, Value>> = LazyLock::new(|| {
|
|
||||||
serde_json::from_str::<Value>(EVENT_GRAPH_COLLECTION)
|
|
||||||
.unwrap()
|
|
||||||
.as_object()
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
});
|
|
||||||
|
|
||||||
pub fn get_event_config_json(id: i32) -> &'static Value {
|
|
||||||
EVENT_MAP.get(&id.to_string()).unwrap()
|
|
||||||
}
|
|
|
@ -3,11 +3,12 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::game::data;
|
|
||||||
use protocol::*;
|
use protocol::*;
|
||||||
use qwer::{phashmap, phashset, PropertyHashMap, PropertyHashSet};
|
use qwer::{phashmap, phashset, PropertyHashMap, PropertyHashSet};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
use crate::data::{self, ConfigAction, ConfigEventType, ConfigValue};
|
||||||
|
|
||||||
pub struct HollowGridManager {
|
pub struct HollowGridManager {
|
||||||
player: Arc<RwLock<PlayerInfo>>,
|
player: Arc<RwLock<PlayerInfo>>,
|
||||||
map: RwLock<Option<HollowGridMapProtocolInfo>>,
|
map: RwLock<Option<HollowGridMapProtocolInfo>>,
|
||||||
|
@ -97,15 +98,14 @@ impl HollowGridManager {
|
||||||
let map = map.as_ref().unwrap();
|
let map = map.as_ref().unwrap();
|
||||||
let cur_grid = map.grids.get(&map.start_grid).unwrap();
|
let cur_grid = map.grids.get(&map.start_grid).unwrap();
|
||||||
|
|
||||||
let event_config =
|
let graph =
|
||||||
data::get_event_config_json(cur_grid.grid.event_graph_info.hollow_event_template_id);
|
data::get_event_graph(cur_grid.grid.event_graph_info.hollow_event_template_id).unwrap();
|
||||||
|
|
||||||
let mut hollow_finished = false;
|
let mut hollow_finished = false;
|
||||||
let actions = event_config["Events"]["OnEnd"]["Actions"]
|
if let Some(event) = graph.events.get(&ConfigEventType::OnEnd) {
|
||||||
.as_array()
|
if let Some(ConfigAction::ConfigFinishHollow) = event.actions.first() {
|
||||||
.unwrap();
|
hollow_finished = true;
|
||||||
if let Some(action) = actions.first() {
|
}
|
||||||
hollow_finished = action["$type"].as_str().unwrap() == "Share.CConfigFinishHollow";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -199,31 +199,29 @@ impl HollowGridManager {
|
||||||
|
|
||||||
let sync_hollow_event = {
|
let sync_hollow_event = {
|
||||||
let info = map.grids.get(&(event_graph_uid as u16)).unwrap().clone();
|
let info = map.grids.get(&(event_graph_uid as u16)).unwrap().clone();
|
||||||
let event_config =
|
let graph =
|
||||||
data::get_event_config_json(info.grid.event_graph_info.hollow_event_template_id);
|
data::get_event_graph(info.grid.event_graph_info.hollow_event_template_id).unwrap();
|
||||||
|
|
||||||
|
let mut last_action = &ConfigAction::ConfigEmpty;
|
||||||
|
|
||||||
let mut last_exec_type = "";
|
|
||||||
for id in &move_path {
|
for id in &move_path {
|
||||||
let index = (id % 1000) - 1;
|
let index = (id % 1000) - 1;
|
||||||
let actions = if id / 1000 == 1 {
|
let event = if id / 1000 == 1 {
|
||||||
event_config["Events"]["OnStart"]["Actions"]
|
graph.events.get(&ConfigEventType::OnStart)
|
||||||
.as_array()
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
} else {
|
||||||
event_config["Events"]["OnEnd"]["Actions"]
|
graph.events.get(&ConfigEventType::OnEnd)
|
||||||
.as_array()
|
|
||||||
.unwrap()
|
|
||||||
};
|
};
|
||||||
if let Some(action) = actions.get(index as usize) {
|
if let Some(action) = event.unwrap().actions.get(index as usize) {
|
||||||
last_exec_type = action["$type"].as_str().unwrap();
|
last_action = action;
|
||||||
|
|
||||||
// ugly, we have to parse these configs properly
|
match action {
|
||||||
match action["$type"].as_str().unwrap() {
|
ConfigAction::ConfigSetMapState { x, y, .. } => {
|
||||||
"Share.CConfigSetMapState" => {
|
let (ConfigValue::Constant(x), ConfigValue::Constant(y)) = (x, y)
|
||||||
let x = action["X"].as_i64().unwrap() as u16;
|
else {
|
||||||
let y = action["Y"].as_i64().unwrap() as u16;
|
panic!("ConfigSetMapState: only constant values are supported");
|
||||||
|
};
|
||||||
|
|
||||||
let uid = (y * 11) + x;
|
let uid = ((y * 11) + x) as u16;
|
||||||
if let Some(info) = map.grids.get_mut(&uid) {
|
if let Some(info) = map.grids.get_mut(&uid) {
|
||||||
info.grid.flag |= HollowGridFlag::Visible as i32
|
info.grid.flag |= HollowGridFlag::Visible as i32
|
||||||
| HollowGridFlag::CanMove as i32
|
| HollowGridFlag::CanMove as i32
|
||||||
|
@ -232,14 +230,14 @@ impl HollowGridManager {
|
||||||
grid_update.grids.insert(uid, info.clone());
|
grid_update.grids.insert(uid, info.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"Share.CConfigTriggerBattle" => {
|
ConfigAction::ConfigTriggerBattle { .. } => {
|
||||||
trigger_battle_id =
|
trigger_battle_id =
|
||||||
Some(match info.grid.event_graph_info.hollow_event_template_id {
|
Some(match info.grid.event_graph_info.hollow_event_template_id {
|
||||||
1000107 => 10101002,
|
1000107 => 10101002,
|
||||||
_ => 10101001,
|
_ => 10101001,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"Share.CConfigFinishHollow" => {
|
ConfigAction::ConfigFinishHollow => {
|
||||||
hollow_finished = true;
|
hollow_finished = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -251,13 +249,9 @@ impl HollowGridManager {
|
||||||
|
|
||||||
let last_client_action = *action_move_path.last().unwrap();
|
let last_client_action = *action_move_path.last().unwrap();
|
||||||
let actions = if last_client_action / 1000 == 1 {
|
let actions = if last_client_action / 1000 == 1 {
|
||||||
event_config["Events"]["OnStart"]["Actions"]
|
&graph.events.get(&ConfigEventType::OnStart).unwrap().actions
|
||||||
.as_array()
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
} else {
|
||||||
event_config["Events"]["OnEnd"]["Actions"]
|
&graph.events.get(&ConfigEventType::OnEnd).unwrap().actions
|
||||||
.as_array()
|
|
||||||
.unwrap()
|
|
||||||
};
|
};
|
||||||
let state = if last_client_action == -1 {
|
let state = if last_client_action == -1 {
|
||||||
EventState::Finished
|
EventState::Finished
|
||||||
|
@ -265,24 +259,24 @@ impl HollowGridManager {
|
||||||
action_move_path.push(-1);
|
action_move_path.push(-1);
|
||||||
EventState::Finished
|
EventState::Finished
|
||||||
} else {
|
} else {
|
||||||
if last_exec_type != "Share.CConfigEmpty" {
|
if !matches!(last_action, ConfigAction::ConfigEmpty) {
|
||||||
action_move_path.push(last_client_action + 1);
|
action_move_path.push(last_client_action + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventState::WaitingClient
|
EventState::WaitingClient
|
||||||
};
|
};
|
||||||
|
|
||||||
let finish_event = if last_exec_type != "Share.CConfigTriggerBattle" {
|
let finish_event = if let ConfigAction::ConfigTriggerBattle { .. } = last_action {
|
||||||
PtcSyncHollowEventInfoArg {
|
PtcSyncHollowEventInfoArg {
|
||||||
event_graph_uid,
|
event_graph_uid,
|
||||||
hollow_event_template_id: info.grid.event_graph_info.hollow_event_template_id,
|
hollow_event_template_id: info.grid.event_graph_info.hollow_event_template_id,
|
||||||
event_graph_id: info.grid.event_graph_info.hollow_event_template_id,
|
event_graph_id: info.grid.event_graph_info.hollow_event_template_id,
|
||||||
updated_event: EventInfo {
|
updated_event: EventInfo {
|
||||||
id: 1000,
|
id: 0,
|
||||||
cur_action_id: *action_move_path.last().unwrap(),
|
cur_action_id: 0,
|
||||||
action_move_path,
|
action_move_path: vec![],
|
||||||
state,
|
state: EventState::Initing,
|
||||||
prev_state: EventState::Running,
|
prev_state: EventState::Initing,
|
||||||
cur_action_info: ActionInfo::None {},
|
cur_action_info: ActionInfo::None {},
|
||||||
cur_action_state: ActionState::Init,
|
cur_action_state: ActionState::Init,
|
||||||
predicated_failed_actions: phashset![],
|
predicated_failed_actions: phashset![],
|
||||||
|
@ -296,11 +290,11 @@ impl HollowGridManager {
|
||||||
hollow_event_template_id: info.grid.event_graph_info.hollow_event_template_id,
|
hollow_event_template_id: info.grid.event_graph_info.hollow_event_template_id,
|
||||||
event_graph_id: info.grid.event_graph_info.hollow_event_template_id,
|
event_graph_id: info.grid.event_graph_info.hollow_event_template_id,
|
||||||
updated_event: EventInfo {
|
updated_event: EventInfo {
|
||||||
id: 0,
|
id: 1000,
|
||||||
cur_action_id: 0,
|
cur_action_id: *action_move_path.last().unwrap(),
|
||||||
action_move_path: vec![],
|
action_move_path,
|
||||||
state: EventState::Initing,
|
state,
|
||||||
prev_state: EventState::Initing,
|
prev_state: EventState::Running,
|
||||||
cur_action_info: ActionInfo::None {},
|
cur_action_info: ActionInfo::None {},
|
||||||
cur_action_state: ActionState::Init,
|
cur_action_state: ActionState::Init,
|
||||||
predicated_failed_actions: phashset![],
|
predicated_failed_actions: phashset![],
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
mod context;
|
mod context;
|
||||||
pub mod data;
|
|
||||||
pub mod manager;
|
pub mod manager;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,4 @@ version.workspace = true
|
||||||
byteorder.workspace = true
|
byteorder.workspace = true
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
qwer.workspace = true
|
qwer.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
#[derive(OctData, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -560,7 +562,7 @@ flag! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(OctData, Clone, Debug)]
|
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||||
#[repr(i16)]
|
#[repr(i16)]
|
||||||
pub enum NodeState {
|
pub enum NodeState {
|
||||||
All = 0,
|
All = 0,
|
||||||
|
@ -577,7 +579,7 @@ pub enum NodeState {
|
||||||
EnumCount = 11,
|
EnumCount = 11,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(OctData, Clone, Debug)]
|
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||||
#[repr(i16)]
|
#[repr(i16)]
|
||||||
pub enum NodeVisible {
|
pub enum NodeVisible {
|
||||||
All = 0,
|
All = 0,
|
||||||
|
@ -588,24 +590,34 @@ pub enum NodeVisible {
|
||||||
EnumCount = 5,
|
EnumCount = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(OctData, Clone, Debug)]
|
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||||
#[repr(i16)]
|
#[repr(i16)]
|
||||||
pub enum HollowEventType {
|
pub enum HollowEventType {
|
||||||
None = 0,
|
None = 0,
|
||||||
All = 1,
|
All = 1,
|
||||||
Begin = 10,
|
Begin = 10,
|
||||||
End = 20,
|
End = 20,
|
||||||
|
#[serde(rename = "Interact_End")]
|
||||||
InteractEnd = 21,
|
InteractEnd = 21,
|
||||||
|
#[serde(rename = "Battle_End")]
|
||||||
BattleEnd = 22,
|
BattleEnd = 22,
|
||||||
|
#[serde(rename = "Change_Level_Interact")]
|
||||||
ChangeLevelInteract = 23,
|
ChangeLevelInteract = 23,
|
||||||
|
#[serde(rename = "Change_Level_Fight")]
|
||||||
ChangeLevelFight = 24,
|
ChangeLevelFight = 24,
|
||||||
Battle = 30,
|
Battle = 30,
|
||||||
|
#[serde(rename = "Battle_Normal")]
|
||||||
BattleNormal = 31,
|
BattleNormal = 31,
|
||||||
|
#[serde(rename = "Battle_Elite")]
|
||||||
BattleElite = 32,
|
BattleElite = 32,
|
||||||
|
#[serde(rename = "Battle_Boss")]
|
||||||
BattleBoss = 33,
|
BattleBoss = 33,
|
||||||
Dialog = 40,
|
Dialog = 40,
|
||||||
|
#[serde(rename = "Dialog_Positive")]
|
||||||
DialogPositive = 41,
|
DialogPositive = 41,
|
||||||
|
#[serde(rename = "Dialog_Negative")]
|
||||||
DialogNegative = 42,
|
DialogNegative = 42,
|
||||||
|
#[serde(rename = "Dialog_Special")]
|
||||||
DialogSpecial = 43,
|
DialogSpecial = 43,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue