Browse Source

load free map monster data and send to client the free map list

pbs
jake 4 years ago
parent
commit
2cd0a32c0f
  1. 279
      src/ship/map.rs
  2. 15
      src/ship/room.rs
  3. 2
      src/ship/ship.rs

279
src/ship/map.rs

@ -6,6 +6,7 @@ use std::io::{Read};
use std::fs::File;
use byteorder::{LittleEndian, ReadBytesExt};
use rand::Rng;
use crate::ship::monster::MonsterType;
use crate::ship::room::Episode;
@ -64,32 +65,6 @@ impl RawMapEnemy {
}
struct MapObjects {
}
struct MapEnemies {
}
impl MapEnemies {
fn new(path: PathBuf) -> MapEnemies {
MapEnemies {
}
}
fn read_next_enemy(&mut self) -> Option<MapEnemy> {
None
}
}
#[derive(Debug)]
enum MapEnemyError {
UnknownEnemyId(u32),
@ -104,7 +79,6 @@ pub struct MapEnemy {
dead: bool,
}
impl MapEnemy {
fn from_raw(enemy: RawMapEnemy, episode: &Episode /*, battleparam */) -> Result<MapEnemy, MapEnemyError> {
let monster = match (enemy, episode) {
@ -191,8 +165,6 @@ impl MapEnemy {
(RawMapEnemy {id: 281, skin: 0, ..}, _) => MonsterType::SaintMillion,
(RawMapEnemy {id: 281, skin: 1, ..}, _) => MonsterType::Shambertin,
_ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
//_ => panic!("trying to load unknown monster: {:?}", enemy)
};
Ok(MapEnemy {
@ -211,50 +183,245 @@ impl MapEnemy {
}
}
//impl From<RawMapEnemy> for MapEnemy
#[derive(Debug)]
enum MapVariantMode {
Online,
Offline,
}
#[derive(Debug)]
enum MapVariantType {
Pioneer2Ep1,
Forest1,
Forest2,
Caves1,
Caves2,
Caves3,
Mines1,
Mines2,
Ruins1,
Ruins2,
Ruins3,
Dragon,
DeRolLe,
VolOpt,
DarkFalz,
}
#[derive(Debug)]
pub struct Maps {
//map_indexes:
enemy_data: Vec<MapEnemy>
struct MapVariant {
map: MapVariantType,
mode: MapVariantMode,
major: u8,
minor: u8,
}
impl MapVariant {
fn new(map: MapVariantType, mode: MapVariantMode) -> MapVariant {
let major = match map {
MapVariantType::Pioneer2Ep1 => 0,
MapVariantType::Forest1 | MapVariantType::Forest2 => 0,
MapVariantType::Caves1 | MapVariantType::Caves2 | MapVariantType::Caves3 => rand::thread_rng().gen_range(0, 3),
MapVariantType::Mines1 | MapVariantType::Mines2 => rand::thread_rng().gen_range(0, 3),
MapVariantType::Ruins1 | MapVariantType::Ruins2 | MapVariantType::Ruins3 => rand::thread_rng().gen_range(0, 3),
MapVariantType::Dragon | MapVariantType::DeRolLe | MapVariantType::VolOpt | MapVariantType::DarkFalz => 0,
};
let minor = match map {
MapVariantType::Pioneer2Ep1 => 0,
MapVariantType::Forest1 => rand::thread_rng().gen_range(0, 6),
MapVariantType::Forest2 => rand::thread_rng().gen_range(0, 5),
MapVariantType::Caves1 | MapVariantType::Caves2 | MapVariantType::Caves3 => rand::thread_rng().gen_range(0, 2),
MapVariantType::Mines1 | MapVariantType::Mines2 => rand::thread_rng().gen_range(0, 2),
MapVariantType::Ruins1 | MapVariantType::Ruins2 | MapVariantType::Ruins3 => rand::thread_rng().gen_range(0, 2),
MapVariantType::Dragon | MapVariantType::DeRolLe | MapVariantType::VolOpt | MapVariantType::DarkFalz => 0,
};
MapVariant {
map: map,
mode: mode,
major: major,
minor: minor,
}
}
fn dat_file(&self) -> String {
match self.map {
MapVariantType::Pioneer2Ep1 => "data/maps/map_city00_00e.dat".into(),
MapVariantType::Forest1 => format!("data/maps/map_forest01_0{}e.dat", self.minor),
MapVariantType::Forest2 => format!("data/maps/map_forest02_0{}e.dat", self.minor),
MapVariantType::Caves1 => format!("data/maps/map_cave01_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Caves2 => format!("data/maps/map_cave02_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Caves3 => format!("data/maps/map_cave03_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Mines1 => format!("data/maps/map_machine01_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Mines2 => format!("data/maps/map_machine02_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Ruins1 => format!("data/maps/map_ancient01_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Ruins2 => format!("data/maps/map_ancient02_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Ruins3 => format!("data/maps/map_ancient03_0{}_0{}e.dat", self.major, self.minor),
MapVariantType::Dragon => "data/maps/map_boss01e.dat".into(),
MapVariantType::DeRolLe => "data/maps/map_boss02e.dat".into(),
MapVariantType::VolOpt => "data/maps/map_boss03e.dat".into(),
MapVariantType::DarkFalz => "data/maps/map_boss04e.dat".into(),
}
}
fn pkt_header(&self) -> [u8; 2] {
[self.major, self.minor]
}
}
fn enemy_data_from_map_data(path: PathBuf, episode: &Episode) -> Vec<Option<MapEnemy>> {
let mut cursor = File::open(path).unwrap();
let mut enemy_data = Vec::new();
while let Ok(enemy) = RawMapEnemy::from_byte_stream(&mut cursor) {
let new_enemy = MapEnemy::from_raw(enemy, episode);
enemy_data.append(&mut new_enemy
.map_or(vec![None], |monster| {
let mut monsters = Vec::new();
monsters.push(Some(monster));
match monster.monster {
MonsterType::Monest => {
for _ in 0..30 {
monsters.push(Some(MapEnemy::new(MonsterType::Mothmant)));
}
},
MonsterType::PofuillySlime => {
for _ in 0..4 {
monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime)));
}
},
MonsterType::PanArms => {
monsters.push(Some(MapEnemy::new(MonsterType::Hidoom)));
monsters.push(Some(MapEnemy::new(MonsterType::Migium)));
},
MonsterType::SinowBeat => {
for _ in 0..4 {
monsters.push(Some(MapEnemy::new(MonsterType::SinowBeat)));
}
},
MonsterType::SinowGold => {
for _ in 0..4 {
monsters.push(Some(MapEnemy::new(MonsterType::SinowGold)));
}
},
MonsterType::Canane => {
for _ in 0..8 {
monsters.push(Some(MapEnemy::new(MonsterType::RingCanadine)));
}
},
MonsterType::ChaosSorcerer => {
monsters.push(Some(MapEnemy::new(MonsterType::BeeR)));
monsters.push(Some(MapEnemy::new(MonsterType::BeeL)));
},
MonsterType::Bulclaw => {
for _ in 0..4 {
monsters.push(Some(MapEnemy::new(MonsterType::Claw)));
}
},
MonsterType::DeRolLe => {
for _ in 0..10 {
monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeBody)));
}
for _ in 0..9 {
monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeMine)));
}
},
MonsterType::VolOptPartA => {
for _ in 0..6 {
monsters.push(Some(MapEnemy::new(MonsterType::VolOptPillar)));
}
for _ in 0..24 {
monsters.push(Some(MapEnemy::new(MonsterType::VolOptMonitor)));
}
for _ in 0..2 {
monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused)));
}
monsters.push(Some(MapEnemy::new(MonsterType::VolOptAmp)));
monsters.push(Some(MapEnemy::new(MonsterType::VolOptCore)));
monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused)));
},
// TOOD: this cares about difficulty (theres an ult-specific darvant?)
MonsterType::DarkFalz => {
for _ in 0..509 {
monsters.push(Some(MapEnemy::new(MonsterType::Darvant)));
}
monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz3)));
monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz2)));
monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz1)));
},
_ => {
warn!("children: {}", enemy.children);
for _ in 0..enemy.children {
monsters.push(Some(MapEnemy::new(monster.monster)));
}
}
}
monsters
}));
}
enemy_data
}
#[derive(Debug)]
pub struct Maps {
map_variants: [MapVariant; 15],
enemy_data: Vec<Option<MapEnemy>>
}
impl Maps {
pub fn new() -> Maps {
pub fn new(episode: Episode) -> Maps {
warn!("new maps ep: {:?}", episode);
let map_variants = match episode {
Episode::One => {
[MapVariant::new(MapVariantType::Pioneer2Ep1, MapVariantMode::Online),
MapVariant::new(MapVariantType::Forest1, MapVariantMode::Online),
MapVariant::new(MapVariantType::Forest2, MapVariantMode::Online),
MapVariant::new(MapVariantType::Caves1, MapVariantMode::Online),
MapVariant::new(MapVariantType::Caves2, MapVariantMode::Online),
MapVariant::new(MapVariantType::Caves3, MapVariantMode::Online),
MapVariant::new(MapVariantType::Mines1, MapVariantMode::Online),
MapVariant::new(MapVariantType::Mines2, MapVariantMode::Online),
MapVariant::new(MapVariantType::Ruins1, MapVariantMode::Online),
MapVariant::new(MapVariantType::Ruins2, MapVariantMode::Online),
MapVariant::new(MapVariantType::Ruins3, MapVariantMode::Online),
MapVariant::new(MapVariantType::Dragon, MapVariantMode::Online),
MapVariant::new(MapVariantType::DeRolLe, MapVariantMode::Online),
MapVariant::new(MapVariantType::VolOpt, MapVariantMode::Online),
MapVariant::new(MapVariantType::DarkFalz, MapVariantMode::Online),
]
},
_ => panic!()
};
let mut maps = Maps {
enemy_data: Vec::new(),
enemy_data: map_variants.iter().fold(Vec::new(), |mut enemy_data, map_variant| {
enemy_data.append(&mut enemy_data_from_map_data(map_variant.dat_file().into(), &episode));
enemy_data
}),
map_variants: map_variants,
};
maps.add_map("data/maps/map_city00_00e.dat".into());
maps.add_map("data/maps/map_forest01_00e.dat".into());
maps.add_map("data/maps/map_cave01_00_00e.dat".into());
warn!("len {}", maps.enemy_data.len());
maps
}
fn add_map(&mut self, path: PathBuf) {
let mut cursor = File::open(path).unwrap();
while let Ok(enemy) = RawMapEnemy::from_byte_stream(&mut cursor) {
let new_enemy = MapEnemy::from_raw(enemy);
match new_enemy.monster {
MonsterType::Monest => {
self.enemy_data.push(new_enemy);
for _ in 0..30 {
self.enemy_data.push(MapEnemy::new(MonsterType::Mothmant));
}
},
_ => self.enemy_data.push(new_enemy)
}
}
pub fn enemy_by_id(&self, id: usize) -> MapEnemy {
self.enemy_data[id].unwrap()
}
pub fn enemy_by_id(&self, id: usize) -> MapEnemy {
self.enemy_data[id]
pub fn map_headers(&self) -> [u32; 0x20] {
self.map_variants.iter()
.enumerate()
.fold([0; 0x20], |mut header, (i, map_variant)| {
let [major, minor] = map_variant.pkt_header();
header[i*2] = major as u32;
header[i*2 + 1] = minor as u32;
header
})
}
}

15
src/ship/room.rs

@ -1,5 +1,7 @@
use std::convert::{From, Into, TryFrom, TryInto};
use crate::ship::map::Maps;
#[derive(Debug)]
pub enum RoomCreationError {
InvalidMode,
@ -117,7 +119,8 @@ pub struct RoomState {
mode: RoomMode,
pub name: String,
password: [u16; 16],
pub maps: [u32; 0x20],
//pub maps: [u32; 0x20],
pub maps: Maps,
// drop_table
// items on ground
// enemy info
@ -158,12 +161,18 @@ impl RoomState {
difficulty: create_room.difficulty.try_into()?,
}
};
let ep = room_mode.episode();
Ok(RoomState {
mode: room_mode,
name: String::from_utf16_lossy(&create_room.name).trim_matches(char::from(0)).into(),
password: create_room.password,
maps: [0; 0x20],
//maps: [0; 0x20],
maps: Maps::new(ep),
})
}
pub fn map_headers(&self) -> [u32; 0x20] {
self.maps.map_headers()
}
}

2
src/ship/ship.rs

@ -369,7 +369,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
let join_room = JoinRoom {
flag: 1,
maps: room.maps,
maps: room.maps.map_headers(),
players: players,
client_id: 0,
leader_id: 0,

Loading…
Cancel
Save