mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'isse/shared-waypoints' into 'master'
Shared and persistent waypoints See merge request veloren/veloren!3162
This commit is contained in:
commit
df7cd2da1a
@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Convert giant trees to site2
|
- Convert giant trees to site2
|
||||||
- Add new upgraded travelers
|
- Add new upgraded travelers
|
||||||
- Wallrunning
|
- Wallrunning
|
||||||
|
- Waypoints saved between sessions and shared with group members.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
BIN
assets/voxygen/element/ui/map/buttons/location_marker_group.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/map/buttons/location_marker_group.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -32,6 +32,7 @@
|
|||||||
"hud.map.toggle_minimap_voxel": "Toggle Minimap Voxel View",
|
"hud.map.toggle_minimap_voxel": "Toggle Minimap Voxel View",
|
||||||
"hud.map.zoom_minimap_explanation": "Zoom in the Minimap to see\nthe area around you in higher detail",
|
"hud.map.zoom_minimap_explanation": "Zoom in the Minimap to see\nthe area around you in higher detail",
|
||||||
"hud.map.gnarling": "Gnarling Fortification",
|
"hud.map.gnarling": "Gnarling Fortification",
|
||||||
|
"hud.map.placed_by": "Placed by {name}",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ use common::{
|
|||||||
slot::{EquipSlot, InvSlotId, Slot},
|
slot::{EquipSlot, InvSlotId, Slot},
|
||||||
CharacterState, ChatMode, ControlAction, ControlEvent, Controller, ControllerInputs,
|
CharacterState, ChatMode, ControlAction, ControlEvent, Controller, ControllerInputs,
|
||||||
GroupManip, InputKind, InventoryAction, InventoryEvent, InventoryUpdateEvent,
|
GroupManip, InputKind, InventoryAction, InventoryEvent, InventoryUpdateEvent,
|
||||||
UtteranceKind,
|
MapMarkerChange, UtteranceKind,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent},
|
event::{EventBus, LocalEvent},
|
||||||
grid::Grid,
|
grid::Grid,
|
||||||
@ -112,6 +112,7 @@ pub enum Event {
|
|||||||
CharacterCreated(CharacterId),
|
CharacterCreated(CharacterId),
|
||||||
CharacterEdited(CharacterId),
|
CharacterEdited(CharacterId),
|
||||||
CharacterError(String),
|
CharacterError(String),
|
||||||
|
MapMarker(comp::MapMarkerUpdate),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WorldData {
|
pub struct WorldData {
|
||||||
@ -759,7 +760,8 @@ impl Client {
|
|||||||
| ClientGeneral::UnlockSkillGroup(_)
|
| ClientGeneral::UnlockSkillGroup(_)
|
||||||
| ClientGeneral::RequestPlayerPhysics { .. }
|
| ClientGeneral::RequestPlayerPhysics { .. }
|
||||||
| ClientGeneral::RequestLossyTerrainCompression { .. }
|
| ClientGeneral::RequestLossyTerrainCompression { .. }
|
||||||
| ClientGeneral::AcknowledgePersistenceLoadError => {
|
| ClientGeneral::AcknowledgePersistenceLoadError
|
||||||
|
| ClientGeneral::UpdateMapMarker(_) => {
|
||||||
#[cfg(feature = "tracy")]
|
#[cfg(feature = "tracy")]
|
||||||
{
|
{
|
||||||
ingame = 1.0;
|
ingame = 1.0;
|
||||||
@ -1190,6 +1192,10 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn map_marker_event(&mut self, event: MapMarkerChange) {
|
||||||
|
self.send_msg(ClientGeneral::UpdateMapMarker(event));
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether a player can swap their weapon+ability `Loadout` settings
|
/// Checks whether a player can swap their weapon+ability `Loadout` settings
|
||||||
/// and sends the `ControlAction` event that signals to do the swap.
|
/// and sends the `ControlAction` event that signals to do the swap.
|
||||||
pub fn swap_loadout(&mut self) { self.control_action(ControlAction::SwapEquippedWeapons) }
|
pub fn swap_loadout(&mut self) { self.control_action(ControlAction::SwapEquippedWeapons) }
|
||||||
@ -1909,6 +1915,9 @@ impl Client {
|
|||||||
self.personalize_alias(uid, player_info.player_alias.clone())
|
self.personalize_alias(uid, player_info.player_alias.clone())
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
|
frontend_events.push(Event::MapMarker(
|
||||||
|
comp::MapMarkerUpdate::GroupMember(uid, MapMarkerChange::Remove),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if self.group_members.remove(&uid).is_none() {
|
if self.group_members.remove(&uid).is_none() {
|
||||||
warn!(
|
warn!(
|
||||||
@ -1931,10 +1940,12 @@ impl Client {
|
|||||||
if let Some(uid) = self.uid() {
|
if let Some(uid) = self.uid() {
|
||||||
self.group_members.remove(&uid);
|
self.group_members.remove(&uid);
|
||||||
}
|
}
|
||||||
|
frontend_events.push(Event::MapMarker(comp::MapMarkerUpdate::ClearGroup));
|
||||||
},
|
},
|
||||||
NoGroup => {
|
NoGroup => {
|
||||||
self.group_leader = None;
|
self.group_leader = None;
|
||||||
self.group_members = HashMap::new();
|
self.group_members = HashMap::new();
|
||||||
|
frontend_events.push(Event::MapMarker(comp::MapMarkerUpdate::ClearGroup));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2032,6 +2043,9 @@ impl Client {
|
|||||||
rich.economy = Some(economy);
|
rich.economy = Some(economy);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ServerGeneral::MapMarker(event) => {
|
||||||
|
frontend_events.push(Event::MapMarker(event));
|
||||||
|
},
|
||||||
_ => unreachable!("Not a in_game message"),
|
_ => unreachable!("Not a in_game message"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -78,6 +78,7 @@ pub enum ClientGeneral {
|
|||||||
UnlockSkill(Skill),
|
UnlockSkill(Skill),
|
||||||
UnlockSkillGroup(SkillGroupKind),
|
UnlockSkillGroup(SkillGroupKind),
|
||||||
RequestSiteInfo(SiteId),
|
RequestSiteInfo(SiteId),
|
||||||
|
UpdateMapMarker(comp::MapMarkerChange),
|
||||||
//Only in Game, via terrain stream
|
//Only in Game, via terrain stream
|
||||||
TerrainChunkRequest {
|
TerrainChunkRequest {
|
||||||
key: Vec2<i32>,
|
key: Vec2<i32>,
|
||||||
@ -132,7 +133,8 @@ impl ClientMsg {
|
|||||||
| ClientGeneral::UnlockSkillGroup(_)
|
| ClientGeneral::UnlockSkillGroup(_)
|
||||||
| ClientGeneral::RequestPlayerPhysics { .. }
|
| ClientGeneral::RequestPlayerPhysics { .. }
|
||||||
| ClientGeneral::RequestLossyTerrainCompression { .. }
|
| ClientGeneral::RequestLossyTerrainCompression { .. }
|
||||||
| ClientGeneral::AcknowledgePersistenceLoadError => {
|
| ClientGeneral::AcknowledgePersistenceLoadError
|
||||||
|
| ClientGeneral::UpdateMapMarker(_) => {
|
||||||
c_type == ClientType::Game && presence.is_some()
|
c_type == ClientType::Game && presence.is_some()
|
||||||
},
|
},
|
||||||
//Always possible
|
//Always possible
|
||||||
|
@ -189,6 +189,7 @@ pub enum ServerGeneral {
|
|||||||
FinishedTrade(TradeResult),
|
FinishedTrade(TradeResult),
|
||||||
/// Economic information about sites
|
/// Economic information about sites
|
||||||
SiteEconomy(EconomyInfo),
|
SiteEconomy(EconomyInfo),
|
||||||
|
MapMarker(comp::MapMarkerUpdate),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerGeneral {
|
impl ServerGeneral {
|
||||||
@ -298,7 +299,8 @@ impl ServerMsg {
|
|||||||
| ServerGeneral::Knockback(_)
|
| ServerGeneral::Knockback(_)
|
||||||
| ServerGeneral::UpdatePendingTrade(_, _, _)
|
| ServerGeneral::UpdatePendingTrade(_, _, _)
|
||||||
| ServerGeneral::FinishedTrade(_)
|
| ServerGeneral::FinishedTrade(_)
|
||||||
| ServerGeneral::SiteEconomy(_) => {
|
| ServerGeneral::SiteEconomy(_)
|
||||||
|
| ServerGeneral::MapMarker(_) => {
|
||||||
c_type == ClientType::Game && presence.is_some()
|
c_type == ClientType::Game && presence.is_some()
|
||||||
},
|
},
|
||||||
// Always possible
|
// Always possible
|
||||||
|
@ -62,9 +62,9 @@ pub enum ChangeNotification<E> {
|
|||||||
// Also note when the same notification is sent to multiple destinations the
|
// Also note when the same notification is sent to multiple destinations the
|
||||||
// mapping might be duplicated effort
|
// mapping might be duplicated effort
|
||||||
impl<E> ChangeNotification<E> {
|
impl<E> ChangeNotification<E> {
|
||||||
pub fn try_map<T>(self, f: impl Fn(E) -> Option<T>) -> Option<ChangeNotification<T>> {
|
pub fn try_map_ref<T>(&self, f: impl Fn(&E) -> Option<T>) -> Option<ChangeNotification<T>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Added(e, r) => f(e).map(|t| ChangeNotification::Added(t, r)),
|
Self::Added(e, r) => f(e).map(|t| ChangeNotification::Added(t, *r)),
|
||||||
Self::Removed(e) => f(e).map(ChangeNotification::Removed),
|
Self::Removed(e) => f(e).map(ChangeNotification::Removed),
|
||||||
Self::NewLeader(e) => f(e).map(ChangeNotification::NewLeader),
|
Self::NewLeader(e) => f(e).map(ChangeNotification::NewLeader),
|
||||||
// Note just discards members that fail map
|
// Note just discards members that fail map
|
||||||
@ -72,8 +72,8 @@ impl<E> ChangeNotification<E> {
|
|||||||
f(leader).map(|leader| ChangeNotification::NewGroup {
|
f(leader).map(|leader| ChangeNotification::NewGroup {
|
||||||
leader,
|
leader,
|
||||||
members: members
|
members: members
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter_map(|(e, r)| f(e).map(|t| (t, r)))
|
.filter_map(|(e, r)| f(e).map(|t| (t, *r)))
|
||||||
.collect(),
|
.collect(),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::resources::Time;
|
use crate::{resources::Time, uid::Uid};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::Component;
|
use specs::Component;
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
@ -45,3 +45,25 @@ impl Component for WaypointArea {
|
|||||||
impl Default for WaypointArea {
|
impl Default for WaypointArea {
|
||||||
fn default() -> Self { Self(5.0) }
|
fn default() -> Self { Self(5.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Marker on the map, used for sharing waypoint with group and
|
||||||
|
/// persisting it server side.
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct MapMarker(pub Vec2<i32>);
|
||||||
|
|
||||||
|
impl Component for MapMarker {
|
||||||
|
type Storage = IdvStorage<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum MapMarkerChange {
|
||||||
|
Update(Vec2<i32>),
|
||||||
|
Remove,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum MapMarkerUpdate {
|
||||||
|
Owned(MapMarkerChange),
|
||||||
|
GroupMember(Uid, MapMarkerChange),
|
||||||
|
ClearGroup,
|
||||||
|
}
|
||||||
|
@ -90,7 +90,7 @@ pub use self::{
|
|||||||
slot, Inventory, InventoryUpdate, InventoryUpdateEvent,
|
slot, Inventory, InventoryUpdate, InventoryUpdateEvent,
|
||||||
},
|
},
|
||||||
last::Last,
|
last::Last,
|
||||||
location::{Waypoint, WaypointArea},
|
location::{MapMarker, MapMarkerChange, MapMarkerUpdate, Waypoint, WaypointArea},
|
||||||
melee::{Melee, MeleeConstructor},
|
melee::{Melee, MeleeConstructor},
|
||||||
misc::Object,
|
misc::Object,
|
||||||
ori::Ori,
|
ori::Ori,
|
||||||
|
@ -115,6 +115,7 @@ pub enum ServerEvent {
|
|||||||
Option<comp::Waypoint>,
|
Option<comp::Waypoint>,
|
||||||
Vec<(comp::Pet, comp::Body, comp::Stats)>,
|
Vec<(comp::Pet, comp::Body, comp::Stats)>,
|
||||||
comp::ActiveAbilities,
|
comp::ActiveAbilities,
|
||||||
|
Option<comp::MapMarker>,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
ExitIngame {
|
ExitIngame {
|
||||||
@ -209,6 +210,10 @@ pub enum ServerEvent {
|
|||||||
auxiliary_key: comp::ability::AuxiliaryKey,
|
auxiliary_key: comp::ability::AuxiliaryKey,
|
||||||
new_ability: comp::ability::AuxiliaryAbility,
|
new_ability: comp::ability::AuxiliaryAbility,
|
||||||
},
|
},
|
||||||
|
UpdateMapMarker {
|
||||||
|
entity: EcsEntity,
|
||||||
|
update: comp::MapMarkerChange,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventBus<E> {
|
pub struct EventBus<E> {
|
||||||
|
@ -191,6 +191,7 @@ impl State {
|
|||||||
ecs.register::<comp::InventoryUpdate>();
|
ecs.register::<comp::InventoryUpdate>();
|
||||||
ecs.register::<comp::Admin>();
|
ecs.register::<comp::Admin>();
|
||||||
ecs.register::<comp::Waypoint>();
|
ecs.register::<comp::Waypoint>();
|
||||||
|
ecs.register::<comp::MapMarker>();
|
||||||
ecs.register::<comp::Projectile>();
|
ecs.register::<comp::Projectile>();
|
||||||
ecs.register::<comp::Melee>();
|
ecs.register::<comp::Melee>();
|
||||||
ecs.register::<comp::ItemDrop>();
|
ecs.register::<comp::ItemDrop>();
|
||||||
|
@ -64,6 +64,7 @@ pub fn create_character(
|
|||||||
.expect("Inventory has at least 1 slot left!");
|
.expect("Inventory has at least 1 slot left!");
|
||||||
|
|
||||||
let waypoint = None;
|
let waypoint = None;
|
||||||
|
let map_marker = None;
|
||||||
|
|
||||||
character_updater.create_character(entity, player_uuid, character_alias, PersistedComponents {
|
character_updater.create_character(entity, player_uuid, character_alias, PersistedComponents {
|
||||||
body,
|
body,
|
||||||
@ -73,6 +74,7 @@ pub fn create_character(
|
|||||||
waypoint,
|
waypoint,
|
||||||
pets: Vec::new(),
|
pets: Vec::new(),
|
||||||
active_abilities: Default::default(),
|
active_abilities: Default::default(),
|
||||||
|
map_marker,
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,8 @@ impl Client {
|
|||||||
| ServerGeneral::Knockback(_)
|
| ServerGeneral::Knockback(_)
|
||||||
| ServerGeneral::SiteEconomy(_)
|
| ServerGeneral::SiteEconomy(_)
|
||||||
| ServerGeneral::UpdatePendingTrade(_, _, _)
|
| ServerGeneral::UpdatePendingTrade(_, _, _)
|
||||||
| ServerGeneral::FinishedTrade(_) => {
|
| ServerGeneral::FinishedTrade(_)
|
||||||
|
| ServerGeneral::MapMarker(_) => {
|
||||||
PreparedMsg::new(2, &g, &self.in_game_stream_params)
|
PreparedMsg::new(2, &g, &self.in_game_stream_params)
|
||||||
},
|
},
|
||||||
//Ingame related, terrain
|
//Ingame related, terrain
|
||||||
|
@ -22,6 +22,8 @@ use specs::{Builder, Entity as EcsEntity, WorldExt};
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vek::{Rgb, Vec3};
|
use vek::{Rgb, Vec3};
|
||||||
|
|
||||||
|
use super::group_manip::update_map_markers;
|
||||||
|
|
||||||
pub fn handle_initialize_character(
|
pub fn handle_initialize_character(
|
||||||
server: &mut Server,
|
server: &mut Server,
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
@ -35,6 +37,14 @@ pub fn handle_loaded_character_data(
|
|||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
loaded_components: PersistedComponents,
|
loaded_components: PersistedComponents,
|
||||||
) {
|
) {
|
||||||
|
if let Some(marker) = loaded_components.map_marker {
|
||||||
|
server.notify_client(
|
||||||
|
entity,
|
||||||
|
ServerGeneral::MapMarker(comp::MapMarkerUpdate::Owned(comp::MapMarkerChange::Update(
|
||||||
|
marker.0,
|
||||||
|
))),
|
||||||
|
);
|
||||||
|
}
|
||||||
server
|
server
|
||||||
.state
|
.state
|
||||||
.update_character_data(entity, loaded_components);
|
.update_character_data(entity, loaded_components);
|
||||||
@ -103,6 +113,7 @@ pub fn handle_create_npc(
|
|||||||
let uids = state.ecs().read_storage::<Uid>();
|
let uids = state.ecs().read_storage::<Uid>();
|
||||||
let mut group_manager = state.ecs().write_resource::<comp::group::GroupManager>();
|
let mut group_manager = state.ecs().write_resource::<comp::group::GroupManager>();
|
||||||
if let Some(owner) = state.ecs().entity_from_uid(owner_uid.into()) {
|
if let Some(owner) = state.ecs().entity_from_uid(owner_uid.into()) {
|
||||||
|
let map_markers = state.ecs().read_storage::<comp::MapMarker>();
|
||||||
group_manager.new_pet(
|
group_manager.new_pet(
|
||||||
new_entity,
|
new_entity,
|
||||||
owner,
|
owner,
|
||||||
@ -115,10 +126,13 @@ pub fn handle_create_npc(
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
group_change
|
group_change
|
||||||
.try_map(|e| uids.get(e).copied())
|
.try_map_ref(|e| uids.get(*e).copied())
|
||||||
.map(|g| (g, c))
|
.map(|g| (g, c))
|
||||||
})
|
})
|
||||||
.map(|(g, c)| {
|
.map(|(g, c)| {
|
||||||
|
// Might be unneccessary, but maybe pets can somehow have map
|
||||||
|
// markers in the future
|
||||||
|
update_map_markers(&map_markers, &uids, c, &group_change);
|
||||||
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1267,3 +1267,41 @@ pub fn handle_change_ability(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_update_map_marker(
|
||||||
|
server: &mut Server,
|
||||||
|
entity: EcsEntity,
|
||||||
|
update: comp::MapMarkerChange,
|
||||||
|
) {
|
||||||
|
use comp::{MapMarker, MapMarkerChange::*};
|
||||||
|
match update {
|
||||||
|
Update(waypoint) => {
|
||||||
|
server
|
||||||
|
.state
|
||||||
|
.write_component_ignore_entity_dead(entity, MapMarker(waypoint));
|
||||||
|
},
|
||||||
|
Remove => {
|
||||||
|
server.state.delete_component::<MapMarker>(entity);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
let ecs = server.state.ecs_mut();
|
||||||
|
// Send updated waypoint to group members
|
||||||
|
let groups = ecs.read_storage();
|
||||||
|
let uids = ecs.read_storage();
|
||||||
|
if let Some((group_id, uid)) = groups.get(entity).zip(uids.get(entity)) {
|
||||||
|
let clients = ecs.read_storage::<Client>();
|
||||||
|
for client in comp::group::members(
|
||||||
|
*group_id,
|
||||||
|
&groups,
|
||||||
|
&ecs.entities(),
|
||||||
|
&ecs.read_storage(),
|
||||||
|
&uids,
|
||||||
|
)
|
||||||
|
.filter_map(|(e, _)| if e != entity { clients.get(e) } else { None })
|
||||||
|
{
|
||||||
|
client.send_fallible(ServerGeneral::MapMarker(
|
||||||
|
comp::MapMarkerUpdate::GroupMember(*uid, update),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::{client::Client, Server};
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
self,
|
self,
|
||||||
group::{self, Group, GroupManager},
|
group::{self, ChangeNotification, Group, GroupManager},
|
||||||
invite::{InviteKind, PendingInvites},
|
invite::{InviteKind, PendingInvites},
|
||||||
ChatType, GroupManip,
|
ChatType, GroupManip,
|
||||||
},
|
},
|
||||||
@ -81,6 +81,37 @@ pub fn can_invite(
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_map_markers<'a>(
|
||||||
|
map_markers: &ReadStorage<'a, comp::MapMarker>,
|
||||||
|
uids: &ReadStorage<'a, Uid>,
|
||||||
|
client: &Client,
|
||||||
|
change: &ChangeNotification<Entity>,
|
||||||
|
) {
|
||||||
|
use comp::group::ChangeNotification::*;
|
||||||
|
let send_update = |entity| {
|
||||||
|
if let (Some(map_marker), Some(uid)) = (map_markers.get(entity), uids.get(entity)) {
|
||||||
|
client.send_fallible(ServerGeneral::MapMarker(
|
||||||
|
comp::MapMarkerUpdate::GroupMember(
|
||||||
|
*uid,
|
||||||
|
comp::MapMarkerChange::Update(map_marker.0),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match change {
|
||||||
|
&Added(entity, _) => {
|
||||||
|
send_update(entity);
|
||||||
|
},
|
||||||
|
NewGroup { leader: _, members } => {
|
||||||
|
for (entity, _) in members {
|
||||||
|
send_update(*entity);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Removed and NoGroup can be inferred by the client, NewLeader does not affect map markers
|
||||||
|
Removed(_) | NoGroup | NewLeader(_) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: turn chat messages into enums
|
// TODO: turn chat messages into enums
|
||||||
pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupManip) {
|
pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupManip) {
|
||||||
match manip {
|
match manip {
|
||||||
@ -89,6 +120,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
|||||||
let clients = state.ecs().read_storage::<Client>();
|
let clients = state.ecs().read_storage::<Client>();
|
||||||
let uids = state.ecs().read_storage::<Uid>();
|
let uids = state.ecs().read_storage::<Uid>();
|
||||||
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
||||||
|
let map_markers = state.ecs().read_storage::<comp::MapMarker>();
|
||||||
group_manager.leave_group(
|
group_manager.leave_group(
|
||||||
entity,
|
entity,
|
||||||
&mut state.ecs().write_storage(),
|
&mut state.ecs().write_storage(),
|
||||||
@ -100,10 +132,13 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
group_change
|
group_change
|
||||||
.try_map(|e| uids.get(e).copied())
|
.try_map_ref(|e| uids.get(*e).copied())
|
||||||
.map(|g| (g, c))
|
.map(|g| (g, c))
|
||||||
})
|
})
|
||||||
.map(|(g, c)| c.send(ServerGeneral::GroupUpdate(g)));
|
.map(|(g, c)| {
|
||||||
|
update_map_markers(&map_markers, &uids, c, &group_change);
|
||||||
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -151,6 +186,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
|||||||
|
|
||||||
let mut groups = state.ecs().write_storage::<group::Group>();
|
let mut groups = state.ecs().write_storage::<group::Group>();
|
||||||
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
||||||
|
let map_markers = state.ecs().read_storage::<comp::MapMarker>();
|
||||||
// Make sure kicker is the group leader
|
// Make sure kicker is the group leader
|
||||||
match groups
|
match groups
|
||||||
.get(target)
|
.get(target)
|
||||||
@ -169,10 +205,13 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
group_change
|
group_change
|
||||||
.try_map(|e| uids.get(e).copied())
|
.try_map_ref(|e| uids.get(*e).copied())
|
||||||
.map(|g| (g, c))
|
.map(|g| (g, c))
|
||||||
})
|
})
|
||||||
.map(|(g, c)| c.send(ServerGeneral::GroupUpdate(g)));
|
.map(|(g, c)| {
|
||||||
|
update_map_markers(&map_markers, &uids, c, &group_change);
|
||||||
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -230,6 +269,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
|||||||
};
|
};
|
||||||
let groups = state.ecs().read_storage::<group::Group>();
|
let groups = state.ecs().read_storage::<group::Group>();
|
||||||
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
||||||
|
let map_markers = state.ecs().read_storage::<comp::MapMarker>();
|
||||||
// Make sure assigner is the group leader
|
// Make sure assigner is the group leader
|
||||||
match groups
|
match groups
|
||||||
.get(target)
|
.get(target)
|
||||||
@ -248,10 +288,13 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
group_change
|
group_change
|
||||||
.try_map(|e| uids.get(e).copied())
|
.try_map_ref(|e| uids.get(*e).copied())
|
||||||
.map(|g| (g, c))
|
.map(|g| (g, c))
|
||||||
})
|
})
|
||||||
.map(|(g, c)| c.send(ServerGeneral::GroupUpdate(g)));
|
.map(|(g, c)| {
|
||||||
|
update_map_markers(&map_markers, &uids, c, &group_change);
|
||||||
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Tell them they are the leader
|
// Tell them they are the leader
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use super::group_manip;
|
use super::group_manip::{self, update_map_markers};
|
||||||
use crate::{client::Client, Server};
|
use crate::{client::Client, Server};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
@ -202,6 +202,7 @@ pub fn handle_invite_accept(server: &mut Server, entity: specs::Entity) {
|
|||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
InviteKind::Group => {
|
InviteKind::Group => {
|
||||||
|
let map_markers = state.ecs().read_storage::<comp::MapMarker>();
|
||||||
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
let mut group_manager = state.ecs().write_resource::<GroupManager>();
|
||||||
group_manager.add_group_member(
|
group_manager.add_group_member(
|
||||||
inviter,
|
inviter,
|
||||||
@ -215,10 +216,13 @@ pub fn handle_invite_accept(server: &mut Server, entity: specs::Entity) {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
group_change
|
group_change
|
||||||
.try_map(|e| uids.get(e).copied())
|
.try_map_ref(|e| uids.get(*e).copied())
|
||||||
.map(|g| (g, c))
|
.map(|g| (g, c))
|
||||||
})
|
})
|
||||||
.map(|(g, c)| c.send(ServerGeneral::GroupUpdate(g)));
|
.map(|(g, c)| {
|
||||||
|
update_map_markers(&map_markers, &uids, c, &group_change);
|
||||||
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -12,7 +12,7 @@ use entity_manipulation::{
|
|||||||
handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_combo_change,
|
handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_combo_change,
|
||||||
handle_delete, handle_destroy, handle_energy_change, handle_entity_attacked_hook,
|
handle_delete, handle_destroy, handle_energy_change, handle_entity_attacked_hook,
|
||||||
handle_explosion, handle_health_change, handle_knockback, handle_land_on_ground, handle_parry,
|
handle_explosion, handle_health_change, handle_knockback, handle_land_on_ground, handle_parry,
|
||||||
handle_poise, handle_respawn, handle_teleport_to,
|
handle_poise, handle_respawn, handle_teleport_to, handle_update_map_marker,
|
||||||
};
|
};
|
||||||
use group_manip::handle_group;
|
use group_manip::handle_group;
|
||||||
use information::handle_site_info;
|
use information::handle_site_info;
|
||||||
@ -26,6 +26,8 @@ use player::{handle_client_disconnect, handle_exit_ingame};
|
|||||||
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
||||||
use trade::{cancel_trade_for, handle_process_trade_action};
|
use trade::{cancel_trade_for, handle_process_trade_action};
|
||||||
|
|
||||||
|
pub use group_manip::update_map_markers;
|
||||||
|
|
||||||
mod entity_creation;
|
mod entity_creation;
|
||||||
mod entity_manipulation;
|
mod entity_manipulation;
|
||||||
mod group_manip;
|
mod group_manip;
|
||||||
@ -132,8 +134,16 @@ impl Server {
|
|||||||
character_id,
|
character_id,
|
||||||
} => handle_initialize_character(self, entity, character_id),
|
} => handle_initialize_character(self, entity, character_id),
|
||||||
ServerEvent::UpdateCharacterData { entity, components } => {
|
ServerEvent::UpdateCharacterData { entity, components } => {
|
||||||
let (body, stats, skill_set, inventory, waypoint, pets, active_abilities) =
|
let (
|
||||||
components;
|
body,
|
||||||
|
stats,
|
||||||
|
skill_set,
|
||||||
|
inventory,
|
||||||
|
waypoint,
|
||||||
|
pets,
|
||||||
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
|
) = components;
|
||||||
let components = PersistedComponents {
|
let components = PersistedComponents {
|
||||||
body,
|
body,
|
||||||
stats,
|
stats,
|
||||||
@ -142,6 +152,7 @@ impl Server {
|
|||||||
waypoint,
|
waypoint,
|
||||||
pets,
|
pets,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
};
|
};
|
||||||
handle_loaded_character_data(self, entity, components);
|
handle_loaded_character_data(self, entity, components);
|
||||||
},
|
},
|
||||||
@ -253,6 +264,9 @@ impl Server {
|
|||||||
auxiliary_key,
|
auxiliary_key,
|
||||||
new_ability,
|
new_ability,
|
||||||
} => handle_change_ability(self, entity, slot, auxiliary_key, new_ability),
|
} => handle_change_ability(self, entity, slot, auxiliary_key, new_ability),
|
||||||
|
ServerEvent::UpdateMapMarker { entity, update } => {
|
||||||
|
handle_update_map_marker(self, entity, update)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,6 +226,11 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
|
|||||||
.read_storage::<common::comp::Waypoint>()
|
.read_storage::<common::comp::Waypoint>()
|
||||||
.get(entity)
|
.get(entity)
|
||||||
.cloned();
|
.cloned();
|
||||||
|
let map_marker = state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<common::comp::MapMarker>()
|
||||||
|
.get(entity)
|
||||||
|
.cloned();
|
||||||
// Store last battle mode change
|
// Store last battle mode change
|
||||||
if let Some(change) = player_info.last_battlemode_change {
|
if let Some(change) = player_info.last_battlemode_change {
|
||||||
let mode = player_info.battle_mode;
|
let mode = player_info.battle_mode;
|
||||||
@ -261,6 +266,7 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
|
|||||||
pets,
|
pets,
|
||||||
waypoint,
|
waypoint,
|
||||||
active_abilities.clone(),
|
active_abilities.clone(),
|
||||||
|
map_marker,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -887,6 +887,7 @@ impl Server {
|
|||||||
waypoint,
|
waypoint,
|
||||||
pets,
|
pets,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
} = character_data;
|
} = character_data;
|
||||||
let character_data = (
|
let character_data = (
|
||||||
body,
|
body,
|
||||||
@ -896,6 +897,7 @@ impl Server {
|
|||||||
waypoint,
|
waypoint,
|
||||||
pets,
|
pets,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
);
|
);
|
||||||
ServerEvent::UpdateCharacterData {
|
ServerEvent::UpdateCharacterData {
|
||||||
entity: query_result.entity,
|
entity: query_result.entity,
|
||||||
|
@ -148,19 +148,22 @@ pub fn load_character_data(
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let char_waypoint = character_data.waypoint.as_ref().and_then(|x| {
|
let (char_waypoint, char_map_marker) = match character_data
|
||||||
match convert_waypoint_from_database_json(x) {
|
.waypoint
|
||||||
Ok(w) => Some(w),
|
.as_ref()
|
||||||
Err(e) => {
|
.map(|x| convert_waypoint_from_database_json(x))
|
||||||
warn!(
|
{
|
||||||
"Error reading waypoint from database for character ID
|
Some(Ok(w)) => w,
|
||||||
|
Some(Err(e)) => {
|
||||||
|
warn!(
|
||||||
|
"Error reading waypoint from database for character ID
|
||||||
{}, error: {}",
|
{}, error: {}",
|
||||||
char_id, e
|
char_id, e
|
||||||
);
|
);
|
||||||
None
|
(None, None)
|
||||||
},
|
},
|
||||||
}
|
None => (None, None),
|
||||||
});
|
};
|
||||||
|
|
||||||
let mut stmt = connection.prepare_cached(
|
let mut stmt = connection.prepare_cached(
|
||||||
"
|
"
|
||||||
@ -261,6 +264,7 @@ pub fn load_character_data(
|
|||||||
waypoint: char_waypoint,
|
waypoint: char_waypoint,
|
||||||
pets,
|
pets,
|
||||||
active_abilities: convert_active_abilities_from_database(&ability_set_data),
|
active_abilities: convert_active_abilities_from_database(&ability_set_data),
|
||||||
|
map_marker: char_map_marker,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,6 +358,7 @@ pub fn create_character(
|
|||||||
waypoint,
|
waypoint,
|
||||||
pets: _,
|
pets: _,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
} = persisted_components;
|
} = persisted_components;
|
||||||
|
|
||||||
// Fetch new entity IDs for character, inventory and loadout
|
// Fetch new entity IDs for character, inventory and loadout
|
||||||
@ -438,7 +443,7 @@ pub fn create_character(
|
|||||||
&character_id as &dyn ToSql,
|
&character_id as &dyn ToSql,
|
||||||
&uuid,
|
&uuid,
|
||||||
&character_alias,
|
&character_alias,
|
||||||
&convert_waypoint_to_database_json(waypoint),
|
&convert_waypoint_to_database_json(waypoint, map_marker),
|
||||||
])?;
|
])?;
|
||||||
drop(stmt);
|
drop(stmt);
|
||||||
|
|
||||||
@ -935,6 +940,8 @@ fn delete_pets(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn update(
|
pub fn update(
|
||||||
char_id: CharacterId,
|
char_id: CharacterId,
|
||||||
char_skill_set: comp::SkillSet,
|
char_skill_set: comp::SkillSet,
|
||||||
@ -942,6 +949,7 @@ pub fn update(
|
|||||||
pets: Vec<PetPersistenceData>,
|
pets: Vec<PetPersistenceData>,
|
||||||
char_waypoint: Option<comp::Waypoint>,
|
char_waypoint: Option<comp::Waypoint>,
|
||||||
active_abilities: comp::ability::ActiveAbilities,
|
active_abilities: comp::ability::ActiveAbilities,
|
||||||
|
map_marker: Option<comp::MapMarker>,
|
||||||
transaction: &mut Transaction,
|
transaction: &mut Transaction,
|
||||||
) -> Result<(), PersistenceError> {
|
) -> Result<(), PersistenceError> {
|
||||||
// Run pet persistence
|
// Run pet persistence
|
||||||
@ -1066,7 +1074,7 @@ pub fn update(
|
|||||||
])?;
|
])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let db_waypoint = convert_waypoint_to_database_json(char_waypoint);
|
let db_waypoint = convert_waypoint_to_database_json(char_waypoint, map_marker);
|
||||||
|
|
||||||
let mut stmt = transaction.prepare_cached(
|
let mut stmt = transaction.prepare_cached(
|
||||||
"
|
"
|
||||||
@ -1103,7 +1111,7 @@ pub fn update(
|
|||||||
if ability_sets_count != 1 {
|
if ability_sets_count != 1 {
|
||||||
return Err(PersistenceError::OtherError(format!(
|
return Err(PersistenceError::OtherError(format!(
|
||||||
"Error updating ability_set table for char_id {}",
|
"Error updating ability_set table for char_id {}",
|
||||||
char_id
|
char_id,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,28 +217,30 @@ pub fn convert_body_to_database_json(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_waypoint_to_database_json(waypoint: Option<Waypoint>) -> Option<String> {
|
pub fn convert_waypoint_to_database_json(
|
||||||
match waypoint {
|
waypoint: Option<Waypoint>,
|
||||||
Some(w) => {
|
map_marker: Option<MapMarker>,
|
||||||
let charpos = CharacterPosition {
|
) -> Option<String> {
|
||||||
waypoint: w.get_pos(),
|
if waypoint.is_some() || map_marker.is_some() {
|
||||||
};
|
let charpos = CharacterPosition {
|
||||||
Some(
|
waypoint: waypoint.map(|w| w.get_pos()),
|
||||||
serde_json::to_string(&charpos)
|
map_marker: map_marker.map(|m| m.0),
|
||||||
.map_err(|err| {
|
};
|
||||||
PersistenceError::ConversionError(format!(
|
Some(
|
||||||
"Error encoding waypoint: {:?}",
|
serde_json::to_string(&charpos)
|
||||||
err
|
.map_err(|err| {
|
||||||
))
|
PersistenceError::ConversionError(format!("Error encoding waypoint: {:?}", err))
|
||||||
})
|
})
|
||||||
.ok()?,
|
.ok()?,
|
||||||
)
|
)
|
||||||
},
|
} else {
|
||||||
None => None,
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_waypoint_from_database_json(position: &str) -> Result<Waypoint, PersistenceError> {
|
pub fn convert_waypoint_from_database_json(
|
||||||
|
position: &str,
|
||||||
|
) -> Result<(Option<Waypoint>, Option<MapMarker>), PersistenceError> {
|
||||||
let character_position =
|
let character_position =
|
||||||
serde_json::de::from_str::<CharacterPosition>(position).map_err(|err| {
|
serde_json::de::from_str::<CharacterPosition>(position).map_err(|err| {
|
||||||
PersistenceError::ConversionError(format!(
|
PersistenceError::ConversionError(format!(
|
||||||
@ -246,7 +248,12 @@ pub fn convert_waypoint_from_database_json(position: &str) -> Result<Waypoint, P
|
|||||||
position, err
|
position, err
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
Ok(Waypoint::new(character_position.waypoint, Time(0.0)))
|
Ok((
|
||||||
|
character_position
|
||||||
|
.waypoint
|
||||||
|
.map(|pos| Waypoint::new(pos, Time(0.0))),
|
||||||
|
character_position.map_marker.map(MapMarker),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Properly-recursive items (currently modular weapons) occupy the same
|
/// Properly-recursive items (currently modular weapons) occupy the same
|
||||||
|
@ -25,6 +25,7 @@ pub type CharacterUpdateData = (
|
|||||||
Vec<PetPersistenceData>,
|
Vec<PetPersistenceData>,
|
||||||
Option<comp::Waypoint>,
|
Option<comp::Waypoint>,
|
||||||
comp::ability::ActiveAbilities,
|
comp::ability::ActiveAbilities,
|
||||||
|
Option<comp::MapMarker>,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub type PetPersistenceData = (comp::Pet, comp::Body, comp::Stats);
|
pub type PetPersistenceData = (comp::Pet, comp::Body, comp::Stats);
|
||||||
@ -332,12 +333,21 @@ impl CharacterUpdater {
|
|||||||
Vec<PetPersistenceData>,
|
Vec<PetPersistenceData>,
|
||||||
Option<&'a comp::Waypoint>,
|
Option<&'a comp::Waypoint>,
|
||||||
&'a comp::ability::ActiveAbilities,
|
&'a comp::ability::ActiveAbilities,
|
||||||
|
Option<&'a comp::MapMarker>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
let updates = updates
|
let updates = updates
|
||||||
.map(
|
.map(
|
||||||
|(character_id, skill_set, inventory, pets, waypoint, active_abilities)| {
|
|(
|
||||||
|
character_id,
|
||||||
|
skill_set,
|
||||||
|
inventory,
|
||||||
|
pets,
|
||||||
|
waypoint,
|
||||||
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
|
)| {
|
||||||
(
|
(
|
||||||
character_id,
|
character_id,
|
||||||
(
|
(
|
||||||
@ -346,6 +356,7 @@ impl CharacterUpdater {
|
|||||||
pets,
|
pets,
|
||||||
waypoint.cloned(),
|
waypoint.cloned(),
|
||||||
active_abilities.clone(),
|
active_abilities.clone(),
|
||||||
|
map_marker.cloned(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -388,7 +399,7 @@ fn execute_batch_update(
|
|||||||
transaction.set_drop_behavior(DropBehavior::Rollback);
|
transaction.set_drop_behavior(DropBehavior::Rollback);
|
||||||
trace!("Transaction started for character batch update");
|
trace!("Transaction started for character batch update");
|
||||||
updates.into_iter().try_for_each(
|
updates.into_iter().try_for_each(
|
||||||
|(character_id, (stats, inventory, pets, waypoint, active_abilities))| {
|
|(character_id, (stats, inventory, pets, waypoint, active_abilities, map_marker))| {
|
||||||
super::character::update(
|
super::character::update(
|
||||||
character_id,
|
character_id,
|
||||||
stats,
|
stats,
|
||||||
@ -396,6 +407,7 @@ fn execute_batch_update(
|
|||||||
pets,
|
pets,
|
||||||
waypoint,
|
waypoint,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
&mut transaction,
|
&mut transaction,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@ use common_base::dev_panic;
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
use vek::Vec3;
|
use vek::{Vec2, Vec3};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct HumanoidBody {
|
pub struct HumanoidBody {
|
||||||
@ -62,7 +62,8 @@ generic_body_from_impl!(comp::quadruped_small::Body);
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct CharacterPosition {
|
pub struct CharacterPosition {
|
||||||
pub waypoint: Vec3<f32>,
|
pub waypoint: Option<Vec3<f32>>,
|
||||||
|
pub map_marker: Option<Vec2<i32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skill_group_to_db_string(skill_group: comp::skillset::SkillGroupKind) -> String {
|
pub fn skill_group_to_db_string(skill_group: comp::skillset::SkillGroupKind) -> String {
|
||||||
|
@ -31,6 +31,7 @@ pub struct PersistedComponents {
|
|||||||
pub waypoint: Option<comp::Waypoint>,
|
pub waypoint: Option<comp::Waypoint>,
|
||||||
pub pets: Vec<PetPersistenceData>,
|
pub pets: Vec<PetPersistenceData>,
|
||||||
pub active_abilities: comp::ActiveAbilities,
|
pub active_abilities: comp::ActiveAbilities,
|
||||||
|
pub map_marker: Option<comp::MapMarker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type EditableComponents = (comp::Body,);
|
pub type EditableComponents = (comp::Body,);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::client::Client;
|
use crate::{client::Client, events::update_map_markers};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{anchor::Anchor, group::GroupManager, Agent, Alignment, Pet},
|
comp::{self, anchor::Anchor, group::GroupManager, Agent, Alignment, Pet},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
};
|
};
|
||||||
use common_net::msg::ServerGeneral;
|
use common_net::msg::ServerGeneral;
|
||||||
@ -59,6 +59,7 @@ fn tame_pet_internal(ecs: &specs::World, pet_entity: Entity, owner: Entity, pet:
|
|||||||
// Add to group system
|
// Add to group system
|
||||||
let clients = ecs.read_storage::<Client>();
|
let clients = ecs.read_storage::<Client>();
|
||||||
let mut group_manager = ecs.write_resource::<GroupManager>();
|
let mut group_manager = ecs.write_resource::<GroupManager>();
|
||||||
|
let map_markers = ecs.read_storage::<comp::MapMarker>();
|
||||||
group_manager.new_pet(
|
group_manager.new_pet(
|
||||||
pet_entity,
|
pet_entity,
|
||||||
owner,
|
owner,
|
||||||
@ -71,10 +72,15 @@ fn tame_pet_internal(ecs: &specs::World, pet_entity: Entity, owner: Entity, pet:
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
group_change
|
group_change
|
||||||
.try_map(|e| uids.get(e).copied())
|
.try_map_ref(|e| uids.get(*e).copied())
|
||||||
.map(|g| (g, c))
|
.map(|g| (g, c))
|
||||||
})
|
})
|
||||||
.map(|(g, c)| c.send_fallible(ServerGeneral::GroupUpdate(g)));
|
.map(|(g, c)| {
|
||||||
|
// Might be unneccessary, but maybe pets can somehow have map
|
||||||
|
// markers in the future
|
||||||
|
update_map_markers(&map_markers, &uids, c, &group_change);
|
||||||
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::Client,
|
client::Client,
|
||||||
|
events::update_map_markers,
|
||||||
persistence::PersistedComponents,
|
persistence::PersistedComponents,
|
||||||
pet::restore_pet,
|
pet::restore_pet,
|
||||||
presence::{Presence, RepositionOnChunkLoad},
|
presence::{Presence, RepositionOnChunkLoad},
|
||||||
@ -526,6 +527,7 @@ impl StateExt for State {
|
|||||||
waypoint,
|
waypoint,
|
||||||
pets,
|
pets,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
} = components;
|
} = components;
|
||||||
|
|
||||||
if let Some(player_uid) = self.read_component_copied::<Uid>(entity) {
|
if let Some(player_uid) = self.read_component_copied::<Uid>(entity) {
|
||||||
@ -572,6 +574,10 @@ impl StateExt for State {
|
|||||||
self.write_component_ignore_entity_dead(entity, comp::ForceUpdate);
|
self.write_component_ignore_entity_dead(entity, comp::ForceUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(map_marker) = map_marker {
|
||||||
|
self.write_component_ignore_entity_dead(entity, map_marker);
|
||||||
|
}
|
||||||
|
|
||||||
let player_pos = self.ecs().read_storage::<comp::Pos>().get(entity).copied();
|
let player_pos = self.ecs().read_storage::<comp::Pos>().get(entity).copied();
|
||||||
if let Some(player_pos) = player_pos {
|
if let Some(player_pos) = player_pos {
|
||||||
trace!(
|
trace!(
|
||||||
@ -885,6 +891,7 @@ impl StateExt for State {
|
|||||||
let clients = self.ecs().read_storage::<Client>();
|
let clients = self.ecs().read_storage::<Client>();
|
||||||
let uids = self.ecs().read_storage::<Uid>();
|
let uids = self.ecs().read_storage::<Uid>();
|
||||||
let mut group_manager = self.ecs().write_resource::<comp::group::GroupManager>();
|
let mut group_manager = self.ecs().write_resource::<comp::group::GroupManager>();
|
||||||
|
let map_markers = self.ecs().read_storage::<comp::MapMarker>();
|
||||||
group_manager.entity_deleted(
|
group_manager.entity_deleted(
|
||||||
entity,
|
entity,
|
||||||
&mut self.ecs().write_storage(),
|
&mut self.ecs().write_storage(),
|
||||||
@ -896,10 +903,13 @@ impl StateExt for State {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
group_change
|
group_change
|
||||||
.try_map(|e| uids.get(e).copied())
|
.try_map_ref(|e| uids.get(*e).copied())
|
||||||
.map(|g| (g, c))
|
.map(|g| (g, c))
|
||||||
})
|
})
|
||||||
.map(|(g, c)| c.send(ServerGeneral::GroupUpdate(g)));
|
.map(|(g, c)| {
|
||||||
|
update_map_markers(&map_markers, &uids, c, &group_change);
|
||||||
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -285,6 +285,9 @@ impl Sys {
|
|||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.map(|mut skill_set| skill_set.persistence_load_error = None);
|
.map(|mut skill_set| skill_set.persistence_load_error = None);
|
||||||
},
|
},
|
||||||
|
ClientGeneral::UpdateMapMarker(update) => {
|
||||||
|
server_emitter.emit(ServerEvent::UpdateMapMarker { entity, update });
|
||||||
|
},
|
||||||
ClientGeneral::RequestCharacterList
|
ClientGeneral::RequestCharacterList
|
||||||
| ClientGeneral::CreateCharacter { .. }
|
| ClientGeneral::CreateCharacter { .. }
|
||||||
| ClientGeneral::EditCharacter { .. }
|
| ClientGeneral::EditCharacter { .. }
|
||||||
|
@ -2,7 +2,7 @@ use crate::{persistence::character_updater, presence::Presence, sys::SysSchedule
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
pet::{is_tameable, Pet},
|
pet::{is_tameable, Pet},
|
||||||
ActiveAbilities, Alignment, Body, Inventory, SkillSet, Stats, Waypoint,
|
ActiveAbilities, Alignment, Body, Inventory, MapMarker, SkillSet, Stats, Waypoint,
|
||||||
},
|
},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
};
|
};
|
||||||
@ -22,6 +22,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadStorage<'a, Inventory>,
|
ReadStorage<'a, Inventory>,
|
||||||
ReadStorage<'a, Uid>,
|
ReadStorage<'a, Uid>,
|
||||||
ReadStorage<'a, Waypoint>,
|
ReadStorage<'a, Waypoint>,
|
||||||
|
ReadStorage<'a, MapMarker>,
|
||||||
ReadStorage<'a, Pet>,
|
ReadStorage<'a, Pet>,
|
||||||
ReadStorage<'a, Stats>,
|
ReadStorage<'a, Stats>,
|
||||||
ReadStorage<'a, ActiveAbilities>,
|
ReadStorage<'a, ActiveAbilities>,
|
||||||
@ -43,6 +44,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
player_inventories,
|
player_inventories,
|
||||||
uids,
|
uids,
|
||||||
player_waypoints,
|
player_waypoints,
|
||||||
|
map_markers,
|
||||||
pets,
|
pets,
|
||||||
stats,
|
stats,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
@ -59,6 +61,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&uids,
|
&uids,
|
||||||
player_waypoints.maybe(),
|
player_waypoints.maybe(),
|
||||||
&active_abilities,
|
&active_abilities,
|
||||||
|
map_markers.maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.filter_map(
|
.filter_map(
|
||||||
@ -69,6 +72,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
player_uid,
|
player_uid,
|
||||||
waypoint,
|
waypoint,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
)| match presence.kind {
|
)| match presence.kind {
|
||||||
PresenceKind::Character(id) => {
|
PresenceKind::Character(id) => {
|
||||||
let pets = (&alignments, &bodies, &stats, &pets)
|
let pets = (&alignments, &bodies, &stats, &pets)
|
||||||
@ -86,7 +90,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Some((id, skill_set, inventory, pets, waypoint, active_abilities))
|
Some((
|
||||||
|
id,
|
||||||
|
skill_set,
|
||||||
|
inventory,
|
||||||
|
pets,
|
||||||
|
waypoint,
|
||||||
|
active_abilities,
|
||||||
|
map_marker,
|
||||||
|
))
|
||||||
},
|
},
|
||||||
PresenceKind::Spectator => None,
|
PresenceKind::Spectator => None,
|
||||||
},
|
},
|
||||||
|
@ -368,6 +368,7 @@ image_ids! {
|
|||||||
indicator_group_up: "voxygen.element.ui.map.buttons.group_indicator_arrow_up",
|
indicator_group_up: "voxygen.element.ui.map.buttons.group_indicator_arrow_up",
|
||||||
indicator_group_down: "voxygen.element.ui.map.buttons.group_indicator_arrow_down",
|
indicator_group_down: "voxygen.element.ui.map.buttons.group_indicator_arrow_down",
|
||||||
location_marker: "voxygen.element.ui.map.buttons.location_marker",
|
location_marker: "voxygen.element.ui.map.buttons.location_marker",
|
||||||
|
location_marker_group: "voxygen.element.ui.map.buttons.location_marker_group",
|
||||||
map_mode_overlay: "voxygen.element.ui.map.buttons.map_modes",
|
map_mode_overlay: "voxygen.element.ui.map.buttons.map_modes",
|
||||||
minimap_mode_overlay: "voxygen.element.ui.map.buttons.minimap_modes",
|
minimap_mode_overlay: "voxygen.element.ui.map.buttons.minimap_modes",
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{
|
use super::{
|
||||||
img_ids::{Imgs, ImgsRot},
|
img_ids::{Imgs, ImgsRot},
|
||||||
Show, QUALITY_COMMON, QUALITY_EPIC, QUALITY_HIGH, QUALITY_LOW, QUALITY_MODERATE, TEXT_BG,
|
MapMarkers, QUALITY_COMMON, QUALITY_EPIC, QUALITY_HIGH, QUALITY_LOW, QUALITY_MODERATE, TEXT_BG,
|
||||||
TEXT_BLUE_COLOR, TEXT_COLOR, TEXT_GRAY_COLOR, TEXT_VELORITE, UI_HIGHLIGHT_0, UI_MAIN,
|
TEXT_BLUE_COLOR, TEXT_COLOR, TEXT_GRAY_COLOR, TEXT_VELORITE, UI_HIGHLIGHT_0, UI_MAIN,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -51,6 +51,7 @@ widget_ids! {
|
|||||||
member_indicators[],
|
member_indicators[],
|
||||||
member_height_indicators[],
|
member_height_indicators[],
|
||||||
location_marker,
|
location_marker,
|
||||||
|
location_marker_group[],
|
||||||
map_settings_align,
|
map_settings_align,
|
||||||
show_towns_img,
|
show_towns_img,
|
||||||
show_towns_box,
|
show_towns_box,
|
||||||
@ -98,7 +99,6 @@ const SHOW_ECONOMY: bool = false; // turn this display off (for 0.9) until we ha
|
|||||||
|
|
||||||
#[derive(WidgetCommon)]
|
#[derive(WidgetCommon)]
|
||||||
pub struct Map<'a> {
|
pub struct Map<'a> {
|
||||||
show: &'a Show,
|
|
||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
world_map: &'a (Vec<img_ids::Rotations>, Vec2<u32>),
|
world_map: &'a (Vec<img_ids::Rotations>, Vec2<u32>),
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
@ -110,12 +110,11 @@ pub struct Map<'a> {
|
|||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
rot_imgs: &'a ImgsRot,
|
rot_imgs: &'a ImgsRot,
|
||||||
tooltip_manager: &'a mut TooltipManager,
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
location_marker: Option<Vec2<f32>>,
|
location_markers: &'a MapMarkers,
|
||||||
map_drag: Vec2<f64>,
|
map_drag: Vec2<f64>,
|
||||||
}
|
}
|
||||||
impl<'a> Map<'a> {
|
impl<'a> Map<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
show: &'a Show,
|
|
||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
rot_imgs: &'a ImgsRot,
|
rot_imgs: &'a ImgsRot,
|
||||||
@ -125,11 +124,10 @@ impl<'a> Map<'a> {
|
|||||||
localized_strings: &'a Localization,
|
localized_strings: &'a Localization,
|
||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
tooltip_manager: &'a mut TooltipManager,
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
location_marker: Option<Vec2<f32>>,
|
location_markers: &'a MapMarkers,
|
||||||
map_drag: Vec2<f64>,
|
map_drag: Vec2<f64>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
show,
|
|
||||||
imgs,
|
imgs,
|
||||||
rot_imgs,
|
rot_imgs,
|
||||||
world_map,
|
world_map,
|
||||||
@ -140,7 +138,7 @@ impl<'a> Map<'a> {
|
|||||||
localized_strings,
|
localized_strings,
|
||||||
global_state,
|
global_state,
|
||||||
tooltip_manager,
|
tooltip_manager,
|
||||||
location_marker,
|
location_markers,
|
||||||
map_drag,
|
map_drag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,9 +152,9 @@ pub enum Event {
|
|||||||
SettingsChange(InterfaceChange),
|
SettingsChange(InterfaceChange),
|
||||||
Close,
|
Close,
|
||||||
RequestSiteInfo(SiteId),
|
RequestSiteInfo(SiteId),
|
||||||
SetLocationMarker(Vec2<f32>),
|
SetLocationMarker(Vec2<i32>),
|
||||||
MapDrag(Vec2<f64>),
|
MapDrag(Vec2<f64>),
|
||||||
ToggleMarker,
|
RemoveMarker,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_site_economy(site_rich: &SiteInfoRich) -> String {
|
fn get_site_economy(site_rich: &SiteInfoRich) -> String {
|
||||||
@ -370,16 +368,15 @@ impl<'a> Widget for Map<'a> {
|
|||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
match wpos {
|
match wpos {
|
||||||
Some(ref wpos) => events.push(Event::SetLocationMarker(*wpos)),
|
Some(ref wpos) => events.push(Event::SetLocationMarker(wpos.as_())),
|
||||||
None => {
|
None => {
|
||||||
let tmp: Vec2<f64> = Vec2::<f64>::from(click.xy) / zoom - drag;
|
let tmp: Vec2<f64> = Vec2::<f64>::from(click.xy) / zoom - drag;
|
||||||
let wpos = tmp
|
let wpos = tmp
|
||||||
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as f32 * sz as f32)
|
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as f32 * sz as f32)
|
||||||
+ player_pos;
|
+ player_pos;
|
||||||
events.push(Event::SetLocationMarker(wpos));
|
events.push(Event::SetLocationMarker(wpos.as_()));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
events.push(Event::ToggleMarker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle zooming with the mousewheel
|
// Handle zooming with the mousewheel
|
||||||
@ -1220,18 +1217,36 @@ impl<'a> Widget for Map<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Location marker
|
let factor = 1.4;
|
||||||
if self.show.map_marker {
|
let side_length = 20.0 * factor;
|
||||||
let factor = 1.4;
|
// Groups location markers
|
||||||
let side_length = 20.0 * factor;
|
if state.ids.location_marker_group.len() < self.location_markers.group.len() {
|
||||||
if let Some((lm, (rpos, fade))) = self.location_marker.and_then(|lm| {
|
state.update(|s| {
|
||||||
Some(lm).zip(wpos_to_rpos_fade(
|
s.ids.location_marker_group.resize(
|
||||||
lm,
|
self.location_markers.group.len(),
|
||||||
Vec2::from(side_length / 2.0),
|
&mut ui.widget_id_generator(),
|
||||||
side_length / 2.0,
|
)
|
||||||
))
|
})
|
||||||
}) {
|
};
|
||||||
if Button::image(self.imgs.location_marker)
|
for (i, (&uid, &rpos)) in self.location_markers.group.iter().enumerate() {
|
||||||
|
let lm = rpos.as_();
|
||||||
|
if let Some((rpos, fade)) =
|
||||||
|
wpos_to_rpos_fade(lm, Vec2::from(side_length / 2.0), side_length / 2.0)
|
||||||
|
{
|
||||||
|
let name = self
|
||||||
|
.client
|
||||||
|
.player_list()
|
||||||
|
.get(&uid)
|
||||||
|
.map(|info| info.player_alias.as_str())
|
||||||
|
.or_else(|| {
|
||||||
|
uid_allocator
|
||||||
|
.retrieve_entity_internal(uid.into())
|
||||||
|
.and_then(|entity| stats.get(entity))
|
||||||
|
.map(|stats| stats.name.as_str())
|
||||||
|
})
|
||||||
|
.unwrap_or("");
|
||||||
|
|
||||||
|
Button::image(self.imgs.location_marker_group)
|
||||||
.x_y_position_relative_to(
|
.x_y_position_relative_to(
|
||||||
state.ids.map_layers[0],
|
state.ids.map_layers[0],
|
||||||
position::Relative::Scalar(rpos.x as f64),
|
position::Relative::Scalar(rpos.x as f64),
|
||||||
@ -1247,26 +1262,58 @@ impl<'a> Widget for Map<'a> {
|
|||||||
"X: {}, Y: {}\n\n{}",
|
"X: {}, Y: {}\n\n{}",
|
||||||
lm.x as i32,
|
lm.x as i32,
|
||||||
lm.y as i32,
|
lm.y as i32,
|
||||||
i18n.get("hud.map.marked_location_remove")
|
i18n.get("hud.map.placed_by").replace("{name}", name),
|
||||||
),
|
),
|
||||||
&site_tooltip,
|
&site_tooltip,
|
||||||
TEXT_VELORITE,
|
TEXT_VELORITE,
|
||||||
)
|
)
|
||||||
.set(state.ids.location_marker, ui)
|
.set(state.ids.location_marker_group[i], ui);
|
||||||
.was_clicked()
|
|
||||||
{
|
|
||||||
events.push(Event::ToggleMarker);
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_widget_mouse_events(
|
|
||||||
state.ids.location_marker,
|
|
||||||
Some(Vec2::new(0.0, 0.0)),
|
|
||||||
ui,
|
|
||||||
&mut events,
|
|
||||||
state.ids.map_layers[0],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Location marker
|
||||||
|
if let Some((lm, (rpos, fade))) = self.location_markers.owned.and_then(|lm| {
|
||||||
|
let lm = lm.as_();
|
||||||
|
Some(lm).zip(wpos_to_rpos_fade(
|
||||||
|
lm,
|
||||||
|
Vec2::from(side_length / 2.0),
|
||||||
|
side_length / 2.0,
|
||||||
|
))
|
||||||
|
}) {
|
||||||
|
if Button::image(self.imgs.location_marker)
|
||||||
|
.x_y_position_relative_to(
|
||||||
|
state.ids.map_layers[0],
|
||||||
|
position::Relative::Scalar(rpos.x as f64),
|
||||||
|
position::Relative::Scalar(rpos.y as f64 + 10.0 * factor as f64),
|
||||||
|
)
|
||||||
|
.w_h(side_length as f64, side_length as f64)
|
||||||
|
.image_color(Color::Rgba(1.0, 1.0, 1.0, fade))
|
||||||
|
.floating(true)
|
||||||
|
.with_tooltip(
|
||||||
|
self.tooltip_manager,
|
||||||
|
i18n.get("hud.map.marked_location"),
|
||||||
|
&format!(
|
||||||
|
"X: {}, Y: {}\n\n{}",
|
||||||
|
lm.x as i32,
|
||||||
|
lm.y as i32,
|
||||||
|
i18n.get("hud.map.marked_location_remove")
|
||||||
|
),
|
||||||
|
&site_tooltip,
|
||||||
|
TEXT_VELORITE,
|
||||||
|
)
|
||||||
|
.set(state.ids.location_marker, ui)
|
||||||
|
.was_clicked()
|
||||||
|
{
|
||||||
|
events.push(Event::RemoveMarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_widget_mouse_events(
|
||||||
|
state.ids.location_marker,
|
||||||
|
Some(Vec2::new(0.0, 0.0)),
|
||||||
|
ui,
|
||||||
|
&mut events,
|
||||||
|
state.ids.map_layers[0],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Cursor pos relative to playerpos and widget size
|
// Cursor pos relative to playerpos and widget size
|
||||||
// Cursor stops moving on an axis as soon as it's position exceeds the maximum
|
// Cursor stops moving on an axis as soon as it's position exceeds the maximum
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{
|
use super::{
|
||||||
img_ids::{Imgs, ImgsRot},
|
img_ids::{Imgs, ImgsRot},
|
||||||
Show, QUALITY_COMMON, QUALITY_DEBUG, QUALITY_EPIC, QUALITY_HIGH, QUALITY_LOW, QUALITY_MODERATE,
|
MapMarkers, QUALITY_COMMON, QUALITY_DEBUG, QUALITY_EPIC, QUALITY_HIGH, QUALITY_LOW,
|
||||||
TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
QUALITY_MODERATE, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
hud::{Graphic, Ui},
|
hud::{Graphic, Ui},
|
||||||
@ -375,7 +375,6 @@ widget_ids! {
|
|||||||
|
|
||||||
#[derive(WidgetCommon)]
|
#[derive(WidgetCommon)]
|
||||||
pub struct MiniMap<'a> {
|
pub struct MiniMap<'a> {
|
||||||
show: &'a Show,
|
|
||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
rot_imgs: &'a ImgsRot,
|
rot_imgs: &'a ImgsRot,
|
||||||
@ -385,13 +384,12 @@ pub struct MiniMap<'a> {
|
|||||||
common: widget::CommonBuilder,
|
common: widget::CommonBuilder,
|
||||||
ori: Vec3<f32>,
|
ori: Vec3<f32>,
|
||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
location_marker: Option<Vec2<f32>>,
|
location_markers: &'a MapMarkers,
|
||||||
voxel_minimap: &'a VoxelMinimap,
|
voxel_minimap: &'a VoxelMinimap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MiniMap<'a> {
|
impl<'a> MiniMap<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
show: &'a Show,
|
|
||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
rot_imgs: &'a ImgsRot,
|
rot_imgs: &'a ImgsRot,
|
||||||
@ -399,11 +397,10 @@ impl<'a> MiniMap<'a> {
|
|||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
ori: Vec3<f32>,
|
ori: Vec3<f32>,
|
||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
location_marker: Option<Vec2<f32>>,
|
location_markers: &'a MapMarkers,
|
||||||
voxel_minimap: &'a VoxelMinimap,
|
voxel_minimap: &'a VoxelMinimap,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
show,
|
|
||||||
client,
|
client,
|
||||||
imgs,
|
imgs,
|
||||||
rot_imgs,
|
rot_imgs,
|
||||||
@ -412,7 +409,7 @@ impl<'a> MiniMap<'a> {
|
|||||||
common: widget::CommonBuilder::default(),
|
common: widget::CommonBuilder::default(),
|
||||||
ori,
|
ori,
|
||||||
global_state,
|
global_state,
|
||||||
location_marker,
|
location_markers,
|
||||||
voxel_minimap,
|
voxel_minimap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -792,11 +789,14 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Location marker
|
// Location marker
|
||||||
if self.show.map_marker {
|
if let Some(rpos) = self
|
||||||
if let Some(rpos) = self.location_marker.and_then(|lm| wpos_to_rpos(lm, true)) {
|
.location_markers
|
||||||
let factor = 1.2;
|
.owned
|
||||||
|
.and_then(|lm| wpos_to_rpos(lm.as_(), true))
|
||||||
|
{
|
||||||
|
let factor = 1.2;
|
||||||
|
|
||||||
Button::image(self.imgs.location_marker)
|
Button::image(self.imgs.location_marker)
|
||||||
.x_y_position_relative_to(
|
.x_y_position_relative_to(
|
||||||
state.ids.map_layers[0],
|
state.ids.map_layers[0],
|
||||||
position::Relative::Scalar(rpos.x as f64),
|
position::Relative::Scalar(rpos.x as f64),
|
||||||
@ -806,7 +806,6 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
//.image_color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
|
//.image_color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
|
||||||
.floating(true)
|
.floating(true)
|
||||||
.set(state.ids.location_marker, ui);
|
.set(state.ids.location_marker, ui);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Indicator
|
// Indicator
|
||||||
let ind_scale = 0.4;
|
let ind_scale = 0.4;
|
||||||
|
@ -83,7 +83,7 @@ use common::{
|
|||||||
inventory::{slot::InvSlotId, trade_pricing::TradePricing},
|
inventory::{slot::InvSlotId, trade_pricing::TradePricing},
|
||||||
item::{tool::ToolKind, ItemDesc, MaterialStatManifest, Quality},
|
item::{tool::ToolKind, ItemDesc, MaterialStatManifest, Quality},
|
||||||
skillset::{skills::Skill, SkillGroupKind},
|
skillset::{skills::Skill, SkillGroupKind},
|
||||||
BuffData, BuffKind, Item,
|
BuffData, BuffKind, Item, MapMarkerChange,
|
||||||
},
|
},
|
||||||
consts::MAX_PICKUP_RANGE,
|
consts::MAX_PICKUP_RANGE,
|
||||||
link::Is,
|
link::Is,
|
||||||
@ -546,6 +546,7 @@ pub enum Event {
|
|||||||
|
|
||||||
SettingsChange(SettingsChange),
|
SettingsChange(SettingsChange),
|
||||||
AcknowledgePersistenceLoadError,
|
AcknowledgePersistenceLoadError,
|
||||||
|
MapMarkerEvent(MapMarkerChange),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Are these the possible layouts we want?
|
// TODO: Are these the possible layouts we want?
|
||||||
@ -638,6 +639,12 @@ impl PressBehavior {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct MapMarkers {
|
||||||
|
owned: Option<Vec2<i32>>,
|
||||||
|
group: HashMap<Uid, Vec2<i32>>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Show {
|
pub struct Show {
|
||||||
ui: bool,
|
ui: bool,
|
||||||
intro: bool,
|
intro: bool,
|
||||||
@ -667,8 +674,7 @@ pub struct Show {
|
|||||||
auto_walk: bool,
|
auto_walk: bool,
|
||||||
camera_clamp: bool,
|
camera_clamp: bool,
|
||||||
prompt_dialog: Option<PromptDialogSettings>,
|
prompt_dialog: Option<PromptDialogSettings>,
|
||||||
location_marker: Option<Vec2<f32>>,
|
location_markers: MapMarkers,
|
||||||
map_marker: bool,
|
|
||||||
salvage: bool,
|
salvage: bool,
|
||||||
}
|
}
|
||||||
impl Show {
|
impl Show {
|
||||||
@ -889,6 +895,26 @@ impl Show {
|
|||||||
global_state.window.center_cursor();
|
global_state.window.center_cursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_map_markers(&mut self, event: comp::MapMarkerUpdate) {
|
||||||
|
match event {
|
||||||
|
comp::MapMarkerUpdate::Owned(event) => match event {
|
||||||
|
MapMarkerChange::Update(waypoint) => self.location_markers.owned = Some(waypoint),
|
||||||
|
MapMarkerChange::Remove => self.location_markers.owned = None,
|
||||||
|
},
|
||||||
|
comp::MapMarkerUpdate::GroupMember(user, event) => match event {
|
||||||
|
MapMarkerChange::Update(waypoint) => {
|
||||||
|
self.location_markers.group.insert(user, waypoint);
|
||||||
|
},
|
||||||
|
MapMarkerChange::Remove => {
|
||||||
|
self.location_markers.group.remove(&user);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
comp::MapMarkerUpdate::ClearGroup => {
|
||||||
|
self.location_markers.group.clear();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PromptDialogSettings {
|
pub struct PromptDialogSettings {
|
||||||
@ -1060,8 +1086,7 @@ impl Hud {
|
|||||||
auto_walk: false,
|
auto_walk: false,
|
||||||
camera_clamp: false,
|
camera_clamp: false,
|
||||||
prompt_dialog: None,
|
prompt_dialog: None,
|
||||||
location_marker: None,
|
location_markers: MapMarkers::default(),
|
||||||
map_marker: false,
|
|
||||||
salvage: false,
|
salvage: false,
|
||||||
},
|
},
|
||||||
to_focus: None,
|
to_focus: None,
|
||||||
@ -2756,7 +2781,6 @@ impl Hud {
|
|||||||
|
|
||||||
// MiniMap
|
// MiniMap
|
||||||
for event in MiniMap::new(
|
for event in MiniMap::new(
|
||||||
&self.show,
|
|
||||||
client,
|
client,
|
||||||
&self.imgs,
|
&self.imgs,
|
||||||
&self.rot_imgs,
|
&self.rot_imgs,
|
||||||
@ -2764,7 +2788,7 @@ impl Hud {
|
|||||||
&self.fonts,
|
&self.fonts,
|
||||||
camera.get_orientation(),
|
camera.get_orientation(),
|
||||||
global_state,
|
global_state,
|
||||||
self.show.location_marker,
|
&self.show.location_markers,
|
||||||
&self.voxel_minimap,
|
&self.voxel_minimap,
|
||||||
)
|
)
|
||||||
.set(self.ids.minimap, ui_widgets)
|
.set(self.ids.minimap, ui_widgets)
|
||||||
@ -3272,7 +3296,6 @@ impl Hud {
|
|||||||
// Map
|
// Map
|
||||||
if self.show.map {
|
if self.show.map {
|
||||||
for event in Map::new(
|
for event in Map::new(
|
||||||
&self.show,
|
|
||||||
client,
|
client,
|
||||||
&self.imgs,
|
&self.imgs,
|
||||||
&self.rot_imgs,
|
&self.rot_imgs,
|
||||||
@ -3282,7 +3305,7 @@ impl Hud {
|
|||||||
i18n,
|
i18n,
|
||||||
global_state,
|
global_state,
|
||||||
tooltip_manager,
|
tooltip_manager,
|
||||||
self.show.location_marker,
|
&self.show.location_markers,
|
||||||
self.map_drag,
|
self.map_drag,
|
||||||
)
|
)
|
||||||
.set(self.ids.map, ui_widgets)
|
.set(self.ids.map, ui_widgets)
|
||||||
@ -3300,13 +3323,15 @@ impl Hud {
|
|||||||
events.push(Event::RequestSiteInfo(id));
|
events.push(Event::RequestSiteInfo(id));
|
||||||
},
|
},
|
||||||
map::Event::SetLocationMarker(pos) => {
|
map::Event::SetLocationMarker(pos) => {
|
||||||
self.show.location_marker = Some(pos);
|
events.push(Event::MapMarkerEvent(MapMarkerChange::Update(pos)));
|
||||||
|
self.show.location_markers.owned = Some(pos);
|
||||||
},
|
},
|
||||||
map::Event::MapDrag(new_drag) => {
|
map::Event::MapDrag(new_drag) => {
|
||||||
self.map_drag = new_drag;
|
self.map_drag = new_drag;
|
||||||
},
|
},
|
||||||
map::Event::ToggleMarker => {
|
map::Event::RemoveMarker => {
|
||||||
self.show.map_marker = !self.show.map_marker;
|
self.show.location_markers.owned = None;
|
||||||
|
events.push(Event::MapMarkerEvent(MapMarkerChange::Remove));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,6 +308,9 @@ impl SessionState {
|
|||||||
client::Event::CharacterError(error) => {
|
client::Event::CharacterError(error) => {
|
||||||
global_state.client_error = Some(error);
|
global_state.client_error = Some(error);
|
||||||
},
|
},
|
||||||
|
client::Event::MapMarker(event) => {
|
||||||
|
self.hud.show.update_map_markers(event);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1446,6 +1449,9 @@ impl PlayState for SessionState {
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.acknolwedge_persistence_load_error();
|
.acknolwedge_persistence_load_error();
|
||||||
},
|
},
|
||||||
|
HudEvent::MapMarkerEvent(event) => {
|
||||||
|
self.client.borrow_mut().map_marker_event(event);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user