mirror of
https://github.com/RustySamovar/RustySamovar.git
synced 2024-11-25 11:36:46 +00:00
Implement basic entity (de)spawning (gadgets, mobs, npcs)
This commit is contained in:
parent
8b6f33421c
commit
b83363fd6d
@ -1,13 +1,22 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use lua_serde::from_file;
|
use lua_serde::from_file;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
use packet_processor::*;
|
||||||
|
use crate::utils::IdManager;
|
||||||
|
|
||||||
use super::scene_config;
|
use super::scene_config;
|
||||||
|
|
||||||
use super::scene_config::Group;
|
pub use super::scene_config::Group;
|
||||||
use super::scene_config::Block;
|
pub use super::scene_config::Block;
|
||||||
use super::scene_config::Scene;
|
pub use super::scene_config::Scene;
|
||||||
|
pub use super::scene_config::Vector;
|
||||||
|
pub use super::scene_config::Monster;
|
||||||
|
pub use super::scene_config::Npc;
|
||||||
|
pub use super::scene_config::Gadget;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InternalSceneData {
|
pub struct InternalSceneData {
|
||||||
@ -22,6 +31,7 @@ pub struct InternalBlockData {
|
|||||||
pub block_id: u32,
|
pub block_id: u32,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
pub groups: HashMap<u32,InternalGroupData>,
|
pub groups: HashMap<u32,InternalGroupData>,
|
||||||
|
pub entities: HashMap<u32, Arc<Entity>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -33,9 +43,25 @@ pub struct InternalGroupData {
|
|||||||
// No extra data here
|
// No extra data here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub enum EntityType {
|
||||||
|
Monster(Monster),
|
||||||
|
Npc(Npc),
|
||||||
|
Gadget(Gadget),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub struct Entity {
|
||||||
|
pub entity_id: u32,
|
||||||
|
pub group_id: u32,
|
||||||
|
pub block_id: u32,
|
||||||
|
pub entity: EntityType,
|
||||||
|
}
|
||||||
|
|
||||||
/// Implementation of utility functions
|
/// Implementation of utility functions
|
||||||
impl InternalSceneData {
|
impl InternalSceneData {
|
||||||
pub fn get_block_by_pos(&self, pos: &proto::Vector) -> Result<&InternalBlockData, String> {
|
pub fn get_block_by_pos(&self, pos: &Vector) -> Result<&InternalBlockData, String> {
|
||||||
for (key, value) in self.scene.block_rects.iter() {
|
for (key, value) in self.scene.block_rects.iter() {
|
||||||
if value.contains(pos.x, pos.z) {
|
if value.contains(pos.x, pos.z) {
|
||||||
let id = self.scene.blocks[&key];
|
let id = self.scene.blocks[&key];
|
||||||
@ -45,6 +71,96 @@ impl InternalSceneData {
|
|||||||
|
|
||||||
return Err(format!("Block in coords {}, {} not found!", pos.x, pos.z));
|
return Err(format!("Block in coords {}, {} not found!", pos.x, pos.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_block_by_id(&self, block_id: u32) -> Result<&InternalBlockData, String> {
|
||||||
|
match self.blocks.get(&block_id) {
|
||||||
|
Some(block) => Ok(block),
|
||||||
|
None => Err(format!("Block with ID {} not found!", block_id)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entity {
|
||||||
|
pub fn pos(&self) -> Vector {
|
||||||
|
match &self.entity {
|
||||||
|
EntityType::Monster(m) => m.pos.clone(),
|
||||||
|
EntityType::Npc(n) => n.pos.clone(),
|
||||||
|
EntityType::Gadget(g) => g.pos.clone(),
|
||||||
|
_ => panic!("Unsupported entity type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rot(&self) -> Vector {
|
||||||
|
match &self.entity {
|
||||||
|
EntityType::Monster(m) => m.rot.clone(),
|
||||||
|
EntityType::Npc(n) => n.rot.clone(),
|
||||||
|
EntityType::Gadget(g) => g.rot.clone(),
|
||||||
|
_ => panic!("Unsupported entity type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn speed(&self) -> Vector {
|
||||||
|
// TODO!
|
||||||
|
Vector { x: 0.0, y: 0.0, z: 0.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn etype(&self) -> i32 {
|
||||||
|
(match &self.entity {
|
||||||
|
EntityType::Monster(_) => proto::ProtEntityType::ProtEntityMonster,
|
||||||
|
EntityType::Npc(n) => proto::ProtEntityType::ProtEntityNpc,
|
||||||
|
EntityType::Gadget(g) => proto::ProtEntityType::ProtEntityGadget,
|
||||||
|
_ => panic!("Unsupported entity type!"),
|
||||||
|
}) as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert(&self) -> proto::SceneEntityInfo {
|
||||||
|
let mut sei = build!(SceneEntityInfo {
|
||||||
|
entity_id: self.entity_id,
|
||||||
|
entity_type: self.etype(),
|
||||||
|
motion_info: Some(build!(MotionInfo {
|
||||||
|
pos: Some((&self.pos()).into()),
|
||||||
|
rot: Some((&self.rot()).into()),
|
||||||
|
speed: Some((&self.speed()).into()),
|
||||||
|
})),
|
||||||
|
animator_para_list: vec![],
|
||||||
|
entity_client_data: Some(build!(EntityClientData {})),
|
||||||
|
entity_authority_info: Some(build!(EntityAuthorityInfo {
|
||||||
|
renderer_changed_info: Some(build!(EntityRendererChangedInfo{})),
|
||||||
|
ai_info: Some(build!(SceneEntityAiInfo {
|
||||||
|
is_ai_open: true, // TODO!
|
||||||
|
born_pos: Some((&self.pos()).into()),
|
||||||
|
})),
|
||||||
|
born_pos: Some((&self.pos()).into()),
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
sei.entity = Some(match &self.entity {
|
||||||
|
EntityType::Monster(m) => proto::scene_entity_info::Entity::Monster(build!(SceneMonsterInfo {
|
||||||
|
monster_id: m.monster_id,
|
||||||
|
group_id: self.group_id,
|
||||||
|
config_id: m.config_id,
|
||||||
|
authority_peer_id: 1, // TODO: hardcoded value!
|
||||||
|
born_type: proto::MonsterBornType::MonsterBornDefault as i32, // TODO: hardcoded value!
|
||||||
|
block_id: self.block_id,
|
||||||
|
// TODO: level scaling, weapons!
|
||||||
|
})),
|
||||||
|
EntityType::Npc(n) => proto::scene_entity_info::Entity::Npc(build!(SceneNpcInfo {
|
||||||
|
npc_id: n.npc_id,
|
||||||
|
block_id: self.block_id,
|
||||||
|
})),
|
||||||
|
EntityType::Gadget(g) => proto::scene_entity_info::Entity::Gadget(build!(SceneGadgetInfo {
|
||||||
|
gadget_id: g.gadget_id,
|
||||||
|
group_id: self.group_id,
|
||||||
|
config_id: g.config_id,
|
||||||
|
authority_peer_id: 1, // TODO: hardcoded value!
|
||||||
|
is_enable_interact: true,
|
||||||
|
// TODO: collectibles!
|
||||||
|
})),
|
||||||
|
_ => panic!("Unsupported entity type!"),
|
||||||
|
});
|
||||||
|
|
||||||
|
sei
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -84,13 +200,15 @@ impl LuaManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_scene(directory: &str, scene_id: u32) -> InternalSceneData {
|
fn load_scene(directory: &str, scene_id: u32) -> InternalSceneData {
|
||||||
|
let mut entity_id_counter: u32 = 1;
|
||||||
|
|
||||||
let filename = format!(scene_name!(), directory, scene_id, scene_id);
|
let filename = format!(scene_name!(), directory, scene_id, scene_id);
|
||||||
|
|
||||||
let scene: Scene = from_file(&filename).unwrap(); // TODO: error handling!
|
let scene: Scene = from_file(&filename).unwrap(); // TODO: error handling!
|
||||||
|
|
||||||
let blocks = scene.blocks
|
let blocks = scene.blocks
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, block_id)| (*block_id, Self::load_block(directory, scene_id, *block_id)))
|
.map(|(key, block_id)| (*block_id, Self::load_block(directory, scene_id, *block_id, &mut entity_id_counter)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
InternalSceneData {
|
InternalSceneData {
|
||||||
@ -100,11 +218,11 @@ impl LuaManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_block(directory: &str, scene_id: u32, block_id: u32) -> InternalBlockData {
|
fn load_block(directory: &str, scene_id: u32, block_id: u32, entity_id_counter: &mut u32) -> InternalBlockData {
|
||||||
let filename = format!(block_name!(), directory, scene_id, scene_id, block_id);
|
let filename = format!(block_name!(), directory, scene_id, scene_id, block_id);
|
||||||
let block: Block = from_file(&filename).unwrap(); // TODO: error handling!
|
let block: Block = from_file(&filename).unwrap(); // TODO: error handling!
|
||||||
|
|
||||||
let groups = if false
|
let groups: HashMap<u32,InternalGroupData> = if false
|
||||||
{
|
{
|
||||||
// TODO: should be this! But some groups are missing
|
// TODO: should be this! But some groups are missing
|
||||||
block.groups
|
block.groups
|
||||||
@ -124,15 +242,57 @@ impl LuaManager {
|
|||||||
groups
|
groups
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: figure out more casual way!
|
||||||
|
let mut entities = HashMap::new();
|
||||||
|
|
||||||
|
for (group_id, igd) in groups.iter() {
|
||||||
|
for (npc_id, npc) in igd.group.npcs.iter() {
|
||||||
|
let entity_id = IdManager::get_entity_id_by_type_and_sub_id(&proto::ProtEntityType::ProtEntityNpc, *entity_id_counter);
|
||||||
|
*entity_id_counter = *entity_id_counter + 1;
|
||||||
|
|
||||||
|
entities.insert(entity_id, Arc::new(Entity {
|
||||||
|
entity_id: entity_id,
|
||||||
|
group_id: *group_id,
|
||||||
|
block_id: block_id,
|
||||||
|
entity: EntityType::Npc(npc.clone()), // TODO: very fucking inefficient!
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (monster_id, monster) in igd.group.monsters.iter() {
|
||||||
|
let entity_id = IdManager::get_entity_id_by_type_and_sub_id(&proto::ProtEntityType::ProtEntityMonster, *entity_id_counter);
|
||||||
|
*entity_id_counter = *entity_id_counter + 1;
|
||||||
|
|
||||||
|
entities.insert(entity_id, Arc::new(Entity {
|
||||||
|
entity_id: entity_id,
|
||||||
|
group_id: *group_id,
|
||||||
|
block_id: block_id,
|
||||||
|
entity: EntityType::Monster(monster.clone()), // TODO: very fucking inefficient!
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (gadget_id, gadget) in igd.group.gadgets.iter() {
|
||||||
|
let entity_id = IdManager::get_entity_id_by_type_and_sub_id(&proto::ProtEntityType::ProtEntityGadget, *entity_id_counter);
|
||||||
|
*entity_id_counter = *entity_id_counter + 1;
|
||||||
|
|
||||||
|
entities.insert(entity_id, Arc::new(Entity {
|
||||||
|
entity_id: entity_id,
|
||||||
|
group_id: *group_id,
|
||||||
|
block_id: block_id,
|
||||||
|
entity: EntityType::Gadget(gadget.clone()), // TODO: very fucking inefficient!
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InternalBlockData {
|
InternalBlockData {
|
||||||
scene_id,
|
scene_id,
|
||||||
block_id,
|
block_id,
|
||||||
block,
|
block,
|
||||||
groups,
|
groups,
|
||||||
|
entities,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_group(directory: &str, scene_id: u32, block_id: u32, group_id: u32) -> Result<InternalGroupData, std::io::Error> {
|
fn load_group(directory: &str, scene_id: u32, block_id: u32, group_id: u32) -> Result<(InternalGroupData), std::io::Error> {
|
||||||
let filename = format!(group_name!(), directory, scene_id, scene_id, group_id);
|
let filename = format!(group_name!(), directory, scene_id, scene_id, group_id);
|
||||||
//let group: Group = from_file(&filename).unwrap(); // TODO: error handling!
|
//let group: Group = from_file(&filename).unwrap(); // TODO: error handling!
|
||||||
let group: Group = from_file(&filename)?;
|
let group: Group = from_file(&filename)?;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
mod lua_manager;
|
mod lua_manager;
|
||||||
mod scene_config;
|
mod scene_config;
|
||||||
|
|
||||||
pub use self::lua_manager::LuaManager;
|
pub use self::lua_manager::LuaManager;
|
||||||
|
pub use self::scene_config::Vector;
|
||||||
|
pub use self::lua_manager::Entity;
|
@ -5,7 +5,7 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
// sceneX.lua
|
// sceneX.lua
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Vector {
|
pub struct Vector {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
@ -49,7 +49,19 @@ impl Vector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
impl From<&Vector> for proto::Vector {
|
||||||
|
fn from(v: &Vector) -> proto::Vector {
|
||||||
|
proto::Vector { x: v.x, y: v.y, z: v.z }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&proto::Vector> for Vector {
|
||||||
|
fn from(v: &proto::Vector) -> Vector {
|
||||||
|
Vector { x: v.x, y: v.y, z: v.z }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct BlockRect {
|
pub struct BlockRect {
|
||||||
pub min: Vector,
|
pub min: Vector,
|
||||||
pub max: Vector,
|
pub max: Vector,
|
||||||
@ -64,7 +76,7 @@ impl BlockRect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct SceneConfig {
|
pub struct SceneConfig {
|
||||||
pub born_rot: Vector,
|
pub born_rot: Vector,
|
||||||
pub born_pos: Vector,
|
pub born_pos: Vector,
|
||||||
@ -74,7 +86,7 @@ pub struct SceneConfig {
|
|||||||
pub die_y: f32,
|
pub die_y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub blocks: HashMap<u32,u32>,
|
pub blocks: HashMap<u32,u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -88,12 +100,12 @@ pub struct Scene {
|
|||||||
|
|
||||||
// sceneX_blockY.lua
|
// sceneX_blockY.lua
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
pub groups: HashMap<u32,GroupInfo>,
|
pub groups: HashMap<u32,GroupInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct GroupInfo {
|
pub struct GroupInfo {
|
||||||
pub is_replaceable: Option<ComplicatedBool>,
|
pub is_replaceable: Option<ComplicatedBool>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -104,21 +116,21 @@ pub struct GroupInfo {
|
|||||||
pub business: Option<Business>,
|
pub business: Option<Business>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct ComplicatedBool {
|
pub struct ComplicatedBool {
|
||||||
pub version: u32,
|
pub version: u32,
|
||||||
pub value: bool,
|
pub value: bool,
|
||||||
pub new_bin_only: bool,
|
pub new_bin_only: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Business {
|
pub struct Business {
|
||||||
pub r#type: u32,
|
pub r#type: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// sceneX_groupZ.lua
|
// sceneX_groupZ.lua
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
pub init_config: Option<GroupInitConfig>,
|
pub init_config: Option<GroupInitConfig>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -140,7 +152,7 @@ pub struct Group {
|
|||||||
// MovePlatform - Function???
|
// MovePlatform - Function???
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Suite {
|
pub struct Suite {
|
||||||
pub rand_weight: u32,
|
pub rand_weight: u32,
|
||||||
|
|
||||||
@ -157,7 +169,7 @@ pub struct Suite {
|
|||||||
pub monsters: HashMap<u32,u32>,
|
pub monsters: HashMap<u32,u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct GroupInitConfig {
|
pub struct GroupInitConfig {
|
||||||
pub end_suite: Option<u32>,
|
pub end_suite: Option<u32>,
|
||||||
//#[serde(default)]
|
//#[serde(default)]
|
||||||
@ -165,14 +177,14 @@ pub struct GroupInitConfig {
|
|||||||
pub suite: u32,
|
pub suite: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Variable {
|
pub struct Variable {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: u32,
|
pub value: u32,
|
||||||
pub no_refresh: bool,
|
pub no_refresh: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Monster {
|
pub struct Monster {
|
||||||
pub rot: Vector,
|
pub rot: Vector,
|
||||||
pub pos: Vector,
|
pub pos: Vector,
|
||||||
@ -181,7 +193,7 @@ pub struct Monster {
|
|||||||
pub monster_id: u32,
|
pub monster_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Npc {
|
pub struct Npc {
|
||||||
pub rot: Vector,
|
pub rot: Vector,
|
||||||
pub pos: Vector,
|
pub pos: Vector,
|
||||||
@ -192,7 +204,7 @@ pub struct Npc {
|
|||||||
pub room: Option<u32>,
|
pub room: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct Gadget {
|
pub struct Gadget {
|
||||||
pub rot: Vector,
|
pub rot: Vector,
|
||||||
pub pos: Vector,
|
pub pos: Vector,
|
||||||
@ -215,7 +227,7 @@ pub struct Gadget {
|
|||||||
pub is_use_point_array: bool,
|
pub is_use_point_array: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct ExploreInfo {
|
pub struct ExploreInfo {
|
||||||
pub exp: u32,
|
pub exp: u32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::sync::{mpsc::{self, Sender, Receiver}, Arc, Mutex};
|
use std::sync::{mpsc::{self, Sender, Receiver}, Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
|
|
||||||
use crate::server::IpcMessage;
|
use crate::server::IpcMessage;
|
||||||
@ -17,20 +17,23 @@ use serde_json::de::Read;
|
|||||||
use crate::LuaManager;
|
use crate::LuaManager;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager, TimeManager};
|
||||||
|
|
||||||
|
use crate::luamanager::Vector;
|
||||||
|
use crate::luamanager::Entity;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Player {
|
struct Player {
|
||||||
player_id: u32,
|
player_id: u32,
|
||||||
pos: proto::Vector,
|
pos: Vector,
|
||||||
current_scene: u32,
|
current_scene: u32,
|
||||||
current_block: u32,
|
current_block: u32,
|
||||||
entities: HashMap<u32,Entity>,
|
entities: HashMap<u32, Arc<Entity>>,
|
||||||
lua_manager: Arc<LuaManager>,
|
lua_manager: Arc<LuaManager>,
|
||||||
packets_to_send_tx: Sender<IpcMessage>,
|
packets_to_send_tx: Sender<IpcMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
const DESPAWN_DISTANCE: f32 = 10.0;
|
const DESPAWN_DISTANCE: f32 = 100.0;
|
||||||
const SPAWN_DISTANCE: f32 = 8.0;
|
const SPAWN_DISTANCE: f32 = Self::DESPAWN_DISTANCE * 0.8;
|
||||||
const RESPAWN_TIME: i32 = 10; // In seconds
|
const RESPAWN_TIME: i32 = 10; // In seconds
|
||||||
|
|
||||||
pub fn despawn_everything(&self) {
|
pub fn despawn_everything(&self) {
|
||||||
@ -53,19 +56,67 @@ impl Player {
|
|||||||
|
|
||||||
pub fn position_changed(&mut self) {
|
pub fn position_changed(&mut self) {
|
||||||
// 1. Go through the list of spawned entities and despawn those that are too far from us
|
// 1. Go through the list of spawned entities and despawn those that are too far from us
|
||||||
// 2. Go through the list of available entities and spawn those that are close to us and their respawn timeout (in case of collectibles and monsters) is over
|
let despawn_list: Vec<u32> = self.entities.iter()
|
||||||
|
.filter(|(k, v)| v.pos().sub(&self.pos).len() > Self::DESPAWN_DISTANCE)
|
||||||
|
.map(|(k, v)| *k)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if despawn_list.len() > 0 {
|
||||||
|
for k in despawn_list.iter() {
|
||||||
|
self.entities.remove(&k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: HACK!
|
||||||
|
let player_id = self.player_id;
|
||||||
|
let metadata = &build!(PacketHead {
|
||||||
|
sent_ms: TimeManager::timestamp(),
|
||||||
|
client_sequence_id: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
build_and_send!(self, player_id, metadata, SceneEntityDisappearNotify {
|
||||||
|
entity_list: despawn_list,
|
||||||
|
disappear_type: proto::VisionType::VisionMiss as i32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Go through the list of available entities and spawn those that are close to us and their respawn timeout (in case of collectibles and monsters) is over
|
||||||
|
let spawned_list: HashSet<u32> = self.entities.iter().map(|(k, v)| *k).collect();
|
||||||
|
|
||||||
|
// TODO: do this once only on block change!
|
||||||
|
let scene = self.lua_manager.get_scene_by_id(self.current_scene).unwrap();
|
||||||
|
let block = match scene.get_block_by_id(self.current_block) { // TODO: this is due to some blocks missing
|
||||||
|
Ok(block) => block,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let spawn_list: Vec<Arc<Entity>> = block.entities.iter()
|
||||||
|
.filter(|(entity_id, entity)| !spawned_list.contains(entity_id))
|
||||||
|
.filter(|(entity_id, entity)| entity.pos().sub(&self.pos).len() < Self::SPAWN_DISTANCE)
|
||||||
|
.map(|(entity_id, entity)| (*entity).clone())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if spawn_list.len() > 0 {
|
||||||
|
// TODO: HACK!
|
||||||
|
let player_id = self.player_id;
|
||||||
|
let metadata = &build!(PacketHead {
|
||||||
|
sent_ms: TimeManager::timestamp(),
|
||||||
|
client_sequence_id: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
build_and_send!(self, player_id, metadata, SceneEntityAppearNotify {
|
||||||
|
entity_list: spawn_list.iter().map(|e| e.convert()).collect(),
|
||||||
|
appear_type: proto::VisionType::VisionBorn as i32,
|
||||||
|
});
|
||||||
|
|
||||||
|
for entity in spawn_list.into_iter() {
|
||||||
|
self.entities.insert(entity.entity_id, entity.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gatherable stuff is described in GatherExcelConfigData
|
// Gatherable stuff is described in GatherExcelConfigData
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone)]
|
|
||||||
pub struct Entity {
|
|
||||||
entity_id: u32,
|
|
||||||
health: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
CombatInvocationsNotify,
|
CombatInvocationsNotify,
|
||||||
)]
|
)]
|
||||||
@ -112,10 +163,13 @@ impl EntitySubsystem {
|
|||||||
match block {
|
match block {
|
||||||
Ok(block) =>
|
Ok(block) =>
|
||||||
if player.current_block != block.block_id {
|
if player.current_block != block.block_id {
|
||||||
println!("Player {:?} moved to the block {:?}", player, block.block_id);
|
println!("Player {:?} moved to the block {:?}", player.player_id, block.block_id);
|
||||||
player.current_block = block.block_id;
|
player.current_block = block.block_id;
|
||||||
},
|
},
|
||||||
Err(_) => {/* TODO? */},
|
Err(_) => {
|
||||||
|
// TODO?
|
||||||
|
player.current_block = 0;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
player.position_changed();
|
player.position_changed();
|
||||||
@ -167,7 +221,7 @@ impl EntitySubsystem {
|
|||||||
// Avatar moved => update player's position
|
// Avatar moved => update player's position
|
||||||
let pos = if let Some(motion_info) = invoke.motion_info.as_ref() {
|
let pos = if let Some(motion_info) = invoke.motion_info.as_ref() {
|
||||||
if let Some(pos) = motion_info.pos.as_ref() {
|
if let Some(pos) = motion_info.pos.as_ref() {
|
||||||
pos.clone()
|
pos.into()
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user