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 tsv_util;
|
||||
|
||||
use std::path::Path;
|
||||
use std::{collections::HashMap, path::Path};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
pub use event_graph::*;
|
||||
use paste::paste;
|
||||
pub use templates::*;
|
||||
use tokio::sync::OnceCell;
|
||||
|
@ -38,6 +40,15 @@ template_collections! {
|
|||
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<()> {
|
||||
if !Path::new("assets/").exists() {
|
||||
bail!(
|
||||
|
@ -46,9 +57,13 @@ pub fn init_assets() -> Result<()> {
|
|||
}
|
||||
|
||||
init_template_collections()?;
|
||||
Ok(())
|
||||
init_binoutput()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
use crate::game::data;
|
||||
use protocol::*;
|
||||
use qwer::{phashmap, phashset, PropertyHashMap, PropertyHashSet};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::data::{self, ConfigAction, ConfigEventType, ConfigValue};
|
||||
|
||||
pub struct HollowGridManager {
|
||||
player: Arc<RwLock<PlayerInfo>>,
|
||||
map: RwLock<Option<HollowGridMapProtocolInfo>>,
|
||||
|
@ -97,15 +98,14 @@ impl HollowGridManager {
|
|||
let map = map.as_ref().unwrap();
|
||||
let cur_grid = map.grids.get(&map.start_grid).unwrap();
|
||||
|
||||
let event_config =
|
||||
data::get_event_config_json(cur_grid.grid.event_graph_info.hollow_event_template_id);
|
||||
let graph =
|
||||
data::get_event_graph(cur_grid.grid.event_graph_info.hollow_event_template_id).unwrap();
|
||||
|
||||
let mut hollow_finished = false;
|
||||
let actions = event_config["Events"]["OnEnd"]["Actions"]
|
||||
.as_array()
|
||||
.unwrap();
|
||||
if let Some(action) = actions.first() {
|
||||
hollow_finished = action["$type"].as_str().unwrap() == "Share.CConfigFinishHollow";
|
||||
if let Some(event) = graph.events.get(&ConfigEventType::OnEnd) {
|
||||
if let Some(ConfigAction::ConfigFinishHollow) = event.actions.first() {
|
||||
hollow_finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
|
@ -199,31 +199,29 @@ impl HollowGridManager {
|
|||
|
||||
let sync_hollow_event = {
|
||||
let info = map.grids.get(&(event_graph_uid as u16)).unwrap().clone();
|
||||
let event_config =
|
||||
data::get_event_config_json(info.grid.event_graph_info.hollow_event_template_id);
|
||||
let graph =
|
||||
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 {
|
||||
let index = (id % 1000) - 1;
|
||||
let actions = if id / 1000 == 1 {
|
||||
event_config["Events"]["OnStart"]["Actions"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
let event = if id / 1000 == 1 {
|
||||
graph.events.get(&ConfigEventType::OnStart)
|
||||
} else {
|
||||
event_config["Events"]["OnEnd"]["Actions"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
graph.events.get(&ConfigEventType::OnEnd)
|
||||
};
|
||||
if let Some(action) = actions.get(index as usize) {
|
||||
last_exec_type = action["$type"].as_str().unwrap();
|
||||
if let Some(action) = event.unwrap().actions.get(index as usize) {
|
||||
last_action = action;
|
||||
|
||||
// ugly, we have to parse these configs properly
|
||||
match action["$type"].as_str().unwrap() {
|
||||
"Share.CConfigSetMapState" => {
|
||||
let x = action["X"].as_i64().unwrap() as u16;
|
||||
let y = action["Y"].as_i64().unwrap() as u16;
|
||||
match action {
|
||||
ConfigAction::ConfigSetMapState { x, y, .. } => {
|
||||
let (ConfigValue::Constant(x), ConfigValue::Constant(y)) = (x, y)
|
||||
else {
|
||||
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) {
|
||||
info.grid.flag |= HollowGridFlag::Visible as i32
|
||||
| HollowGridFlag::CanMove as i32
|
||||
|
@ -232,14 +230,14 @@ impl HollowGridManager {
|
|||
grid_update.grids.insert(uid, info.clone());
|
||||
}
|
||||
}
|
||||
"Share.CConfigTriggerBattle" => {
|
||||
ConfigAction::ConfigTriggerBattle { .. } => {
|
||||
trigger_battle_id =
|
||||
Some(match info.grid.event_graph_info.hollow_event_template_id {
|
||||
1000107 => 10101002,
|
||||
_ => 10101001,
|
||||
});
|
||||
}
|
||||
"Share.CConfigFinishHollow" => {
|
||||
ConfigAction::ConfigFinishHollow => {
|
||||
hollow_finished = true;
|
||||
}
|
||||
_ => {}
|
||||
|
@ -251,13 +249,9 @@ impl HollowGridManager {
|
|||
|
||||
let last_client_action = *action_move_path.last().unwrap();
|
||||
let actions = if last_client_action / 1000 == 1 {
|
||||
event_config["Events"]["OnStart"]["Actions"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
&graph.events.get(&ConfigEventType::OnStart).unwrap().actions
|
||||
} else {
|
||||
event_config["Events"]["OnEnd"]["Actions"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
&graph.events.get(&ConfigEventType::OnEnd).unwrap().actions
|
||||
};
|
||||
let state = if last_client_action == -1 {
|
||||
EventState::Finished
|
||||
|
@ -265,24 +259,24 @@ impl HollowGridManager {
|
|||
action_move_path.push(-1);
|
||||
EventState::Finished
|
||||
} else {
|
||||
if last_exec_type != "Share.CConfigEmpty" {
|
||||
if !matches!(last_action, ConfigAction::ConfigEmpty) {
|
||||
action_move_path.push(last_client_action + 1);
|
||||
}
|
||||
|
||||
EventState::WaitingClient
|
||||
};
|
||||
|
||||
let finish_event = if last_exec_type != "Share.CConfigTriggerBattle" {
|
||||
let finish_event = if let ConfigAction::ConfigTriggerBattle { .. } = last_action {
|
||||
PtcSyncHollowEventInfoArg {
|
||||
event_graph_uid,
|
||||
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,
|
||||
updated_event: EventInfo {
|
||||
id: 1000,
|
||||
cur_action_id: *action_move_path.last().unwrap(),
|
||||
action_move_path,
|
||||
state,
|
||||
prev_state: EventState::Running,
|
||||
id: 0,
|
||||
cur_action_id: 0,
|
||||
action_move_path: vec![],
|
||||
state: EventState::Initing,
|
||||
prev_state: EventState::Initing,
|
||||
cur_action_info: ActionInfo::None {},
|
||||
cur_action_state: ActionState::Init,
|
||||
predicated_failed_actions: phashset![],
|
||||
|
@ -296,11 +290,11 @@ impl HollowGridManager {
|
|||
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,
|
||||
updated_event: EventInfo {
|
||||
id: 0,
|
||||
cur_action_id: 0,
|
||||
action_move_path: vec![],
|
||||
state: EventState::Initing,
|
||||
prev_state: EventState::Initing,
|
||||
id: 1000,
|
||||
cur_action_id: *action_move_path.last().unwrap(),
|
||||
action_move_path,
|
||||
state,
|
||||
prev_state: EventState::Running,
|
||||
cur_action_info: ActionInfo::None {},
|
||||
cur_action_state: ActionState::Init,
|
||||
predicated_failed_actions: phashset![],
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
mod context;
|
||||
pub mod data;
|
||||
pub mod manager;
|
||||
pub mod util;
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ version.workspace = true
|
|||
byteorder.workspace = true
|
||||
hex.workspace = true
|
||||
qwer.workspace = true
|
||||
serde.workspace = true
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[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)]
|
||||
pub enum NodeState {
|
||||
All = 0,
|
||||
|
@ -577,7 +579,7 @@ pub enum NodeState {
|
|||
EnumCount = 11,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||
#[repr(i16)]
|
||||
pub enum NodeVisible {
|
||||
All = 0,
|
||||
|
@ -588,24 +590,34 @@ pub enum NodeVisible {
|
|||
EnumCount = 5,
|
||||
}
|
||||
|
||||
#[derive(OctData, Clone, Debug)]
|
||||
#[derive(OctData, Clone, Debug, Hash, PartialEq, Eq, Deserialize)]
|
||||
#[repr(i16)]
|
||||
pub enum HollowEventType {
|
||||
None = 0,
|
||||
All = 1,
|
||||
Begin = 10,
|
||||
End = 20,
|
||||
#[serde(rename = "Interact_End")]
|
||||
InteractEnd = 21,
|
||||
#[serde(rename = "Battle_End")]
|
||||
BattleEnd = 22,
|
||||
#[serde(rename = "Change_Level_Interact")]
|
||||
ChangeLevelInteract = 23,
|
||||
#[serde(rename = "Change_Level_Fight")]
|
||||
ChangeLevelFight = 24,
|
||||
Battle = 30,
|
||||
#[serde(rename = "Battle_Normal")]
|
||||
BattleNormal = 31,
|
||||
#[serde(rename = "Battle_Elite")]
|
||||
BattleElite = 32,
|
||||
#[serde(rename = "Battle_Boss")]
|
||||
BattleBoss = 33,
|
||||
Dialog = 40,
|
||||
#[serde(rename = "Dialog_Positive")]
|
||||
DialogPositive = 41,
|
||||
#[serde(rename = "Dialog_Negative")]
|
||||
DialogNegative = 42,
|
||||
#[serde(rename = "Dialog_Special")]
|
||||
DialogSpecial = 43,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue