mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Started moving loading of ability manifest to an ecs variable.
This commit is contained in:
parent
050ad82e55
commit
9b4fa4e961
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
assets::{self, Asset},
|
||||
comp::{
|
||||
item::{armor::Protection, Item, ItemKind},
|
||||
item::{armor::Protection, tool::AbilityMap, Item, ItemKind},
|
||||
projectile::ProjectileConstructor,
|
||||
Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
|
||||
},
|
||||
@ -325,10 +325,10 @@ pub struct ItemConfig {
|
||||
pub dodge_ability: Option<CharacterAbility>,
|
||||
}
|
||||
|
||||
impl From<Item> for ItemConfig {
|
||||
fn from(item: Item) -> Self {
|
||||
impl From<(Item, &AbilityMap)> for ItemConfig {
|
||||
fn from((item, map): (Item, &AbilityMap)) -> Self {
|
||||
if let ItemKind::Tool(tool) = &item.kind() {
|
||||
let abilities = tool.get_abilities().clone();
|
||||
let abilities = tool.get_abilities(map).clone();
|
||||
|
||||
return ItemConfig {
|
||||
item,
|
||||
|
@ -2,7 +2,7 @@ pub mod armor;
|
||||
pub mod tool;
|
||||
|
||||
// Reexports
|
||||
pub use tool::{Hands, Tool, ToolKind, UniqueKind};
|
||||
pub use tool::{AbilitySet, Hands, Tool, ToolKind, UniqueKind};
|
||||
|
||||
use crate::{
|
||||
assets::{self, Asset, Error},
|
||||
|
@ -95,7 +95,7 @@ impl Tool {
|
||||
Duration::from_millis(millis).div_f32(self.base_speed())
|
||||
}
|
||||
|
||||
pub fn get_abilities(&self) -> AbilitySet<CharacterAbility> {
|
||||
pub fn get_abilities(&self, map: &AbilityMap) -> AbilitySet<CharacterAbility> {
|
||||
let base_abilities = match AbilityMap::load("common.abilities.weapon_ability_manifest") {
|
||||
Ok(map) => map.0.get(&self.kind).map(|a| a.clone()).unwrap_or_default(),
|
||||
Err(err) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
comp,
|
||||
comp::{item, item::armor, ItemConfig},
|
||||
comp::{item::{self, armor, tool::AbilityMap}, ItemConfig},
|
||||
};
|
||||
use comp::{Inventory, Loadout};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -90,6 +90,7 @@ fn loadout_replace(
|
||||
equip_slot: EquipSlot,
|
||||
item: Option<item::Item>,
|
||||
loadout: &mut Loadout,
|
||||
map: &AbilityMap,
|
||||
) -> Option<item::Item> {
|
||||
use std::mem::replace;
|
||||
match equip_slot {
|
||||
@ -107,10 +108,10 @@ fn loadout_replace(
|
||||
EquipSlot::Lantern => replace(&mut loadout.lantern, item),
|
||||
EquipSlot::Glider => replace(&mut loadout.glider, item),
|
||||
EquipSlot::Mainhand => {
|
||||
replace(&mut loadout.active_item, item.map(ItemConfig::from)).map(|i| i.item)
|
||||
replace(&mut loadout.active_item, item.map(|item| ItemConfig::from((item, map)))).map(|i| i.item)
|
||||
},
|
||||
EquipSlot::Offhand => {
|
||||
replace(&mut loadout.second_item, item.map(ItemConfig::from)).map(|i| i.item)
|
||||
replace(&mut loadout.second_item, item.map(|item| ItemConfig::from((item, map)))).map(|i| i.item)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -122,8 +123,9 @@ fn loadout_insert(
|
||||
equip_slot: EquipSlot,
|
||||
item: item::Item,
|
||||
loadout: &mut Loadout,
|
||||
map: &AbilityMap,
|
||||
) -> Option<item::Item> {
|
||||
loadout_replace(equip_slot, Some(item), loadout)
|
||||
loadout_replace(equip_slot, Some(item), loadout, map)
|
||||
}
|
||||
|
||||
/// Remove an item from a loadout.
|
||||
@ -151,8 +153,8 @@ fn loadout_insert(
|
||||
/// loadout_remove(slot, &mut loadout);
|
||||
/// assert_eq!(None, loadout.active_item);
|
||||
/// ```
|
||||
pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout) -> Option<item::Item> {
|
||||
loadout_replace(equip_slot, None, loadout)
|
||||
pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout, map: &AbilityMap) -> Option<item::Item> {
|
||||
loadout_replace(equip_slot, None, loadout, map)
|
||||
}
|
||||
|
||||
/// Swap item in an inventory slot with one in a loadout slot.
|
||||
@ -161,6 +163,7 @@ fn swap_inventory_loadout(
|
||||
equip_slot: EquipSlot,
|
||||
inventory: &mut Inventory,
|
||||
loadout: &mut Loadout,
|
||||
map: &AbilityMap,
|
||||
) {
|
||||
// Check if loadout slot can hold item
|
||||
if inventory
|
||||
@ -168,7 +171,7 @@ fn swap_inventory_loadout(
|
||||
.map_or(true, |item| equip_slot.can_hold(&item.kind()))
|
||||
{
|
||||
// Take item from loadout
|
||||
let from_equip = loadout_remove(equip_slot, loadout);
|
||||
let from_equip = loadout_remove(equip_slot, loadout, map);
|
||||
// Swap with item in the inventory
|
||||
let from_inv = if let Some(item) = from_equip {
|
||||
// If this fails and we get item back as an err it will just be put back in the
|
||||
@ -179,14 +182,14 @@ fn swap_inventory_loadout(
|
||||
};
|
||||
// Put item from the inventory in loadout
|
||||
if let Some(item) = from_inv {
|
||||
loadout_insert(equip_slot, item, loadout).unwrap_none(); // Can never fail
|
||||
loadout_insert(equip_slot, item, loadout, map).unwrap_none(); // Can never fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Swap items in loadout. Does nothing if items are not compatible with their
|
||||
/// new slots.
|
||||
fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) {
|
||||
fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout, map: &AbilityMap) {
|
||||
// Ensure that the slots are not the same
|
||||
if slot_a == slot_b {
|
||||
warn!("Tried to swap equip slot with itself");
|
||||
@ -194,19 +197,19 @@ fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) {
|
||||
}
|
||||
|
||||
// Get items from the slots
|
||||
let item_a = loadout_remove(slot_a, loadout);
|
||||
let item_b = loadout_remove(slot_b, loadout);
|
||||
let item_a = loadout_remove(slot_a, loadout, map);
|
||||
let item_b = loadout_remove(slot_b, loadout, map);
|
||||
// Check if items can go in the other slots
|
||||
if item_a.as_ref().map_or(true, |i| slot_b.can_hold(&i.kind()))
|
||||
&& item_b.as_ref().map_or(true, |i| slot_a.can_hold(&i.kind()))
|
||||
{
|
||||
// Swap
|
||||
loadout_replace(slot_b, item_a, loadout).unwrap_none();
|
||||
loadout_replace(slot_a, item_b, loadout).unwrap_none();
|
||||
loadout_replace(slot_b, item_a, loadout, map).unwrap_none();
|
||||
loadout_replace(slot_a, item_b, loadout, map).unwrap_none();
|
||||
} else {
|
||||
// Otherwise put the items back
|
||||
loadout_replace(slot_a, item_a, loadout).unwrap_none();
|
||||
loadout_replace(slot_b, item_b, loadout).unwrap_none();
|
||||
loadout_replace(slot_a, item_a, loadout, map).unwrap_none();
|
||||
loadout_replace(slot_b, item_b, loadout, map).unwrap_none();
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,6 +222,7 @@ pub fn swap(
|
||||
slot_b: Slot,
|
||||
inventory: Option<&mut Inventory>,
|
||||
loadout: Option<&mut Loadout>,
|
||||
map: &AbilityMap,
|
||||
) {
|
||||
match (slot_a, slot_b) {
|
||||
(Slot::Inventory(slot_a), Slot::Inventory(slot_b)) => {
|
||||
@ -227,12 +231,12 @@ pub fn swap(
|
||||
(Slot::Inventory(inv_slot), Slot::Equip(equip_slot))
|
||||
| (Slot::Equip(equip_slot), Slot::Inventory(inv_slot)) => {
|
||||
if let Some((inventory, loadout)) = loadout.and_then(|l| inventory.map(|i| (i, l))) {
|
||||
swap_inventory_loadout(inv_slot, equip_slot, inventory, loadout);
|
||||
swap_inventory_loadout(inv_slot, equip_slot, inventory, loadout, map);
|
||||
}
|
||||
},
|
||||
|
||||
(Slot::Equip(slot_a), Slot::Equip(slot_b)) => {
|
||||
loadout.map(|l| swap_loadout(slot_a, slot_b, l));
|
||||
loadout.map(|l| swap_loadout(slot_a, slot_b, l, map));
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -261,7 +265,7 @@ pub fn swap(
|
||||
/// equip(0, &mut inv, &mut loadout);
|
||||
/// assert_eq!(Some(boots), loadout.foot);
|
||||
/// ```
|
||||
pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) {
|
||||
pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout, map: &AbilityMap) {
|
||||
use armor::Armor;
|
||||
use item::{armor::ArmorKind, ItemKind};
|
||||
|
||||
@ -289,10 +293,10 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) {
|
||||
// If item is going to mainhand, put mainhand in offhand and place offhand in
|
||||
// inventory
|
||||
if let EquipSlot::Mainhand = equip_slot {
|
||||
swap_loadout(EquipSlot::Mainhand, EquipSlot::Offhand, loadout);
|
||||
swap_loadout(EquipSlot::Mainhand, EquipSlot::Offhand, loadout, map);
|
||||
}
|
||||
|
||||
swap_inventory_loadout(slot, equip_slot, inventory, loadout);
|
||||
swap_inventory_loadout(slot, equip_slot, inventory, loadout, map);
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,10 +326,10 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) {
|
||||
/// unequip(slot, &mut inv, &mut loadout);
|
||||
/// assert_eq!(None, loadout.active_item);
|
||||
/// ```
|
||||
pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout) {
|
||||
loadout_remove(slot, loadout) // Remove item from loadout
|
||||
pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout, map: &AbilityMap) {
|
||||
loadout_remove(slot, loadout, map) // Remove item from loadout
|
||||
.and_then(|i| inventory.push(i)) // Insert into inventory
|
||||
.and_then(|i| loadout_insert(slot, i, loadout)) // If that fails put back in loadout
|
||||
.and_then(|i| loadout_insert(slot, i, loadout, map)) // If that fails put back in loadout
|
||||
.unwrap_none(); // Never fails
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::comp::{
|
||||
biped_large, golem,
|
||||
item::{Item, ItemKind},
|
||||
item::{tool::AbilityMap, Item, ItemKind},
|
||||
Alignment, Body, CharacterAbility, ItemConfig, Loadout,
|
||||
};
|
||||
use rand::Rng;
|
||||
@ -72,6 +72,7 @@ impl LoadoutBuilder {
|
||||
alignment: Alignment,
|
||||
mut main_tool: Option<Item>,
|
||||
is_giant: bool,
|
||||
map: &AbilityMap,
|
||||
) -> Self {
|
||||
match body {
|
||||
Body::Golem(golem) => match golem.species {
|
||||
@ -145,21 +146,12 @@ impl LoadoutBuilder {
|
||||
};
|
||||
|
||||
let active_item = if let Some(ItemKind::Tool(_)) = main_tool.as_ref().map(|i| i.kind()) {
|
||||
main_tool.map(ItemConfig::from)
|
||||
main_tool.map(|item| ItemConfig::from((item, map)))
|
||||
} else {
|
||||
Some(ItemConfig {
|
||||
// We need the empty item so npcs can attack
|
||||
item: Item::new_from_asset_expect("common.items.weapons.empty.empty"),
|
||||
ability1: Some(CharacterAbility::BasicMelee {
|
||||
energy_cost: 0,
|
||||
buildup_duration: 0,
|
||||
swing_duration: 100,
|
||||
recover_duration: 300,
|
||||
base_damage: 40,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
max_angle: 15.0,
|
||||
}),
|
||||
ability1: Some(CharacterAbility::default()),
|
||||
ability2: None,
|
||||
ability3: None,
|
||||
block_ability: None,
|
||||
@ -370,7 +362,7 @@ impl LoadoutBuilder {
|
||||
/// abilities or their timings is desired, you should create and provide
|
||||
/// the item config directly to the [active_item](#method.active_item)
|
||||
/// method
|
||||
pub fn default_item_config_from_item(item: Item) -> ItemConfig { ItemConfig::from(item) }
|
||||
pub fn default_item_config_from_item(item: Item, map: &AbilityMap) -> ItemConfig { ItemConfig::from((item, map)) }
|
||||
|
||||
/// Get an item's (weapon's) default
|
||||
/// [ItemConfig](../comp/struct.ItemConfig.html)
|
||||
@ -378,8 +370,8 @@ impl LoadoutBuilder {
|
||||
/// the default abilities for that item via the
|
||||
/// [default_item_config_from_item](#method.default_item_config_from_item)
|
||||
/// function
|
||||
pub fn default_item_config_from_str(item_ref: &str) -> ItemConfig {
|
||||
Self::default_item_config_from_item(Item::new_from_asset_expect(item_ref))
|
||||
pub fn default_item_config_from_str(item_ref: &str, map: &AbilityMap) -> ItemConfig {
|
||||
Self::default_item_config_from_item(Item::new_from_asset_expect(item_ref), map)
|
||||
}
|
||||
|
||||
pub fn active_item(mut self, item: Option<ItemConfig>) -> Self {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
assets::Asset,
|
||||
comp,
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
metrics::{PhysicsMetrics, SysMetrics},
|
||||
@ -180,6 +181,7 @@ impl State {
|
||||
ecs.insert(BlockChange::default());
|
||||
ecs.insert(TerrainChanges::default());
|
||||
ecs.insert(EventBus::<LocalEvent>::default());
|
||||
ecs.insert(comp::item::tool::AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"));
|
||||
// TODO: only register on the server
|
||||
ecs.insert(EventBus::<ServerEvent>::default());
|
||||
ecs.insert(comp::group::GroupManager::default());
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::persistence::character_loader::CharacterLoader;
|
||||
use common::{
|
||||
comp::{Body, Inventory, Stats},
|
||||
comp::{item::tool::AbilityMap, Body, Inventory, Stats},
|
||||
loadout_builder::LoadoutBuilder,
|
||||
};
|
||||
use specs::{Entity, ReadExpect};
|
||||
@ -12,13 +12,14 @@ pub fn create_character(
|
||||
character_tool: Option<String>,
|
||||
body: Body,
|
||||
character_loader: &ReadExpect<'_, CharacterLoader>,
|
||||
map: &AbilityMap,
|
||||
) {
|
||||
let stats = Stats::new(character_alias.to_string(), body);
|
||||
|
||||
let loadout = LoadoutBuilder::new()
|
||||
.defaults()
|
||||
.active_item(Some(LoadoutBuilder::default_item_config_from_str(
|
||||
character_tool.as_deref().unwrap(),
|
||||
character_tool.as_deref().unwrap(), map
|
||||
)))
|
||||
.build();
|
||||
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
use chrono::{NaiveTime, Timelike};
|
||||
use common::{
|
||||
cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS},
|
||||
comp::{self, ChatType, Item, LightEmitter, WaypointArea},
|
||||
comp::{self, item::tool::AbilityMap, ChatType, Item, LightEmitter, WaypointArea},
|
||||
effect::Effect,
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral},
|
||||
@ -655,14 +655,17 @@ fn handle_spawn(
|
||||
|
||||
let body = body();
|
||||
|
||||
let map = server.state().ecs().fetch::<AbilityMap>();
|
||||
let loadout = LoadoutBuilder::build_loadout(body, alignment, None, false, &map).build();
|
||||
drop(map);
|
||||
|
||||
let mut entity_base = server
|
||||
.state
|
||||
.create_npc(
|
||||
pos,
|
||||
comp::Stats::new(get_npc_name(id).into(), body),
|
||||
comp::Health::new(body, 1),
|
||||
LoadoutBuilder::build_loadout(body, alignment, None, false)
|
||||
.build(),
|
||||
loadout,
|
||||
body,
|
||||
)
|
||||
.with(comp::Vel(vel))
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
Server,
|
||||
};
|
||||
use common::{
|
||||
comp::{self, item, Pos},
|
||||
comp::{self, item::{self, tool::AbilityMap}, Pos},
|
||||
consts::MAX_MOUNT_RANGE,
|
||||
msg::ServerGeneral,
|
||||
sync::{Uid, WorldSyncExt},
|
||||
@ -103,8 +103,8 @@ pub fn handle_unmount(server: &mut Server, mounter: EcsEntity) {
|
||||
|
||||
#[allow(clippy::nonminimal_bool)] // TODO: Pending review in #587
|
||||
pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) {
|
||||
let state = &server.state;
|
||||
let ecs = state.ecs();
|
||||
let ecs = &server.state.ecs();
|
||||
let map = ecs.fetch::<AbilityMap>();
|
||||
if let (Some(possessor), Some(possesse)) = (
|
||||
ecs.entity_from_uid(possessor_uid.into()),
|
||||
ecs.entity_from_uid(possesse_uid.into()),
|
||||
@ -177,7 +177,7 @@ pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) {
|
||||
|
||||
let item = comp::Item::new_from_asset_expect("common.items.debug.possess");
|
||||
if let item::ItemKind::Tool(_) = item.kind() {
|
||||
let debug_item = comp::ItemConfig::from(item);
|
||||
let debug_item = comp::ItemConfig::from((item, &*map));
|
||||
std::mem::swap(&mut loadout.active_item, &mut loadout.second_item);
|
||||
loadout.active_item = Some(debug_item);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{client::Client, Server, StateExt};
|
||||
use common::{
|
||||
comp::{
|
||||
self, item,
|
||||
self, item::{self, tool::AbilityMap},
|
||||
slot::{self, Slot},
|
||||
Pos,
|
||||
},
|
||||
@ -203,7 +203,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
if let Some(lantern) = lantern_opt {
|
||||
swap_lantern(&mut state.ecs().write_storage(), entity, &lantern);
|
||||
}
|
||||
slot::equip(slot, inventory, loadout);
|
||||
let map = state.ecs().fetch::<AbilityMap>();
|
||||
slot::equip(slot, inventory, loadout, &map);
|
||||
Some(comp::InventoryUpdateEvent::Used)
|
||||
} else {
|
||||
None
|
||||
@ -338,7 +339,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
if slot == slot::EquipSlot::Lantern {
|
||||
snuff_lantern(&mut state.ecs().write_storage(), entity);
|
||||
}
|
||||
slot::unequip(slot, inventory, loadout);
|
||||
let map = state.ecs().fetch::<AbilityMap>();
|
||||
slot::unequip(slot, inventory, loadout, &map);
|
||||
Some(comp::InventoryUpdateEvent::Used)
|
||||
} else {
|
||||
error!(?entity, "Entity doesn't have a loadout, can't unequip...");
|
||||
@ -364,12 +366,14 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
let mut loadouts = ecs.write_storage();
|
||||
let inventory = inventories.get_mut(entity);
|
||||
let loadout = loadouts.get_mut(entity);
|
||||
let map = state.ecs().fetch::<AbilityMap>();
|
||||
|
||||
slot::swap(a, b, inventory, loadout);
|
||||
slot::swap(a, b, inventory, loadout, &map);
|
||||
|
||||
// :/
|
||||
drop(loadouts);
|
||||
drop(inventories);
|
||||
drop(map);
|
||||
|
||||
state.write_component(
|
||||
entity,
|
||||
@ -378,6 +382,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
},
|
||||
|
||||
comp::InventoryManip::Drop(slot) => {
|
||||
let map = state.ecs().fetch::<AbilityMap>();
|
||||
let item = match slot {
|
||||
Slot::Inventory(slot) => state
|
||||
.ecs()
|
||||
@ -388,8 +393,9 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.get_mut(entity)
|
||||
.and_then(|ldt| slot::loadout_remove(slot, ldt)),
|
||||
.and_then(|ldt| slot::loadout_remove(slot, ldt, &map)),
|
||||
};
|
||||
drop(map);
|
||||
|
||||
// FIXME: We should really require the drop and write to be atomic!
|
||||
if let (Some(mut item), Some(pos)) =
|
||||
|
@ -46,7 +46,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
cmd::ChatCommand,
|
||||
comp::{self, ChatType},
|
||||
comp::{self, item::tool::AbilityMap, ChatType},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{
|
||||
ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg,
|
||||
@ -159,9 +159,9 @@ impl Server {
|
||||
state
|
||||
.ecs_mut()
|
||||
.insert(CharacterUpdater::new(&persistence_db_dir)?);
|
||||
state
|
||||
.ecs_mut()
|
||||
.insert(CharacterLoader::new(&persistence_db_dir)?);
|
||||
|
||||
let character_loader = CharacterLoader::new(&persistence_db_dir, &*state.ecs().fetch::<AbilityMap>());
|
||||
state.ecs_mut().insert(character_loader);
|
||||
state.ecs_mut().insert(Vec::<Outcome>::new());
|
||||
|
||||
// System timers for performance monitoring
|
||||
|
@ -25,6 +25,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
character::{CharacterId, CharacterItem, MAX_CHARACTERS_PER_PLAYER},
|
||||
comp::item::tool::AbilityMap,
|
||||
state::Time,
|
||||
};
|
||||
use core::ops::Range;
|
||||
@ -60,6 +61,7 @@ pub fn load_character_data(
|
||||
requesting_player_uuid: String,
|
||||
char_id: CharacterId,
|
||||
connection: VelorenTransaction,
|
||||
map: &AbilityMap,
|
||||
) -> CharacterDataResult {
|
||||
use schema::{body::dsl::*, character::dsl::*, item::dsl::*, stats::dsl::*};
|
||||
|
||||
@ -102,7 +104,7 @@ pub fn load_character_data(
|
||||
convert_body_from_database(&char_body)?,
|
||||
convert_stats_from_database(&stats_data, character_data.alias),
|
||||
convert_inventory_from_database_items(&inventory_items)?,
|
||||
convert_loadout_from_database_items(&loadout_items)?,
|
||||
convert_loadout_from_database_items(&loadout_items, map)?,
|
||||
waypoint,
|
||||
))
|
||||
}
|
||||
@ -117,6 +119,7 @@ pub fn load_character_data(
|
||||
pub fn load_character_list(
|
||||
player_uuid_: &str,
|
||||
connection: VelorenTransaction,
|
||||
map: &AbilityMap,
|
||||
) -> CharacterListResult {
|
||||
use schema::{body::dsl::*, character::dsl::*, item::dsl::*, stats::dsl::*};
|
||||
|
||||
@ -149,7 +152,7 @@ pub fn load_character_list(
|
||||
.filter(parent_container_item_id.eq(loadout_container_id))
|
||||
.load::<Item>(&*connection)?;
|
||||
|
||||
let loadout = convert_loadout_from_database_items(&loadout_items)?;
|
||||
let loadout = convert_loadout_from_database_items(&loadout_items, map)?;
|
||||
|
||||
Ok(CharacterItem {
|
||||
character: char,
|
||||
@ -166,6 +169,7 @@ pub fn create_character(
|
||||
character_alias: &str,
|
||||
persisted_components: PersistedComponents,
|
||||
connection: VelorenTransaction,
|
||||
map: &AbilityMap,
|
||||
) -> CharacterListResult {
|
||||
use schema::item::dsl::*;
|
||||
|
||||
@ -299,7 +303,7 @@ pub fn create_character(
|
||||
)));
|
||||
}
|
||||
|
||||
load_character_list(uuid, connection)
|
||||
load_character_list(uuid, connection, map)
|
||||
}
|
||||
|
||||
/// Delete a character. Returns the updated character list.
|
||||
@ -307,6 +311,7 @@ pub fn delete_character(
|
||||
requesting_player_uuid: &str,
|
||||
char_id: CharacterId,
|
||||
connection: VelorenTransaction,
|
||||
map: &AbilityMap,
|
||||
) -> CharacterListResult {
|
||||
use schema::{body::dsl::*, character::dsl::*, stats::dsl::*};
|
||||
|
||||
@ -387,7 +392,7 @@ pub fn delete_character(
|
||||
)));
|
||||
}
|
||||
|
||||
load_character_list(requesting_player_uuid, connection)
|
||||
load_character_list(requesting_player_uuid, connection, map)
|
||||
}
|
||||
|
||||
/// Before creating a character, we ensure that the limit on the number of
|
||||
|
@ -9,7 +9,7 @@ use crate::persistence::{
|
||||
};
|
||||
use common::{
|
||||
character::CharacterId,
|
||||
comp::{Body as CompBody, *},
|
||||
comp::{item::tool::AbilityMap, Body as CompBody, *},
|
||||
loadout_builder,
|
||||
};
|
||||
use core::{convert::TryFrom, num::NonZeroU64};
|
||||
@ -240,7 +240,7 @@ pub fn convert_inventory_from_database_items(database_items: &[Item]) -> Result<
|
||||
Ok(inventory)
|
||||
}
|
||||
|
||||
pub fn convert_loadout_from_database_items(database_items: &[Item]) -> Result<Loadout, Error> {
|
||||
pub fn convert_loadout_from_database_items(database_items: &[Item], map: &AbilityMap) -> Result<Loadout, Error> {
|
||||
let mut loadout = loadout_builder::LoadoutBuilder::new();
|
||||
for db_item in database_items.iter() {
|
||||
let item = common::comp::Item::new_from_asset(db_item.item_definition_id.as_str())?;
|
||||
@ -251,8 +251,8 @@ pub fn convert_loadout_from_database_items(database_items: &[Item]) -> Result<Lo
|
||||
)?));
|
||||
|
||||
match db_item.position.as_str() {
|
||||
"active_item" => loadout = loadout.active_item(Some(ItemConfig::from(item))),
|
||||
"second_item" => loadout = loadout.second_item(Some(ItemConfig::from(item))),
|
||||
"active_item" => loadout = loadout.active_item(Some(ItemConfig::from((item, map)))),
|
||||
"second_item" => loadout = loadout.second_item(Some(ItemConfig::from((item, map)))),
|
||||
"lantern" => loadout = loadout.lantern(Some(item)),
|
||||
"shoulder" => loadout = loadout.shoulder(Some(item)),
|
||||
"chest" => loadout = loadout.chest(Some(item)),
|
||||
|
@ -3,7 +3,10 @@ use crate::persistence::{
|
||||
error::Error,
|
||||
establish_connection, PersistedComponents,
|
||||
};
|
||||
use common::character::{CharacterId, CharacterItem};
|
||||
use common::{
|
||||
character::{CharacterId, CharacterItem},
|
||||
comp::item::tool::AbilityMap,
|
||||
};
|
||||
use crossbeam::{channel, channel::TryIter};
|
||||
use std::path::Path;
|
||||
use tracing::error;
|
||||
@ -65,12 +68,14 @@ pub struct CharacterLoader {
|
||||
}
|
||||
|
||||
impl CharacterLoader {
|
||||
pub fn new(db_dir: &Path) -> diesel::QueryResult<Self> {
|
||||
pub fn new(db_dir: &Path, map: &AbilityMap) -> diesel::QueryResult<Self> {
|
||||
let (update_tx, internal_rx) = channel::unbounded::<CharacterLoaderRequest>();
|
||||
let (internal_tx, update_rx) = channel::unbounded::<CharacterLoaderResponse>();
|
||||
|
||||
let mut conn = establish_connection(db_dir)?;
|
||||
|
||||
let map = map.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
for request in internal_rx {
|
||||
let (entity, kind) = request;
|
||||
@ -88,6 +93,7 @@ impl CharacterLoader {
|
||||
&character_alias,
|
||||
persisted_components,
|
||||
txn,
|
||||
&map,
|
||||
)
|
||||
})),
|
||||
CharacterLoaderRequestKind::DeleteCharacter {
|
||||
@ -95,12 +101,12 @@ impl CharacterLoader {
|
||||
character_id,
|
||||
} => {
|
||||
CharacterLoaderResponseType::CharacterList(conn.transaction(|txn| {
|
||||
delete_character(&player_uuid, character_id, txn)
|
||||
delete_character(&player_uuid, character_id, txn, &map)
|
||||
}))
|
||||
},
|
||||
CharacterLoaderRequestKind::LoadCharacterList { player_uuid } => {
|
||||
CharacterLoaderResponseType::CharacterList(
|
||||
conn.transaction(|txn| load_character_list(&player_uuid, txn)),
|
||||
conn.transaction(|txn| load_character_list(&player_uuid, txn, &map)),
|
||||
)
|
||||
},
|
||||
CharacterLoaderRequestKind::LoadCharacterData {
|
||||
@ -108,7 +114,7 @@ impl CharacterLoader {
|
||||
character_id,
|
||||
} => {
|
||||
CharacterLoaderResponseType::CharacterData(Box::new(conn.transaction(
|
||||
|txn| load_character_data(player_uuid, character_id, txn),
|
||||
|txn| load_character_data(player_uuid, character_id, txn, &map),
|
||||
)))
|
||||
},
|
||||
},
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
persistence::character_loader::CharacterLoader, presence::Presence, EditableSettings,
|
||||
};
|
||||
use common::{
|
||||
comp::{ChatType, Player, UnresolvedChatMsg},
|
||||
comp::{item::tool::AbilityMap, ChatType, Player, UnresolvedChatMsg},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{ClientGeneral, ServerGeneral},
|
||||
span,
|
||||
@ -28,6 +28,7 @@ impl Sys {
|
||||
editable_settings: &ReadExpect<'_, EditableSettings>,
|
||||
alias_validator: &ReadExpect<'_, AliasValidator>,
|
||||
msg: ClientGeneral,
|
||||
map: &AbilityMap,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
match msg {
|
||||
// Request spectator state
|
||||
@ -101,6 +102,7 @@ impl Sys {
|
||||
tool,
|
||||
body,
|
||||
character_loader,
|
||||
map,
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -134,6 +136,7 @@ impl<'a> System<'a> for Sys {
|
||||
ReadStorage<'a, Presence>,
|
||||
ReadExpect<'a, EditableSettings>,
|
||||
ReadExpect<'a, AliasValidator>,
|
||||
ReadExpect<'a, AbilityMap>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
@ -149,6 +152,7 @@ impl<'a> System<'a> for Sys {
|
||||
presences,
|
||||
editable_settings,
|
||||
alias_validator,
|
||||
map,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
span!(_guard, "run", "msg::character_screen::Sys::run");
|
||||
@ -171,6 +175,7 @@ impl<'a> System<'a> for Sys {
|
||||
&editable_settings,
|
||||
&alias_validator,
|
||||
msg,
|
||||
&map,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::SysTimer;
|
||||
use crate::{chunk_generator::ChunkGenerator, client::Client, presence::Presence, Tick};
|
||||
use common::{
|
||||
comp::{self, bird_medium, Alignment, Pos},
|
||||
comp::{self, bird_medium, item::tool::AbilityMap, Alignment, Pos},
|
||||
event::{EventBus, ServerEvent},
|
||||
generation::get_npc_name,
|
||||
msg::ServerGeneral,
|
||||
@ -12,7 +12,7 @@ use common::{
|
||||
LoadoutBuilder,
|
||||
};
|
||||
use rand::Rng;
|
||||
use specs::{Join, Read, ReadStorage, System, Write, WriteExpect};
|
||||
use specs::{Join, Read, ReadExpect, ReadStorage, System, Write, WriteExpect};
|
||||
use std::sync::Arc;
|
||||
use vek::*;
|
||||
|
||||
@ -35,6 +35,7 @@ impl<'a> System<'a> for Sys {
|
||||
ReadStorage<'a, Pos>,
|
||||
ReadStorage<'a, Presence>,
|
||||
ReadStorage<'a, Client>,
|
||||
ReadExpect<'a, AbilityMap>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
@ -49,6 +50,7 @@ impl<'a> System<'a> for Sys {
|
||||
positions,
|
||||
presences,
|
||||
clients,
|
||||
map,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
span!(_guard, "run", "terrain::Sys::run");
|
||||
@ -143,7 +145,7 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
|
||||
let loadout =
|
||||
LoadoutBuilder::build_loadout(body, alignment, main_tool, entity.is_giant)
|
||||
LoadoutBuilder::build_loadout(body, alignment, main_tool, entity.is_giant, &map)
|
||||
.build();
|
||||
|
||||
let health = comp::Health::new(stats.body_type, stats.level.level());
|
||||
|
@ -39,7 +39,7 @@ use crate::{
|
||||
settings::Settings,
|
||||
window::{Event, Window},
|
||||
};
|
||||
use common::{assets::watch, clock::Clock};
|
||||
use common::{assets::watch, clock::Clock, comp::item::tool::AbilityMap};
|
||||
|
||||
/// A type used to store state that is shared between all play states.
|
||||
pub struct GlobalState {
|
||||
@ -110,7 +110,7 @@ pub trait PlayState {
|
||||
fn enter(&mut self, global_state: &mut GlobalState, direction: Direction);
|
||||
|
||||
/// Tick the play state
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>) -> PlayStateResult;
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>, map: &AbilityMap) -> PlayStateResult;
|
||||
|
||||
/// Get a descriptive name for this state type.
|
||||
fn name(&self) -> &'static str;
|
||||
|
@ -192,5 +192,5 @@ fn main() {
|
||||
localization_watcher,
|
||||
};
|
||||
|
||||
run::run(global_state, event_loop);
|
||||
run::run(global_state, event_loop, map);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
Direction, GlobalState, PlayState, PlayStateResult,
|
||||
};
|
||||
use client::{self, Client};
|
||||
use common::{assets::Asset, comp, span, state::DeltaTime};
|
||||
use common::{assets::Asset, comp::{self, item::tool::AbilityMap}, span, state::DeltaTime};
|
||||
use specs::WorldExt;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use tracing::error;
|
||||
@ -62,7 +62,7 @@ impl PlayState for CharSelectionState {
|
||||
self.client.borrow_mut().load_character_list();
|
||||
}
|
||||
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<WinEvent>) -> PlayStateResult {
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<WinEvent>, map: &AbilityMap) -> PlayStateResult {
|
||||
span!(_guard, "tick", "<CharSelectionState as PlayState>::tick");
|
||||
let (client_presence, client_registered) = {
|
||||
let client = self.client.borrow();
|
||||
@ -88,7 +88,7 @@ impl PlayState for CharSelectionState {
|
||||
// Maintain the UI.
|
||||
let events = self
|
||||
.char_selection_ui
|
||||
.maintain(global_state, &mut self.client.borrow_mut());
|
||||
.maintain(global_state, &mut self.client.borrow_mut(), map);
|
||||
|
||||
for event in events {
|
||||
match event {
|
||||
|
@ -24,7 +24,7 @@ use client::Client;
|
||||
use common::{
|
||||
assets::Asset,
|
||||
character::{CharacterId, CharacterItem, MAX_CHARACTERS_PER_PLAYER},
|
||||
comp::{self, humanoid},
|
||||
comp::{self, humanoid, item::tool::AbilityMap},
|
||||
LoadoutBuilder,
|
||||
};
|
||||
//ImageFrame, Tooltip,
|
||||
@ -179,12 +179,12 @@ impl Mode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(name: String) -> Self {
|
||||
pub fn create(name: String, map: &AbilityMap) -> Self {
|
||||
let tool = STARTER_SWORD;
|
||||
|
||||
let loadout = LoadoutBuilder::new()
|
||||
.defaults()
|
||||
.active_item(Some(LoadoutBuilder::default_item_config_from_str(tool)))
|
||||
.active_item(Some(LoadoutBuilder::default_item_config_from_str(tool, map)))
|
||||
.build();
|
||||
|
||||
let loadout = Box::new(loadout);
|
||||
@ -1172,7 +1172,7 @@ impl Controls {
|
||||
.into()
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Message, events: &mut Vec<Event>, characters: &[CharacterItem]) {
|
||||
fn update(&mut self, message: Message, events: &mut Vec<Event>, characters: &[CharacterItem], map: &AbilityMap) {
|
||||
match message {
|
||||
Message::Back => {
|
||||
if matches!(&self.mode, Mode::Create { .. }) {
|
||||
@ -1206,7 +1206,7 @@ impl Controls {
|
||||
},
|
||||
Message::NewCharacter => {
|
||||
if matches!(&self.mode, Mode::Select { .. }) {
|
||||
self.mode = Mode::create(String::new());
|
||||
self.mode = Mode::create(String::new(), map);
|
||||
}
|
||||
},
|
||||
Message::CreateCharacter => {
|
||||
@ -1242,7 +1242,7 @@ impl Controls {
|
||||
Message::Tool(value) => {
|
||||
if let Mode::Create { tool, loadout, .. } = &mut self.mode {
|
||||
*tool = value;
|
||||
loadout.active_item = Some(LoadoutBuilder::default_item_config_from_str(*tool));
|
||||
loadout.active_item = Some(LoadoutBuilder::default_item_config_from_str(*tool, map));
|
||||
}
|
||||
},
|
||||
Message::RandomizeCharacter => {
|
||||
@ -1411,7 +1411,7 @@ impl CharSelectionUi {
|
||||
}
|
||||
|
||||
// TODO: do we need whole client here or just character list?
|
||||
pub fn maintain(&mut self, global_state: &mut GlobalState, client: &mut Client) -> Vec<Event> {
|
||||
pub fn maintain(&mut self, global_state: &mut GlobalState, client: &mut Client, map: &AbilityMap) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
|
||||
let (mut messages, _) = self.ui.maintain(
|
||||
@ -1426,7 +1426,7 @@ impl CharSelectionUi {
|
||||
|
||||
messages.into_iter().for_each(|message| {
|
||||
self.controls
|
||||
.update(message, &mut events, &client.character_list.characters)
|
||||
.update(message, &mut events, &client.character_list.characters, map)
|
||||
});
|
||||
|
||||
events
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
Direction, GlobalState, PlayState, PlayStateResult,
|
||||
};
|
||||
use client_init::{ClientInit, Error as InitError, Msg as InitMsg};
|
||||
use common::{assets::Asset, comp, span};
|
||||
use common::{assets::Asset, comp::{self, item::tool::AbilityMap}, span};
|
||||
use tracing::error;
|
||||
use ui::{Event as MainMenuEvent, MainMenuUi};
|
||||
|
||||
@ -48,7 +48,7 @@ impl PlayState for MainMenuState {
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>) -> PlayStateResult {
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>, map: &AbilityMap) -> PlayStateResult {
|
||||
span!(_guard, "tick", "<MainMenuState as PlayState>::tick");
|
||||
let mut localized_strings = crate::i18n::Localization::load_expect(
|
||||
&crate::i18n::i18n_asset_key(&global_state.settings.language.selected_language),
|
||||
@ -263,7 +263,7 @@ impl PlayState for MainMenuState {
|
||||
},
|
||||
#[cfg(feature = "singleplayer")]
|
||||
MainMenuEvent::StartSingleplayer => {
|
||||
let singleplayer = Singleplayer::new(None); // TODO: Make client and server use the same thread pool
|
||||
let singleplayer = Singleplayer::new(None, map); // TODO: Make client and server use the same thread pool
|
||||
|
||||
global_state.singleplayer = Some(singleplayer);
|
||||
},
|
||||
|
@ -4,11 +4,11 @@ use crate::{
|
||||
window::{Event, EventLoop},
|
||||
Direction, GlobalState, PlayState, PlayStateResult,
|
||||
};
|
||||
use common::{no_guard_span, span, util::GuardlessSpan};
|
||||
use common::{comp::item::tool::AbilityMap, no_guard_span, span, util::GuardlessSpan};
|
||||
use std::{mem, time::Duration};
|
||||
use tracing::debug;
|
||||
|
||||
pub fn run(mut global_state: GlobalState, event_loop: EventLoop) {
|
||||
pub fn run(mut global_state: GlobalState, event_loop: EventLoop, map: &AbilityMap) {
|
||||
// Set up the initial play state.
|
||||
let mut states: Vec<Box<dyn PlayState>> = vec![Box::new(MainMenuState::new(&mut global_state))];
|
||||
states.last_mut().map(|current_state| {
|
||||
@ -26,6 +26,8 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) {
|
||||
let mut poll_span = None;
|
||||
let mut event_span = None;
|
||||
|
||||
let map = map.clone();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
// Continuously run loop since we handle sleeping
|
||||
*control_flow = winit::event_loop::ControlFlow::Poll;
|
||||
@ -53,7 +55,7 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) {
|
||||
event_span.take();
|
||||
poll_span.take();
|
||||
if polled_twice {
|
||||
handle_main_events_cleared(&mut states, control_flow, &mut global_state);
|
||||
handle_main_events_cleared(&mut states, control_flow, &mut global_state, &map);
|
||||
}
|
||||
poll_span = Some(no_guard_span!("Poll Winit"));
|
||||
polled_twice = !polled_twice;
|
||||
@ -82,6 +84,7 @@ fn handle_main_events_cleared(
|
||||
states: &mut Vec<Box<dyn PlayState>>,
|
||||
control_flow: &mut winit::event_loop::ControlFlow,
|
||||
global_state: &mut GlobalState,
|
||||
map: &AbilityMap,
|
||||
) {
|
||||
span!(guard, "Handle MainEventsCleared");
|
||||
// Screenshot / Fullscreen toggle
|
||||
@ -102,7 +105,7 @@ fn handle_main_events_cleared(
|
||||
let mut exit = true;
|
||||
while let Some(state_result) = states.last_mut().map(|last| {
|
||||
let events = global_state.window.fetch_events();
|
||||
last.tick(global_state, events)
|
||||
last.tick(global_state, events, map)
|
||||
}) {
|
||||
// Implement state transfer logic.
|
||||
match state_result {
|
||||
|
@ -15,7 +15,7 @@ use client::{self, Client};
|
||||
use common::{
|
||||
assets::Asset,
|
||||
comp,
|
||||
comp::{ChatMsg, ChatType, InventoryUpdateEvent, Pos, Vel},
|
||||
comp::{item::tool::AbilityMap, ChatMsg, ChatType, InventoryUpdateEvent, Pos, Vel},
|
||||
consts::{MAX_MOUNT_RANGE, MAX_PICKUP_RANGE},
|
||||
event::EventBus,
|
||||
msg::PresenceKind,
|
||||
@ -203,7 +203,7 @@ impl PlayState for SessionState {
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>) -> PlayStateResult {
|
||||
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>, map: &AbilityMap) -> PlayStateResult {
|
||||
span!(_guard, "tick", "<Session as PlayState>::tick");
|
||||
// TODO: let mut client = self.client.borrow_mut();
|
||||
// NOTE: Not strictly necessary, but useful for hotloading translation changes.
|
||||
|
@ -1,5 +1,5 @@
|
||||
use client::Client;
|
||||
use common::clock::Clock;
|
||||
use common::{clock::Clock, comp::item::tool::AbilityMap};
|
||||
use crossbeam::channel::{bounded, unbounded, Receiver, Sender, TryRecvError};
|
||||
use server::{Error as ServerError, Event, Input, Server};
|
||||
use std::{
|
||||
@ -31,7 +31,7 @@ pub struct Singleplayer {
|
||||
}
|
||||
|
||||
impl Singleplayer {
|
||||
pub fn new(client: Option<&Client>) -> Self {
|
||||
pub fn new(client: Option<&Client>,map: &AbilityMap) -> Self {
|
||||
let (sender, receiver) = unbounded();
|
||||
|
||||
// Determine folder to save server data in
|
||||
|
Loading…
Reference in New Issue
Block a user