2024-08-23 11:22:09 +00:00
|
|
|
// engine
|
|
|
|
use engine::prelude::*;
|
|
|
|
|
|
|
|
use assetpath::AssetPath;
|
|
|
|
|
|
|
|
// use lua_wrapper::LuaFunction;
|
|
|
|
|
|
|
|
use anyhow::Result;
|
2024-08-25 07:11:52 +00:00
|
|
|
use entity_manager::*;
|
2024-08-23 11:22:09 +00:00
|
|
|
use lua_wrapper::LuaFunction;
|
2024-08-24 13:36:58 +00:00
|
|
|
use rpg_components::config::abilities::AbilitySettings;
|
|
|
|
use rpg_components::config::attributes::AttributeSettings;
|
|
|
|
use rpg_components::config::experience::ExperienceSettings;
|
|
|
|
use rpg_components::config::items::ItemSettings;
|
2024-08-25 09:44:44 +00:00
|
|
|
use rpg_components::items::{ItemSystem, ToolTipBuilder};
|
2024-08-23 11:22:09 +00:00
|
|
|
|
|
|
|
// std
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::sync::{Mutex, MutexGuard, RwLock};
|
|
|
|
use std::{fs::create_dir_all, path::Path, sync::Arc};
|
|
|
|
|
|
|
|
// game
|
|
|
|
use crate::game::configloader::*;
|
|
|
|
use crate::loader::settings::*;
|
|
|
|
|
|
|
|
use cgmath::Vector3;
|
|
|
|
use promise::Promise;
|
|
|
|
|
|
|
|
use super::handle::{StrongHandle, WeakHandle};
|
|
|
|
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
|
|
pub struct MapInformation {
|
|
|
|
// root directories for maps
|
|
|
|
pub map_directories: Vec<AssetPath>,
|
|
|
|
|
|
|
|
// possible start map, where players get spawned on connection
|
|
|
|
pub start_map: Option<String>,
|
|
|
|
|
|
|
|
// maps that are going to be ignored
|
|
|
|
pub black_list: Vec<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Game {
|
|
|
|
engine: Arc<Engine>,
|
|
|
|
|
|
|
|
game_settings: GameSection,
|
|
|
|
_lua_scripts: LuaScripts,
|
|
|
|
|
|
|
|
data_directory: String,
|
|
|
|
|
|
|
|
pub attribute_settings: AttributeSettings,
|
|
|
|
pub item_settings: ItemSettings,
|
|
|
|
pub experience_settings: ExperienceSettings,
|
|
|
|
pub mob_settings: MobSettings,
|
|
|
|
pub ability_settings: AbilitySettings,
|
|
|
|
|
|
|
|
pub maps: RwLock<HashMap<String, AssetPath>>,
|
|
|
|
pub black_listed_maps: RwLock<HashMap<String, AssetPath>>,
|
|
|
|
pub tiles: RwLock<HashMap<String, AssetPath>>,
|
|
|
|
|
|
|
|
settings_file_location: AssetPath,
|
|
|
|
|
|
|
|
item_system: Promise<Arc<ItemSystem>>,
|
|
|
|
|
|
|
|
entity_manager: Mutex<EntityManager>,
|
|
|
|
|
|
|
|
slide_images: Mutex<HashMap<String, Arc<Image>>>,
|
|
|
|
|
|
|
|
pub change_map_context: LuaFunction,
|
|
|
|
|
|
|
|
map_info: MapInformation,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type GameHandle = WeakHandle<Game>;
|
|
|
|
pub type StrongGame = StrongHandle<Game>;
|
|
|
|
|
|
|
|
impl GameHandle {
|
|
|
|
pub fn gui_builder(&self, path: &str) -> Result<Arc<GuiBuilder>> {
|
|
|
|
let strong = self.upgrade();
|
|
|
|
|
|
|
|
GuiBuilder::new(strong.engine.gui_handler(), &strong.build_data_path(path))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn gui_snippet(&self, path: &str) -> Result<Arc<GuiSnippet>> {
|
|
|
|
let strong = self.upgrade();
|
|
|
|
|
|
|
|
GuiSnippet::new(strong.engine.gui_handler(), &strong.build_data_path(path))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn controller_icon(&self, button: ControllerButton) -> Result<Arc<Image>> {
|
|
|
|
let game = self.upgrade();
|
|
|
|
let engine = game.engine();
|
|
|
|
|
|
|
|
engine
|
|
|
|
.settings()
|
|
|
|
.controller_button_for(engine, button, ControllerType::XBox)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_data_path(&self, path: &str) -> AssetPath {
|
|
|
|
self.upgrade().build_data_path(path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-25 09:44:44 +00:00
|
|
|
impl ToolTipBuilder for GameHandle {
|
|
|
|
fn asset_path(&self, s: &str) -> AssetPath {
|
|
|
|
self.build_data_path(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gui_handler(&self) -> Arc<GuiHandler> {
|
|
|
|
self.upgrade().engine().gui_handler().clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-23 11:22:09 +00:00
|
|
|
pub struct Settings {
|
|
|
|
pub core_settings: CoreSettings,
|
|
|
|
pub user_settings: UserSettings,
|
|
|
|
pub data_path: String,
|
|
|
|
pub user_settings_file: AssetPath,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Game {
|
|
|
|
pub fn load_settings<'a>(data_path: impl Into<Option<&'a str>>) -> Result<Settings> {
|
|
|
|
let data_path = data_path.into().unwrap_or("data");
|
|
|
|
|
|
|
|
println!("Data directory: {}", data_path);
|
|
|
|
|
|
|
|
let mut core_settings = CoreSettings::load((data_path, "settings.conf"))?;
|
|
|
|
let mut user_settings = UserSettings::load((data_path, "user_settings.conf"))?;
|
|
|
|
|
|
|
|
let gavania_save_dir = settings_file_dir();
|
|
|
|
Self::verify_dir_existence(&gavania_save_dir)?;
|
|
|
|
|
|
|
|
let user_settings_file = AssetPath::from((gavania_save_dir, "user_settings.conf"));
|
|
|
|
|
|
|
|
if user_settings_file.exists() {
|
|
|
|
user_settings.load_with_default(user_settings_file.clone())?;
|
|
|
|
} else {
|
|
|
|
user_settings.file_name = user_settings_file.clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
user_settings.store()?;
|
|
|
|
|
|
|
|
Self::apply_data_dir(&mut core_settings, data_path);
|
|
|
|
|
|
|
|
Ok(Settings {
|
|
|
|
core_settings,
|
|
|
|
user_settings,
|
|
|
|
data_path: data_path.to_string(),
|
|
|
|
user_settings_file,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new(settings: Settings) -> Result<StrongGame> {
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
{
|
|
|
|
Self::set_radeon_ray_tracing();
|
|
|
|
|
|
|
|
#[cfg(feature = "wayland")]
|
|
|
|
Self::check_wayland_for_sdl();
|
|
|
|
}
|
|
|
|
|
|
|
|
let game_settings = settings.core_settings.game.clone();
|
|
|
|
let lua_scripts = settings.core_settings.lua_scripts.clone();
|
|
|
|
let map_info = settings.core_settings.map_info();
|
|
|
|
|
|
|
|
#[allow(unused_mut)]
|
|
|
|
let mut engine_create_info =
|
|
|
|
into_engine_info(settings.core_settings, settings.user_settings);
|
|
|
|
|
|
|
|
{
|
|
|
|
engine_create_info.app_info.application_name = "Gavania".to_string();
|
|
|
|
engine_create_info.app_info.application_version = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
let attribute_settings =
|
|
|
|
AttributeSettings::load((settings.data_path.as_str(), "configs/stats.conf"))?;
|
|
|
|
let mut item_settings =
|
|
|
|
ItemSettings::load((settings.data_path.as_str(), "configs/items.conf"))?;
|
|
|
|
let experience_settings =
|
|
|
|
ExperienceSettings::load((settings.data_path.as_str(), "configs/experience.conf"))?;
|
|
|
|
let mob_settings = MobSettings::load((settings.data_path.as_str(), "configs/mobs.conf"))?;
|
|
|
|
let mut ability_settings =
|
|
|
|
AbilitySettings::load((settings.data_path.as_str(), "configs/abilities.conf"))?;
|
|
|
|
|
|
|
|
Self::apply_data_dir_to_configs(
|
|
|
|
&mut item_settings,
|
|
|
|
&mut ability_settings,
|
|
|
|
&settings.data_path,
|
|
|
|
);
|
|
|
|
|
|
|
|
// ----------------- maps ---------------------
|
|
|
|
let mut map_map = HashMap::new();
|
|
|
|
let mut black_listed_maps = HashMap::new();
|
|
|
|
|
|
|
|
for map_directory in map_info.map_directories.iter() {
|
|
|
|
let map_vector = search_dir_recursively(&map_directory.full_path(), "")?;
|
|
|
|
|
|
|
|
'outer: for file in &map_vector {
|
|
|
|
let s = file.full_path();
|
|
|
|
let path = Path::new(s.as_str());
|
|
|
|
|
|
|
|
if let Some(name) = path.file_stem() {
|
|
|
|
if let Some(name_str) = name.to_str() {
|
|
|
|
let string = name_str.to_string();
|
|
|
|
|
|
|
|
for blacked in map_info.black_list.iter() {
|
|
|
|
if *blacked == string {
|
|
|
|
assert!(
|
|
|
|
black_listed_maps
|
|
|
|
.insert(string.clone(), file.clone())
|
|
|
|
.is_none(),
|
|
|
|
"blacklisted map already present: {}",
|
|
|
|
string
|
|
|
|
);
|
|
|
|
|
|
|
|
continue 'outer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert!(
|
|
|
|
map_map.insert(string.clone(), file.clone()).is_none(),
|
|
|
|
"map already present: {}",
|
|
|
|
string
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let game = {
|
|
|
|
engine_create_info.gui_info.resource_directory = {
|
|
|
|
let mut path = AssetPath::from(settings.data_path.as_str());
|
|
|
|
path.assume_prefix_free();
|
|
|
|
|
|
|
|
path
|
|
|
|
};
|
|
|
|
engine_create_info.resource_base_path = settings.data_path.clone();
|
|
|
|
|
|
|
|
let engine = Engine::new(engine_create_info.clone())?;
|
|
|
|
|
2024-08-25 10:03:07 +00:00
|
|
|
// ----------------- tiles --------------------
|
|
|
|
let tile_vector = search_dir_recursively(
|
|
|
|
engine.settings().tiles_directory().full_path().as_str(),
|
|
|
|
".png",
|
|
|
|
)?;
|
|
|
|
let mut tile_map = HashMap::new();
|
|
|
|
|
|
|
|
for file in &tile_vector {
|
|
|
|
let s = file.full_path();
|
|
|
|
let path = Path::new(s.as_str());
|
|
|
|
|
|
|
|
if let Some(name) = path.file_stem() {
|
|
|
|
if let Some(name_str) = name.to_str() {
|
|
|
|
let string = name_str.to_string();
|
|
|
|
|
|
|
|
tile_map.insert(string.clone(), file.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-23 11:22:09 +00:00
|
|
|
let item_system = Promise::new({
|
|
|
|
let engine = engine.clone();
|
|
|
|
let item_settings = item_settings.clone();
|
|
|
|
let ability_settings = ability_settings.clone();
|
|
|
|
let attribute_settings = attribute_settings.clone();
|
|
|
|
let ability_directory = game_settings.ability_directory.clone();
|
|
|
|
let data_path = settings.data_path.clone();
|
|
|
|
|
|
|
|
move || {
|
|
|
|
Ok(Arc::new(ItemSystem::new(
|
|
|
|
&engine,
|
|
|
|
&item_settings,
|
|
|
|
&ability_settings,
|
|
|
|
&attribute_settings,
|
|
|
|
&ability_directory,
|
|
|
|
&data_path,
|
|
|
|
)?))
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
StrongHandle::new(Game {
|
|
|
|
engine,
|
|
|
|
|
|
|
|
maps: RwLock::new(map_map),
|
|
|
|
black_listed_maps: RwLock::new(black_listed_maps),
|
|
|
|
tiles: RwLock::new(tile_map),
|
|
|
|
|
|
|
|
change_map_context: LuaFunction::new(&lua_scripts.change_map)?,
|
|
|
|
game_settings,
|
|
|
|
_lua_scripts: lua_scripts,
|
|
|
|
|
|
|
|
data_directory: settings.data_path.to_string(),
|
|
|
|
|
|
|
|
attribute_settings,
|
|
|
|
item_settings,
|
|
|
|
experience_settings,
|
|
|
|
mob_settings,
|
|
|
|
ability_settings,
|
|
|
|
|
|
|
|
item_system,
|
|
|
|
|
|
|
|
entity_manager: Mutex::new(EntityManager::new(
|
|
|
|
engine_create_info.asset_directories.entity_file_directory,
|
|
|
|
)?),
|
|
|
|
|
|
|
|
settings_file_location: settings.user_settings_file,
|
|
|
|
|
|
|
|
slide_images: Mutex::new(HashMap::new()),
|
|
|
|
|
|
|
|
map_info,
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(game)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn verify_dir_existence(dir: &str) -> Result<()> {
|
|
|
|
let path = Path::new(&dir);
|
|
|
|
|
|
|
|
if !path.exists() {
|
|
|
|
create_dir_all(path)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run(&self) -> Result<()> {
|
|
|
|
self.engine.run()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_game_state<E>(&self, game_object: E) -> Result<()>
|
|
|
|
where
|
|
|
|
E: EngineObject + Send + Sync,
|
|
|
|
{
|
|
|
|
self.engine.set_game_object(Some(game_object))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn quit(&self) -> Result<()> {
|
|
|
|
self.store_settings()?;
|
|
|
|
|
|
|
|
self.engine.quit()?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
fn set_radeon_ray_tracing() {
|
|
|
|
std::env::set_var("RADV_PERFTEST", "rt");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "wayland")]
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
fn check_wayland_for_sdl() {
|
|
|
|
if let Ok(session_type) = std::env::var("XDG_SESSION_TYPE") {
|
|
|
|
if session_type == "wayland" {
|
|
|
|
std::env::set_var("SDL_VIDEODRIVER", "wayland");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn map_directories(&self) -> &[AssetPath] {
|
|
|
|
&self.map_info.map_directories
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn home_map(&self) -> Option<&String> {
|
|
|
|
self.map_info.start_map.as_ref()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn black_listed_maps(&self) -> &[String] {
|
|
|
|
&self.map_info.black_list
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn engine(&self) -> &Arc<Engine> {
|
|
|
|
&self.engine
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn game_settings(&self) -> &GameSection {
|
|
|
|
&self.game_settings
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn item_system(&self) -> Arc<ItemSystem> {
|
|
|
|
self.item_system.get()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn data_directory(&self) -> &str {
|
|
|
|
&self.data_directory
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_data_path(&self, path: &str) -> AssetPath {
|
|
|
|
AssetPath::from((self.data_directory.as_str(), path))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn entity_manager(&self) -> MutexGuard<'_, EntityManager> {
|
|
|
|
self.entity_manager.lock().unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn slide_images(&self) -> MutexGuard<'_, HashMap<String, Arc<Image>>> {
|
|
|
|
self.slide_images.lock().unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn gui_builder(&self, path: &str) -> Result<Arc<GuiBuilder>> {
|
|
|
|
GuiBuilder::new(self.engine.gui_handler(), &self.build_data_path(path))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn gui_snippet(&self, path: &str) -> Result<Arc<GuiSnippet>> {
|
|
|
|
GuiSnippet::new(self.engine.gui_handler(), &self.build_data_path(path))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn store_settings(&self) -> Result<()> {
|
|
|
|
let mut user_settings = UserSettings::load(self.settings_file_location.clone())?;
|
|
|
|
|
|
|
|
// first update settings
|
|
|
|
if self.engine.window_config().is_fullscreen() {
|
|
|
|
user_settings.window.fullscreen = true;
|
|
|
|
} else {
|
|
|
|
user_settings.window.fullscreen = false;
|
|
|
|
let render_core = self.engine.context().render_core();
|
|
|
|
|
|
|
|
user_settings.window.width = render_core.width();
|
|
|
|
user_settings.window.height = render_core.height();
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let sound = self.engine.sound();
|
|
|
|
|
|
|
|
user_settings.audio.master = sound.volume("master")?;
|
|
|
|
user_settings.audio.gui = sound.volume("gui")?;
|
|
|
|
user_settings.audio.sfx = sound.volume("sfx")?;
|
|
|
|
user_settings.audio.music = sound.volume("music")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if renderer type actually changed
|
|
|
|
// if so, clear all loaded entities
|
|
|
|
let renderer_type = self.engine.settings().graphics_info()?.render_type;
|
|
|
|
|
|
|
|
if renderer_type != user_settings.graphics.renderer_type {
|
|
|
|
user_settings.graphics.renderer_type = renderer_type;
|
|
|
|
|
|
|
|
self.engine.assets().clear()?;
|
|
|
|
}
|
|
|
|
|
|
|
|
user_settings.store()?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_frustum_check(scene: &mut Scene) {
|
|
|
|
let entity_name = "Lightning".to_string();
|
|
|
|
|
|
|
|
scene.set_frustum_check(move |entity, _view_proj, _view_frustum, frustum_planes| {
|
|
|
|
// filter everything that isnt Draw
|
|
|
|
if !entity.contains_component::<Draw>() {
|
|
|
|
if entity.debug_name.as_ref() == Some(&entity_name) {
|
|
|
|
println!("{entity_name}-Entity does not contain Draw");
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// filter everything that isnt Bounding Box
|
|
|
|
let bb = match entity.get_component::<BoundingBox>() {
|
|
|
|
Ok(bounding_box) => bounding_box,
|
|
|
|
Err(_) => {
|
|
|
|
if entity.debug_name.as_ref() == Some(&entity_name) {
|
|
|
|
println!("{entity_name}-Entity does not contain BoundingBox");
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let transformation_matrix = entity
|
|
|
|
.get_component::<Location>()
|
|
|
|
.ok()
|
|
|
|
.map(|location| location.transformation_matrix());
|
|
|
|
|
|
|
|
let planes = frustum_planes.as_array();
|
|
|
|
let corners: Vec<Vector3<f32>> = bb
|
|
|
|
.corners()
|
|
|
|
.iter()
|
|
|
|
.map(|corner| match transformation_matrix {
|
|
|
|
Some(m) => (m * corner.extend(1.0)).xyz(),
|
|
|
|
None => *corner,
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
// if there is a plane where all corners are outside, the box is not visible
|
|
|
|
for plane in planes {
|
|
|
|
let mut outside = true;
|
|
|
|
|
|
|
|
for corner in corners.iter() {
|
|
|
|
if !plane.is_above(*corner) {
|
|
|
|
outside = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if outside {
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if entity.debug_name.as_ref() == Some(&entity_name) {
|
|
|
|
println!("{entity_name}-Entity is inside");
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(true)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn apply_data_dir(settings: &mut CoreSettings, data_dir: &str) {
|
|
|
|
// game
|
|
|
|
settings.game.sounds_directory.set_prefix(data_dir);
|
|
|
|
settings.game.music_directory.set_prefix(data_dir);
|
|
|
|
settings.game.ability_icon_directory.set_prefix(data_dir);
|
|
|
|
settings.game.ability_directory.set_prefix(data_dir);
|
|
|
|
settings.game.particle_directory.set_prefix(data_dir);
|
|
|
|
settings.game.slides_directory.set_prefix(data_dir);
|
|
|
|
settings.game.npc_directory.set_prefix(data_dir);
|
|
|
|
|
|
|
|
// map info
|
|
|
|
settings.map_infos.directory.set_prefix(data_dir);
|
|
|
|
|
|
|
|
// scripts
|
|
|
|
settings.lua_scripts.change_map.set_prefix(data_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn apply_data_dir_to_configs(
|
|
|
|
item_settings: &mut ItemSettings,
|
|
|
|
ability_settings: &mut AbilitySettings,
|
|
|
|
data_dir: &str,
|
|
|
|
) {
|
|
|
|
item_settings.icon_paths.amulet.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.background.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.boots.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.chest.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.helmet.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.jewel.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.ring.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.belt.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.gloves.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.main_hand.set_prefix(data_dir);
|
|
|
|
item_settings.icon_paths.off_hand.set_prefix(data_dir);
|
|
|
|
|
|
|
|
item_settings.jewel_paths.first.set_prefix(data_dir);
|
|
|
|
item_settings.jewel_paths.second.set_prefix(data_dir);
|
|
|
|
item_settings.jewel_paths.third.set_prefix(data_dir);
|
|
|
|
item_settings.jewel_paths.fourth.set_prefix(data_dir);
|
|
|
|
|
|
|
|
ability_settings.icons.book.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.damage.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.projectile_speed.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.bounce.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.explosion.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.size.set_prefix(data_dir);
|
|
|
|
ability_settings
|
|
|
|
.icons
|
|
|
|
.additional_projectiles
|
|
|
|
.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.cool_down.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.distance.set_prefix(data_dir);
|
|
|
|
ability_settings.icons.addon_background.set_prefix(data_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gather_maps(
|
|
|
|
map_directories: &[AssetPath],
|
|
|
|
home_map: Option<&str>,
|
|
|
|
ignore_maps: &[String],
|
|
|
|
) -> Result<Vec<String>> {
|
|
|
|
let mut maps = Vec::new();
|
|
|
|
|
|
|
|
for map_directory in map_directories.iter() {
|
|
|
|
for map in search_dir_recursively(&map_directory.full_path(), "")? {
|
|
|
|
let map_name = Path::new(&map.full_path())
|
|
|
|
.file_name()
|
|
|
|
.expect("map is not a file name")
|
|
|
|
.to_str()
|
|
|
|
.expect("failed converting OsStr to str")
|
|
|
|
.to_string();
|
|
|
|
|
|
|
|
if let Some(home) = home_map {
|
|
|
|
if map_name == home {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ignore_maps.contains(&map_name) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
maps.push(map_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(maps)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_map(&self, current_map: &str) -> Result<String> {
|
|
|
|
let map_directories = self.map_directories();
|
|
|
|
let home_map = self.home_map().map(|s| s.as_str());
|
|
|
|
let ignore_maps: Vec<String> = self
|
|
|
|
.black_listed_maps
|
|
|
|
.read()
|
|
|
|
.unwrap()
|
|
|
|
.keys()
|
|
|
|
.cloned()
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
let maps = Self::gather_maps(map_directories, home_map, &ignore_maps)?;
|
|
|
|
let map_count = maps.len();
|
|
|
|
|
|
|
|
let next_map = self.change_map_context.execute((
|
|
|
|
current_map,
|
|
|
|
home_map.unwrap_or(""),
|
|
|
|
maps,
|
|
|
|
map_count,
|
|
|
|
))?;
|
|
|
|
|
|
|
|
Ok(next_map)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Game {
|
|
|
|
fn drop(&mut self) {}
|
|
|
|
}
|