mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'zesterer/cs-char-saving' into 'master'
Client-side character saving See merge request veloren/veloren!737
This commit is contained in:
commit
0223a60a1e
@ -29,7 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Added a Death Screen and Hurt Screen
|
||||
- Added randomly selected Loading Screen background images
|
||||
- Added options to disable clouds and to use cheaper water rendering
|
||||
|
||||
- Added client-side character saving
|
||||
|
||||
### Changed
|
||||
|
||||
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3244,6 +3244,7 @@ name = "veloren-voxygen"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"conrod_core 0.63.0 (git+https://gitlab.com/veloren/conrod.git)",
|
||||
"conrod_winit 0.63.0 (git+https://gitlab.com/veloren/conrod.git)",
|
||||
|
@ -13,17 +13,18 @@ use specs::{Component, FlaggedStorage};
|
||||
use specs_idvs::IDVStorage;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Body {
|
||||
Humanoid(humanoid::Body),
|
||||
QuadrupedSmall(quadruped_small::Body),
|
||||
QuadrupedMedium(quadruped_medium::Body),
|
||||
BirdMedium(bird_medium::Body),
|
||||
FishMedium(fish_medium::Body),
|
||||
Dragon(dragon::Body),
|
||||
BirdSmall(bird_small::Body),
|
||||
FishSmall(fish_small::Body),
|
||||
BipedLarge(biped_large::Body),
|
||||
Object(object::Body),
|
||||
Humanoid(humanoid::Body) = 0,
|
||||
QuadrupedSmall(quadruped_small::Body) = 1,
|
||||
QuadrupedMedium(quadruped_medium::Body) = 2,
|
||||
BirdMedium(bird_medium::Body) = 3,
|
||||
FishMedium(fish_medium::Body) = 4,
|
||||
Dragon(dragon::Body) = 5,
|
||||
BirdSmall(bird_small::Body) = 6,
|
||||
FishSmall(fish_small::Body) = 7,
|
||||
BipedLarge(biped_large::Body) = 8,
|
||||
Object(object::Body) = 9,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub head: Head,
|
||||
pub upper_torso: UpperTorso,
|
||||
@ -34,66 +35,77 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Head {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS: [Head; 1] = [Head::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum UpperTorso {
|
||||
Default,
|
||||
}
|
||||
const ALL_UPPER_TORSOS: [UpperTorso; 1] = [UpperTorso::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum LowerTorso {
|
||||
Default,
|
||||
}
|
||||
const ALL_LOWER_TORSOS: [LowerTorso; 1] = [LowerTorso::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum ShoulderL {
|
||||
Default,
|
||||
}
|
||||
const ALL_SHOULDER_LS: [ShoulderL; 1] = [ShoulderL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum ShoulderR {
|
||||
Default,
|
||||
}
|
||||
const ALL_SHOULDER_RS: [ShoulderR; 1] = [ShoulderR::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum HandL {
|
||||
Default,
|
||||
}
|
||||
const ALL_HAND_LS: [HandL; 1] = [HandL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum HandR {
|
||||
Default,
|
||||
}
|
||||
const ALL_HAND_RS: [HandR; 1] = [HandR::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum LegL {
|
||||
Default,
|
||||
}
|
||||
const ALL_LEG_LS: [LegL; 1] = [LegL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum LegR {
|
||||
Default,
|
||||
}
|
||||
const ALL_LEG_RS: [LegR; 1] = [LegR::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootL {
|
||||
Default,
|
||||
}
|
||||
const ALL_FOOT_LS: [FootL; 1] = [FootL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootR {
|
||||
Default,
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub head: Head,
|
||||
pub torso: Torso,
|
||||
@ -26,42 +27,49 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Head {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS: [Head; 1] = [Head::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Torso {
|
||||
Default,
|
||||
}
|
||||
const ALL_TORSOS: [Torso; 1] = [Torso::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Tail {
|
||||
Default,
|
||||
}
|
||||
const ALL_TAILS: [Tail; 1] = [Tail::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingL {
|
||||
Default,
|
||||
}
|
||||
const ALL_WING_LS: [WingL; 1] = [WingL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingR {
|
||||
Default,
|
||||
}
|
||||
const ALL_WING_RS: [WingR; 1] = [WingR::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum LegL {
|
||||
Default,
|
||||
}
|
||||
const ALL_LEG_LS: [LegL; 1] = [LegL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum LegR {
|
||||
Default,
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub head: Head,
|
||||
pub torso: Torso,
|
||||
@ -20,24 +21,28 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Head {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS: [Head; 1] = [Head::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Torso {
|
||||
Default,
|
||||
}
|
||||
const ALL_TORSOS: [Torso; 1] = [Torso::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingL {
|
||||
Default,
|
||||
}
|
||||
const ALL_WING_LS: [WingL; 1] = [WingL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingR {
|
||||
Default,
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub head: Head,
|
||||
pub chest_front: ChestFront,
|
||||
@ -38,78 +39,91 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Head {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS: [Head; 1] = [Head::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum ChestFront {
|
||||
Default,
|
||||
}
|
||||
const ALL_CHEST_FRONTS: [ChestFront; 1] = [ChestFront::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum ChestRear {
|
||||
Default,
|
||||
}
|
||||
const ALL_CHEST_REARS: [ChestRear; 1] = [ChestRear::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum TailFront {
|
||||
Default,
|
||||
}
|
||||
const ALL_TAIL_FRONTS: [TailFront; 1] = [TailFront::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum TailRear {
|
||||
Default,
|
||||
}
|
||||
const ALL_TAIL_REARS: [TailRear; 1] = [TailRear::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingInL {
|
||||
Default,
|
||||
}
|
||||
const ALL_WING_IN_LS: [WingInL; 1] = [WingInL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingInR {
|
||||
Default,
|
||||
}
|
||||
const ALL_WING_IN_RS: [WingInR; 1] = [WingInR::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingOutL {
|
||||
Default,
|
||||
}
|
||||
const ALL_WING_OUT_LS: [WingOutL; 1] = [WingOutL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum WingOutR {
|
||||
Default,
|
||||
}
|
||||
const ALL_WING_OUT_RS: [WingOutR; 1] = [WingOutR::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootFL {
|
||||
Default,
|
||||
}
|
||||
const ALL_FOOT_FLS: [FootFL; 1] = [FootFL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootFR {
|
||||
Default,
|
||||
}
|
||||
const ALL_FOOT_FRS: [FootFR; 1] = [FootFR::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootBL {
|
||||
Default,
|
||||
}
|
||||
const ALL_FOOT_BLS: [FootBL; 1] = [FootBL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootBR {
|
||||
Default,
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub head: Head,
|
||||
pub torso: Torso,
|
||||
@ -24,36 +25,42 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Head {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS: [Head; 1] = [Head::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Torso {
|
||||
Default,
|
||||
}
|
||||
const ALL_TORSOS: [Torso; 1] = [Torso::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Rear {
|
||||
Default,
|
||||
}
|
||||
const ALL_REARS: [Rear; 1] = [Rear::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Tail {
|
||||
Default,
|
||||
}
|
||||
const ALL_TAILS: [Tail; 1] = [Tail::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FinL {
|
||||
Default,
|
||||
}
|
||||
const ALL_FIN_LS: [FinL; 1] = [FinL::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FinR {
|
||||
Default,
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub torso: Torso,
|
||||
pub tail: Tail,
|
||||
@ -16,12 +17,14 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Torso {
|
||||
Default,
|
||||
}
|
||||
const ALL_TORSOS: [Torso; 1] = [Torso::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Tail {
|
||||
Default,
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub head: Head,
|
||||
pub head: Head,
|
||||
pub shoulder: Shoulder,
|
||||
pub chest: Chest,
|
||||
pub hand: Hand
|
||||
pub hand: Hand
|
||||
pub belt: Belt,
|
||||
pub pants: Pants,
|
||||
pub foot: Foot,
|
||||
pub foot: Foot,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
@ -27,40 +28,47 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Head {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS: [Head; 1] = [Head::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Shoulder {
|
||||
Default,
|
||||
}
|
||||
const ALL_SHOULDERS: [Shoulder; 1] = [Shoulder::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Chest {
|
||||
Default,
|
||||
}
|
||||
const ALL_CHESTS: [Chest; 1] = [Chest::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Hand {
|
||||
Default,
|
||||
}
|
||||
const ALL_HANDS: [Hand; 1] = [Hand::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Belt {
|
||||
Default,
|
||||
}
|
||||
const ALL_BELTS: [Belt; 1] = [Belt::Default];
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Pants {
|
||||
Default,
|
||||
}
|
||||
const ALL_FEET: [Foot; 1] = [Foot::Default];
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Foot {
|
||||
Default,
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use rand::{seq::SliceRandom, thread_rng, Rng};
|
||||
use vek::Rgb;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub race: Race,
|
||||
pub body_type: BodyType,
|
||||
@ -59,13 +60,14 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Race {
|
||||
Danari,
|
||||
Dwarf,
|
||||
Elf,
|
||||
Human,
|
||||
Orc,
|
||||
Undead,
|
||||
Danari = 0,
|
||||
Dwarf = 1,
|
||||
Elf = 2,
|
||||
Human = 3,
|
||||
Orc = 4,
|
||||
Undead = 5,
|
||||
}
|
||||
pub const ALL_RACES: [Race; 6] = [
|
||||
Race::Danari,
|
||||
@ -379,21 +381,23 @@ impl Race {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female,
|
||||
Male,
|
||||
Female = 0,
|
||||
Male = 1,
|
||||
}
|
||||
pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Chest {
|
||||
Blue,
|
||||
Brown,
|
||||
Dark,
|
||||
Green,
|
||||
Orange,
|
||||
Midnight,
|
||||
Kimono,
|
||||
Blue = 0,
|
||||
Brown = 1,
|
||||
Dark = 2,
|
||||
Green = 3,
|
||||
Orange = 4,
|
||||
Midnight = 5,
|
||||
Kimono = 6,
|
||||
}
|
||||
pub const ALL_CHESTS: [Chest; 7] = [
|
||||
Chest::Blue,
|
||||
@ -406,20 +410,22 @@ pub const ALL_CHESTS: [Chest; 7] = [
|
||||
];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Belt {
|
||||
Dark,
|
||||
Cloth,
|
||||
Dark = 0,
|
||||
Cloth = 1,
|
||||
}
|
||||
pub const ALL_BELTS: [Belt; 2] = [Belt::Dark, Belt::Cloth];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Pants {
|
||||
Blue,
|
||||
Brown,
|
||||
Dark,
|
||||
Green,
|
||||
Orange,
|
||||
Kimono,
|
||||
Blue = 0,
|
||||
Brown = 1,
|
||||
Dark = 2,
|
||||
Green = 3,
|
||||
Orange = 4,
|
||||
Kimono = 5,
|
||||
}
|
||||
pub const ALL_PANTS: [Pants; 6] = [
|
||||
Pants::Blue,
|
||||
@ -431,47 +437,52 @@ pub const ALL_PANTS: [Pants; 6] = [
|
||||
];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Hand {
|
||||
Bare,
|
||||
Cloth,
|
||||
Bare = 0,
|
||||
Cloth = 1,
|
||||
}
|
||||
pub const ALL_HANDS: [Hand; 2] = [Hand::Bare, Hand::Cloth];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Foot {
|
||||
Bare,
|
||||
Dark,
|
||||
Sandal,
|
||||
Jester,
|
||||
Bare = 0,
|
||||
Dark = 1,
|
||||
Sandal = 2,
|
||||
Jester = 3,
|
||||
}
|
||||
pub const ALL_FEET: [Foot; 4] = [Foot::Bare, Foot::Dark, Foot::Sandal, Foot::Jester];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Shoulder {
|
||||
None,
|
||||
Brown1,
|
||||
Chain,
|
||||
None = 0,
|
||||
Brown1 = 1,
|
||||
Chain = 2,
|
||||
}
|
||||
pub const ALL_SHOULDERS: [Shoulder; 3] = [Shoulder::None, Shoulder::Brown1, Shoulder::Chain];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Eyebrows {
|
||||
Yup,
|
||||
Yup = 0,
|
||||
}
|
||||
pub const ALL_EYEBROWS: [Eyebrows; 1] = [Eyebrows::Yup];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum EyeColor {
|
||||
VigorousBlack,
|
||||
NobleBlue,
|
||||
CuriousGreen,
|
||||
LoyalBrown,
|
||||
ViciousRed,
|
||||
PumpkinOrange,
|
||||
GhastlyYellow,
|
||||
MagicPurple,
|
||||
ToxicGreen,
|
||||
ExoticPurple,
|
||||
VigorousBlack = 0,
|
||||
NobleBlue = 1,
|
||||
CuriousGreen = 2,
|
||||
LoyalBrown = 3,
|
||||
ViciousRed = 4,
|
||||
PumpkinOrange = 5,
|
||||
GhastlyYellow = 6,
|
||||
MagicPurple = 7,
|
||||
ToxicGreen = 8,
|
||||
ExoticPurple = 9,
|
||||
}
|
||||
impl EyeColor {
|
||||
pub fn light_rgb(self) -> Rgb<u8> {
|
||||
@ -508,35 +519,37 @@ impl EyeColor {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Accessory {
|
||||
Nothing,
|
||||
Some,
|
||||
Nothing = 0,
|
||||
Some = 1,
|
||||
}
|
||||
pub const ALL_ACCESSORIES: [Accessory; 2] = [Accessory::Nothing, Accessory::Some];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Skin {
|
||||
Pale,
|
||||
White,
|
||||
Tanned,
|
||||
Brown,
|
||||
TannedBrown,
|
||||
TannedDarkBrown,
|
||||
Iron,
|
||||
Steel,
|
||||
DanariOne,
|
||||
DanariTwo,
|
||||
DanariThree,
|
||||
DanariFour,
|
||||
ElfOne,
|
||||
ElfTwo,
|
||||
ElfThree,
|
||||
OrcOne,
|
||||
OrcTwo,
|
||||
OrcThree,
|
||||
UndeadOne,
|
||||
UndeadTwo,
|
||||
UndeadThree,
|
||||
Pale = 0,
|
||||
White = 1,
|
||||
Tanned = 2,
|
||||
Brown = 3,
|
||||
TannedBrown = 4,
|
||||
TannedDarkBrown = 5,
|
||||
Iron = 6,
|
||||
Steel = 7,
|
||||
DanariOne = 8,
|
||||
DanariTwo = 9,
|
||||
DanariThree = 10,
|
||||
DanariFour = 11,
|
||||
ElfOne = 12,
|
||||
ElfTwo = 13,
|
||||
ElfThree = 14,
|
||||
OrcOne = 15,
|
||||
OrcTwo = 16,
|
||||
OrcThree = 17,
|
||||
UndeadOne = 18,
|
||||
UndeadTwo = 19,
|
||||
UndeadThree = 20,
|
||||
}
|
||||
impl Skin {
|
||||
pub fn rgb(self) -> Rgb<u8> {
|
||||
|
@ -1,58 +1,59 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Body {
|
||||
Arrow,
|
||||
Bomb,
|
||||
Scarecrow,
|
||||
Cauldron,
|
||||
ChestVines,
|
||||
Chest,
|
||||
ChestDark,
|
||||
ChestDemon,
|
||||
ChestGold,
|
||||
ChestLight,
|
||||
ChestOpen,
|
||||
ChestSkull,
|
||||
Pumpkin,
|
||||
Pumpkin2,
|
||||
Pumpkin3,
|
||||
Pumpkin4,
|
||||
Pumpkin5,
|
||||
Campfire,
|
||||
LanternGround,
|
||||
LanternGroundOpen,
|
||||
LanternStanding2,
|
||||
LanternStanding,
|
||||
PotionBlue,
|
||||
PotionGreen,
|
||||
PotionRed,
|
||||
Crate,
|
||||
Tent,
|
||||
WindowSpooky,
|
||||
DoorSpooky,
|
||||
Anvil,
|
||||
Gravestone,
|
||||
Gravestone2,
|
||||
Bench,
|
||||
Chair,
|
||||
Chair2,
|
||||
Chair3,
|
||||
Table,
|
||||
Table2,
|
||||
Table3,
|
||||
Drawer,
|
||||
BedBlue,
|
||||
Carpet,
|
||||
Bedroll,
|
||||
CarpetHumanRound,
|
||||
CarpetHumanSquare,
|
||||
CarpetHumanSquare2,
|
||||
CarpetHumanSquircle,
|
||||
Pouch,
|
||||
CraftingBench,
|
||||
BoltFire,
|
||||
ArrowSnake,
|
||||
Arrow = 0,
|
||||
Bomb = 1,
|
||||
Scarecrow = 2,
|
||||
Cauldron = 3,
|
||||
ChestVines = 4,
|
||||
Chest = 5,
|
||||
ChestDark = 6,
|
||||
ChestDemon = 7,
|
||||
ChestGold = 8,
|
||||
ChestLight = 9,
|
||||
ChestOpen = 10,
|
||||
ChestSkull = 11,
|
||||
Pumpkin = 12,
|
||||
Pumpkin2 = 13,
|
||||
Pumpkin3 = 14,
|
||||
Pumpkin4 = 15,
|
||||
Pumpkin5 = 16,
|
||||
Campfire = 17,
|
||||
LanternGround = 18,
|
||||
LanternGroundOpen = 19,
|
||||
LanternStanding2 = 20,
|
||||
LanternStanding = 21,
|
||||
PotionBlue = 22,
|
||||
PotionGreen = 23,
|
||||
PotionRed = 24,
|
||||
Crate = 25,
|
||||
Tent = 26,
|
||||
WindowSpooky = 27,
|
||||
DoorSpooky = 28,
|
||||
Anvil = 29,
|
||||
Gravestone = 30,
|
||||
Gravestone2 = 31,
|
||||
Bench = 32,
|
||||
Chair = 33,
|
||||
Chair2 = 34,
|
||||
Chair3 = 35,
|
||||
Table = 36,
|
||||
Table2 = 37,
|
||||
Table3 = 38,
|
||||
Drawer = 39,
|
||||
BedBlue = 40,
|
||||
Carpet = 41,
|
||||
Bedroll = 42,
|
||||
CarpetHumanRound = 43,
|
||||
CarpetHumanSquare = 44,
|
||||
CarpetHumanSquare2 = 45,
|
||||
CarpetHumanSquircle = 46,
|
||||
Pouch = 47,
|
||||
CraftingBench = 48,
|
||||
BoltFire = 49,
|
||||
ArrowSnake = 50,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct Body {
|
||||
pub head_upper: HeadUpper,
|
||||
pub jaw: Jaw,
|
||||
@ -35,66 +36,77 @@ impl Body {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum HeadUpper {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS_UPPER: [HeadUpper; 1] = [HeadUpper::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Jaw {
|
||||
Default,
|
||||
}
|
||||
const ALL_JAWS: [Jaw; 1] = [Jaw::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum HeadLower {
|
||||
Default,
|
||||
}
|
||||
const ALL_HEADS_LOWER: [HeadLower; 1] = [HeadLower::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Tail {
|
||||
Default,
|
||||
}
|
||||
const ALL_TAILS: [Tail; 1] = [Tail::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum TorsoBack {
|
||||
Default,
|
||||
}
|
||||
const ALL_TORSOS_BACK: [TorsoBack; 1] = [TorsoBack::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum TorsoMid {
|
||||
Default,
|
||||
}
|
||||
const ALL_TORSOS_MID: [TorsoMid; 1] = [TorsoMid::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Ears {
|
||||
Default,
|
||||
}
|
||||
const ALL_EARS: [Ears; 1] = [Ears::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootLF {
|
||||
Default,
|
||||
}
|
||||
const ALL_FEETS_LF: [FootLF; 1] = [FootLF::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootRF {
|
||||
Default,
|
||||
}
|
||||
const ALL_FEETS_RF: [FootRF; 1] = [FootRF::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootLB {
|
||||
Default,
|
||||
}
|
||||
const ALL_FEETS_LB: [FootLB; 1] = [FootLB::Default];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum FootRB {
|
||||
Default,
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![deny(unsafe_code)]
|
||||
#![type_length_limit = "1664759"]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(trait_alias, arbitrary_enum_discriminant)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
@ -62,9 +62,10 @@ crossbeam = "=0.7.2"
|
||||
hashbrown = { version = "0.6.2", features = ["serde", "nightly"] }
|
||||
chrono = "0.4.9"
|
||||
rust-argon2 = "0.5"
|
||||
bincode = "1.2"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
dispatch = "0.1.4"
|
||||
dispatch = "0.1.4"
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
winres = "0.1"
|
||||
|
@ -13,6 +13,7 @@ pub mod key_state;
|
||||
mod logging;
|
||||
pub mod menu;
|
||||
pub mod mesh;
|
||||
pub mod meta;
|
||||
pub mod render;
|
||||
pub mod scene;
|
||||
pub mod session;
|
||||
@ -24,13 +25,16 @@ pub mod window;
|
||||
// Reexports
|
||||
pub use crate::error::Error;
|
||||
|
||||
use crate::{audio::AudioFrontend, menu::main::MainMenuState, settings::Settings, window::Window};
|
||||
use crate::{
|
||||
audio::AudioFrontend, menu::main::MainMenuState, meta::Meta, settings::Settings, window::Window,
|
||||
};
|
||||
use log::{debug, error};
|
||||
use std::{mem, panic, str::FromStr};
|
||||
|
||||
/// A type used to store state that is shared between all play states.
|
||||
pub struct GlobalState {
|
||||
settings: Settings,
|
||||
meta: Meta,
|
||||
window: Window,
|
||||
audio: AudioFrontend,
|
||||
info_message: Option<String>,
|
||||
@ -97,6 +101,9 @@ fn main() {
|
||||
|
||||
logging::init(&settings, term_log_level, file_log_level);
|
||||
|
||||
// Load metadata
|
||||
let meta = Meta::load();
|
||||
|
||||
// Save settings to add new fields or create the file if it is not already there
|
||||
if let Err(err) = settings.save_to_file() {
|
||||
panic!("Failed to save settings: {:?}", err);
|
||||
@ -120,6 +127,7 @@ fn main() {
|
||||
audio,
|
||||
window: Window::new(&settings).expect("Failed to create window!"),
|
||||
settings,
|
||||
meta,
|
||||
info_message: None,
|
||||
};
|
||||
|
||||
@ -254,6 +262,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Save any unsaved changes to settings
|
||||
// Save any unsaved changes to settings and meta
|
||||
global_state.settings.save_to_file_warn();
|
||||
global_state.meta.save_to_file_warn();
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ impl PlayState for CharSelectionState {
|
||||
// Maintain the UI.
|
||||
let events = self
|
||||
.char_selection_ui
|
||||
.maintain(global_state.window.renderer_mut(), &self.client.borrow());
|
||||
.maintain(global_state, &self.client.borrow());
|
||||
for event in events {
|
||||
match event {
|
||||
ui::Event::Logout => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::window::{Event as WinEvent, PressState};
|
||||
use crate::{
|
||||
meta::CharacterData,
|
||||
render::{Consts, Globals, Renderer},
|
||||
ui::{
|
||||
img_ids::{BlankGraphic, ImageGraphic, VoxelGraphic, VoxelMs9Graphic},
|
||||
@ -8,7 +9,7 @@ use crate::{
|
||||
GlobalState,
|
||||
};
|
||||
use client::Client;
|
||||
use common::comp::humanoid;
|
||||
use common::comp::{self, humanoid};
|
||||
use conrod_core::{
|
||||
color,
|
||||
color::TRANSPARENT,
|
||||
@ -43,7 +44,6 @@ widget_ids! {
|
||||
divider,
|
||||
bodyrace_text,
|
||||
facialfeatures_text,
|
||||
char_delete,
|
||||
info_bg,
|
||||
info_frame,
|
||||
info_button_align,
|
||||
@ -61,10 +61,11 @@ widget_ids! {
|
||||
|
||||
|
||||
// Characters
|
||||
character_box_1,
|
||||
character_name_1,
|
||||
character_location_1,
|
||||
character_level_1,
|
||||
character_boxes[],
|
||||
character_deletes[],
|
||||
character_names[],
|
||||
character_locations[],
|
||||
character_levels[],
|
||||
|
||||
character_box_2,
|
||||
character_name_2,
|
||||
@ -242,7 +243,8 @@ const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
||||
const TEXT_COLOR_2: Color = Color::Rgba(1.0, 1.0, 1.0, 0.2);
|
||||
|
||||
enum InfoContent {
|
||||
Deletion,
|
||||
None,
|
||||
Deletion(usize),
|
||||
//Name,
|
||||
}
|
||||
|
||||
@ -254,7 +256,6 @@ pub struct CharSelectionUi {
|
||||
fonts: Fonts,
|
||||
character_creation: bool,
|
||||
info_content: InfoContent,
|
||||
info_window: bool,
|
||||
//deletion_confirmation: bool,
|
||||
pub character_name: String,
|
||||
pub character_body: humanoid::Body,
|
||||
@ -283,8 +284,7 @@ impl CharSelectionUi {
|
||||
imgs,
|
||||
rot_imgs,
|
||||
fonts,
|
||||
info_window: false,
|
||||
info_content: InfoContent::Deletion,
|
||||
info_content: InfoContent::None,
|
||||
//deletion_confirmation: false,
|
||||
character_creation: false,
|
||||
character_name: "Character Name".to_string(),
|
||||
@ -294,7 +294,7 @@ impl CharSelectionUi {
|
||||
}
|
||||
|
||||
// TODO: Split this into multiple modules or functions.
|
||||
fn update_layout(&mut self, client: &Client) -> Vec<Event> {
|
||||
fn update_layout(&mut self, global_state: &mut GlobalState, client: &Client) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
|
||||
let version = format!(
|
||||
@ -322,7 +322,8 @@ impl CharSelectionUi {
|
||||
.desc_text_color(TEXT_COLOR_2);
|
||||
|
||||
// Information Window
|
||||
if self.info_window {
|
||||
if let InfoContent::None = self.info_content {
|
||||
} else {
|
||||
Rectangle::fill_with([520.0, 150.0], color::rgba(0.0, 0.0, 0.0, 0.9))
|
||||
.mid_top_with_margin_on(ui_widgets.window, 300.0)
|
||||
.set(self.ids.info_bg, ui_widgets);
|
||||
@ -334,7 +335,8 @@ impl CharSelectionUi {
|
||||
.bottom_left_with_margins_on(self.ids.info_frame, 0.0, 0.0)
|
||||
.set(self.ids.info_button_align, ui_widgets);
|
||||
match self.info_content {
|
||||
InfoContent::Deletion => {
|
||||
InfoContent::None => unreachable!(),
|
||||
InfoContent::Deletion(character_index) => {
|
||||
Text::new("Permanently delete this Character?")
|
||||
.mid_top_with_margin_on(self.ids.info_frame, 40.0)
|
||||
.font_size(24)
|
||||
@ -354,29 +356,44 @@ impl CharSelectionUi {
|
||||
.set(self.ids.info_no, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
self.info_window = false
|
||||
self.info_content = InfoContent::None;
|
||||
};
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(150.0, 40.0)
|
||||
.right_from(self.ids.info_no, 100.0)
|
||||
//.hover_image(self.imgs.button_hover)
|
||||
//.press_image(self.imgs.button_press)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.label("Yes")
|
||||
.label_font_size(18)
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(Color::Rgba(1.0, 1.0, 1.0, 0.1))
|
||||
.label_font_size(18)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(self.ids.info_ok, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
//self.info_window = false
|
||||
// TODO -> Char Deletion Event
|
||||
self.info_content = InfoContent::None;
|
||||
global_state.meta.delete_character(character_index);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
// Character Selection /////////////////
|
||||
if !self.character_creation {
|
||||
// Set active body
|
||||
self.character_body = if let Some(character) = global_state
|
||||
.meta
|
||||
.characters
|
||||
.get(global_state.meta.selected_character)
|
||||
{
|
||||
match character.body {
|
||||
comp::Body::Humanoid(body) => Some(body.clone()),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.unwrap_or_else(|| humanoid::Body::random());
|
||||
|
||||
// Background for Server Frame
|
||||
Rectangle::fill_with([386.0, 95.0], color::rgba(0.0, 0.0, 0.0, 0.9))
|
||||
.top_left_with_margins_on(ui_widgets.window, 30.0, 30.0)
|
||||
@ -489,54 +506,96 @@ impl CharSelectionUi {
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.version, ui_widgets);
|
||||
|
||||
// 1st Character in Selection List
|
||||
if Button::image(self.imgs.selection)
|
||||
.top_left_with_margins_on(self.ids.charlist_alignment, 0.0, 2.0)
|
||||
.w_h(386.0, 80.0)
|
||||
.image_color(Color::Rgba(1.0, 1.0, 1.0, 0.8))
|
||||
.hover_image(self.imgs.selection)
|
||||
.press_image(self.imgs.selection)
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_y(conrod_core::position::Relative::Scalar(20.0))
|
||||
.set(self.ids.character_box_1, ui_widgets)
|
||||
.was_clicked()
|
||||
{}
|
||||
if Button::image(self.imgs.delete_button)
|
||||
.w_h(30.0 * 0.5, 30.0 * 0.5)
|
||||
.top_right_with_margins_on(self.ids.character_box_1, 15.0, 15.0)
|
||||
.hover_image(self.imgs.delete_button_hover)
|
||||
.press_image(self.imgs.delete_button_press)
|
||||
.with_tooltip(tooltip_manager, "Delete Character", "", &tooltip_human)
|
||||
.set(self.ids.char_delete, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
self.info_content = InfoContent::Deletion;
|
||||
self.info_window = true;
|
||||
// Resize character selection widgets
|
||||
let character_count = global_state.meta.characters.len();
|
||||
self.ids
|
||||
.character_boxes
|
||||
.resize(character_count, &mut ui_widgets.widget_id_generator());
|
||||
self.ids
|
||||
.character_deletes
|
||||
.resize(character_count, &mut ui_widgets.widget_id_generator());
|
||||
self.ids
|
||||
.character_names
|
||||
.resize(character_count, &mut ui_widgets.widget_id_generator());
|
||||
self.ids
|
||||
.character_levels
|
||||
.resize(character_count, &mut ui_widgets.widget_id_generator());
|
||||
self.ids
|
||||
.character_locations
|
||||
.resize(character_count, &mut ui_widgets.widget_id_generator());
|
||||
|
||||
// Character selection
|
||||
for (i, character) in global_state.meta.characters.iter().enumerate() {
|
||||
let character_box = Button::image(if global_state.meta.selected_character == i {
|
||||
self.imgs.selection_hover
|
||||
} else {
|
||||
self.imgs.selection
|
||||
});
|
||||
let character_box = if i == 0 {
|
||||
character_box.top_left_with_margins_on(self.ids.charlist_alignment, 0.0, 2.0)
|
||||
} else {
|
||||
character_box.down_from(self.ids.character_boxes[i - 1], 5.0)
|
||||
};
|
||||
if character_box
|
||||
.w_h(386.0, 80.0)
|
||||
.image_color(Color::Rgba(1.0, 1.0, 1.0, 0.8))
|
||||
.hover_image(self.imgs.selection_hover)
|
||||
.press_image(self.imgs.selection_press)
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_y(conrod_core::position::Relative::Scalar(20.0))
|
||||
.set(self.ids.character_boxes[i], ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
self.character_name = character.name.clone();
|
||||
self.character_body = match &character.body {
|
||||
comp::Body::Humanoid(body) => body.clone(),
|
||||
_ => panic!("Unsupported body type!"),
|
||||
};
|
||||
global_state.meta.selected_character = i;
|
||||
}
|
||||
if Button::image(self.imgs.delete_button)
|
||||
.w_h(30.0 * 0.5, 30.0 * 0.5)
|
||||
.top_right_with_margins_on(self.ids.character_boxes[i], 15.0, 15.0)
|
||||
.hover_image(self.imgs.delete_button_hover)
|
||||
.press_image(self.imgs.delete_button_press)
|
||||
.with_tooltip(tooltip_manager, "Delete Character", "", &tooltip_human)
|
||||
.set(self.ids.character_deletes[i], ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
self.info_content = InfoContent::Deletion(i);
|
||||
}
|
||||
Text::new(&character.name)
|
||||
.top_left_with_margins_on(self.ids.character_boxes[i], 6.0, 9.0)
|
||||
.font_size(19)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.character_names[i], ui_widgets);
|
||||
|
||||
Text::new("Level <n/a>")
|
||||
.down_from(self.ids.character_names[i], 4.0)
|
||||
.font_size(17)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.character_levels[i], ui_widgets);
|
||||
|
||||
Text::new("Uncanny Valley")
|
||||
.down_from(self.ids.character_levels[i], 4.0)
|
||||
.font_size(17)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.character_locations[i], ui_widgets);
|
||||
}
|
||||
Text::new("Test Character")
|
||||
.top_left_with_margins_on(self.ids.character_box_1, 6.0, 9.0)
|
||||
.font_size(19)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.character_name_1, ui_widgets);
|
||||
|
||||
Text::new("Level 1")
|
||||
.down_from(self.ids.character_name_1, 4.0)
|
||||
.font_size(17)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.character_level_1, ui_widgets);
|
||||
|
||||
Text::new("Uncanny Valley")
|
||||
.down_from(self.ids.character_level_1, 4.0)
|
||||
.font_size(17)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.character_location_1, ui_widgets);
|
||||
|
||||
// Create Character Button
|
||||
if Button::image(self.imgs.selection)
|
||||
.down_from(self.ids.character_box_1, 5.0)
|
||||
let create_char_button = Button::image(self.imgs.selection);
|
||||
|
||||
let create_char_button = if character_count > 0 {
|
||||
create_char_button.down_from(self.ids.character_boxes[character_count - 1], 5.0)
|
||||
} else {
|
||||
create_char_button.top_left_with_margins_on(self.ids.charlist_alignment, 0.0, 2.0)
|
||||
};
|
||||
|
||||
if create_char_button
|
||||
.w_h(386.0, 80.0)
|
||||
.hover_image(self.imgs.selection_hover)
|
||||
.press_image(self.imgs.selection_press)
|
||||
@ -549,6 +608,7 @@ impl CharSelectionUi {
|
||||
{
|
||||
self.character_creation = true;
|
||||
self.character_tool = Some(STARTER_SWORD);
|
||||
self.character_body = humanoid::Body::random();
|
||||
}
|
||||
}
|
||||
// Character_Creation //////////////////////////////////////////////////////////////////////
|
||||
@ -585,6 +645,10 @@ impl CharSelectionUi {
|
||||
{
|
||||
// TODO: Save character.
|
||||
self.character_creation = false;
|
||||
global_state.meta.add_character(CharacterData {
|
||||
name: self.character_name.clone(),
|
||||
body: comp::Body::Humanoid(self.character_body.clone()),
|
||||
});
|
||||
}
|
||||
// Character Name Input
|
||||
Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97))
|
||||
@ -1186,9 +1250,9 @@ impl CharSelectionUi {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) -> Vec<Event> {
|
||||
let events = self.update_layout(client);
|
||||
self.ui.maintain(renderer, None);
|
||||
pub fn maintain(&mut self, global_state: &mut GlobalState, client: &Client) -> Vec<Event> {
|
||||
let events = self.update_layout(global_state, client);
|
||||
self.ui.maintain(global_state.window.renderer_mut(), None);
|
||||
events
|
||||
}
|
||||
|
||||
|
@ -223,8 +223,9 @@ impl MainMenuUi {
|
||||
\n\
|
||||
The name you put in will be your character name ingame.\n\
|
||||
\n\
|
||||
As of now you can't save your characters.\n\
|
||||
Changing their appearance is possible though.";
|
||||
Character names and appearances will be saved on your computer.\n\
|
||||
\n\
|
||||
Levels/Items are not saved yet.";
|
||||
|
||||
// Tooltip
|
||||
let _tooltip = Tooltip::new({
|
||||
|
89
voxygen/src/meta.rs
Normal file
89
voxygen/src/meta.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use common::comp;
|
||||
use directories::ProjectDirs;
|
||||
use log::warn;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fs, io, path::PathBuf};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct CharacterData {
|
||||
pub name: String,
|
||||
pub body: comp::Body,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
#[repr(C)]
|
||||
pub struct Meta {
|
||||
pub characters: Vec<CharacterData>,
|
||||
pub selected_character: usize,
|
||||
}
|
||||
|
||||
impl Meta {
|
||||
pub fn delete_character(&mut self, index: usize) {
|
||||
self.characters.remove(index);
|
||||
if index < self.selected_character {
|
||||
self.selected_character -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_character(&mut self, data: CharacterData) {
|
||||
self.characters.push(data);
|
||||
}
|
||||
|
||||
pub fn load() -> Self {
|
||||
let path = Self::get_meta_path();
|
||||
|
||||
if let Ok(file) = fs::File::open(&path) {
|
||||
match bincode::deserialize_from(file) {
|
||||
Ok(s) => return s,
|
||||
Err(e) => {
|
||||
log::warn!("Failed to parse meta file! Fallback to default. {}", e);
|
||||
// Rename the corrupted settings file
|
||||
let mut new_path = path.to_owned();
|
||||
new_path.pop();
|
||||
new_path.push("meta.invalid.dat");
|
||||
if let Err(err) = std::fs::rename(path, new_path) {
|
||||
log::warn!("Failed to rename meta file. {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is reached if either:
|
||||
// - The file can't be opened (presumably it doesn't exist)
|
||||
// - Or there was an error parsing the file
|
||||
let default = Self::default();
|
||||
default.save_to_file_warn();
|
||||
default
|
||||
}
|
||||
|
||||
pub fn save_to_file_warn(&self) {
|
||||
if let Err(err) = self.save_to_file() {
|
||||
warn!("Failed to save settings: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_to_file(&self) -> std::io::Result<()> {
|
||||
let path = Self::get_meta_path();
|
||||
if let Some(dir) = path.parent() {
|
||||
fs::create_dir_all(dir)?;
|
||||
}
|
||||
bincode::serialize_into(fs::File::create(path)?, self)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_meta_path() -> PathBuf {
|
||||
if let Some(val) = std::env::var_os("VOXYGEN_CONFIG") {
|
||||
let meta = PathBuf::from(val).join("meta.dat");
|
||||
if meta.exists() || meta.parent().map(|x| x.exists()).unwrap_or(false) {
|
||||
return meta;
|
||||
}
|
||||
log::warn!("VOXYGEN_CONFIG points to invalid path.");
|
||||
}
|
||||
|
||||
let proj_dirs = ProjectDirs::from("net", "veloren", "voxygen")
|
||||
.expect("System's $HOME directory path not found!");
|
||||
proj_dirs.config_dir().join("meta").with_extension("dat")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user