From a371aad05e6ee1e27c39320c31e9f1fb3abaa107 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Sat, 20 Aug 2022 15:20:27 +0300
Subject: [PATCH 1/3] Add /body command that allows you to switch body

---
 common/src/cmd.rs |  7 +++++++
 server/src/cmd.rs | 21 +++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/common/src/cmd.rs b/common/src/cmd.rs
index 96aea26498..ed8c986797 100644
--- a/common/src/cmd.rs
+++ b/common/src/cmd.rs
@@ -240,6 +240,7 @@ pub enum ServerChatCommand {
     Ban,
     BattleMode,
     BattleModeForce,
+    Body,
     Build,
     BuildAreaAdd,
     BuildAreaList,
@@ -365,6 +366,11 @@ impl ServerChatCommand {
                 None,
 
             ),
+            ServerChatCommand::Body => cmd(
+                vec![Enum("body", ENTITIES.clone(), Required)],
+                "Change your body to different species",
+                Some(Admin),
+            ),
             ServerChatCommand::BattleModeForce => cmd(
                 vec![Enum(
                     "battle mode",
@@ -720,6 +726,7 @@ impl ServerChatCommand {
             ServerChatCommand::Ban => "ban",
             ServerChatCommand::BattleMode => "battlemode",
             ServerChatCommand::BattleModeForce => "battlemode_force",
+            ServerChatCommand::Body => "body",
             ServerChatCommand::Build => "build",
             ServerChatCommand::BuildAreaAdd => "build_area_add",
             ServerChatCommand::BuildAreaList => "build_area_list",
diff --git a/server/src/cmd.rs b/server/src/cmd.rs
index 948d451959..ec01ab389b 100644
--- a/server/src/cmd.rs
+++ b/server/src/cmd.rs
@@ -129,6 +129,7 @@ fn do_command(
         ServerChatCommand::Ban => handle_ban,
         ServerChatCommand::BattleMode => handle_battlemode,
         ServerChatCommand::BattleModeForce => handle_battlemode_force,
+        ServerChatCommand::Body => handle_body,
         ServerChatCommand::Build => handle_build,
         ServerChatCommand::BuildAreaAdd => handle_build_area_add,
         ServerChatCommand::BuildAreaList => handle_build_area_list,
@@ -3704,3 +3705,23 @@ fn handle_lightning(
         .emit_now(Outcome::Lightning { pos });
     Ok(())
 }
+
+fn handle_body(
+    server: &mut Server,
+    _client: EcsEntity,
+    target: EcsEntity,
+    args: Vec<String>,
+    action: &ServerChatCommand,
+) -> CmdResult<()> {
+    if let Some(npc::NpcBody(_id, mut body)) = parse_cmd_args!(args, npc::NpcBody) {
+        let body = body();
+        let ecs = &server.state.ecs();
+        let mut bodies = ecs.write_storage::<comp::Body>();
+        if let Some(mut target_body) = bodies.get_mut(target) {
+            *target_body = body;
+        }
+        Ok(())
+    } else {
+        Err(action.help_string())
+    }
+}

From 6319dcfc22c1167212f1e6871b70785d1ea09304 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Sat, 20 Aug 2022 16:59:57 +0300
Subject: [PATCH 2/3] Add more components in /body

* Add mass
* Add density
* Add collider.
This one is strange as always, I don't know what's wrong, but debug hitbox
changes only after death. Real one seems to work.
---
 common/src/comp/body.rs | 19 ++++++++++++++++++-
 server/src/cmd.rs       |  9 ++++-----
 server/src/state_ext.rs | 30 +++++++++---------------------
 3 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs
index 53a7853fda..2c7ac05664 100644
--- a/common/src/comp/body.rs
+++ b/common/src/comp/body.rs
@@ -27,7 +27,7 @@ use specs::{Component, DerefFlaggedStorage};
 use strum::Display;
 use vek::*;
 
-use super::{BuffKind, Density, Mass};
+use super::{BuffKind, Collider, Density, Mass};
 
 make_case_elim!(
     body,
@@ -567,6 +567,23 @@ impl Body {
         }
     }
 
+    // Body collider
+    pub fn collider(&self) -> Collider {
+        if let Body::Ship(ship) = self {
+            ship.make_collider()
+        } else {
+            let (p0, p1, radius) = self.sausage();
+
+            Collider::CapsulePrism {
+                p0,
+                p1,
+                radius,
+                z_min: 0.0,
+                z_max: self.height(),
+            }
+        }
+    }
+
     // How far away other entities should try to be. Will be added upon the other
     // entity's spacing_radius. So an entity with 2.0 and an entity with 3.0 will
     // lead to that both entities will try to keep 5.0 units away from each
diff --git a/server/src/cmd.rs b/server/src/cmd.rs
index ec01ab389b..bc010776d8 100644
--- a/server/src/cmd.rs
+++ b/server/src/cmd.rs
@@ -3715,11 +3715,10 @@ fn handle_body(
 ) -> CmdResult<()> {
     if let Some(npc::NpcBody(_id, mut body)) = parse_cmd_args!(args, npc::NpcBody) {
         let body = body();
-        let ecs = &server.state.ecs();
-        let mut bodies = ecs.write_storage::<comp::Body>();
-        if let Some(mut target_body) = bodies.get_mut(target) {
-            *target_body = body;
-        }
+        insert_or_replace_component(server, target, body, "body")?;
+        insert_or_replace_component(server, target, body.mass(), "mass")?;
+        insert_or_replace_component(server, target, body.density(), "density")?;
+        insert_or_replace_component(server, target, body.collider(), "collider")?;
         Ok(())
     } else {
         Err(action.help_string())
diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs
index 237f891849..2dff0e15eb 100644
--- a/server/src/state_ext.rs
+++ b/server/src/state_ext.rs
@@ -241,10 +241,7 @@ impl StateExt for State {
             )
             .with(body.mass())
             .with(body.density())
-            .with(match body {
-                comp::Body::Ship(ship) => ship.make_collider(),
-                _ => capsule(&body),
-            })
+            .with(body.collider())
             .with(comp::Controller::default())
             .with(body)
             .with(comp::Energy::new(
@@ -275,7 +272,7 @@ impl StateExt for State {
             .with(comp::Ori::default())
             .with(body.mass())
             .with(body.density())
-            .with(capsule(&body))
+            .with(body.collider())
             .with(body)
     }
 
@@ -290,7 +287,7 @@ impl StateExt for State {
             .with(item_drop.orientation(&mut thread_rng()))
             .with(item_drop.mass())
             .with(item_drop.density())
-            .with(capsule(&body))
+            .with(body.collider())
             .with(body)
     }
 
@@ -352,7 +349,7 @@ impl StateExt for State {
         if projectile.is_point {
             projectile_base = projectile_base.with(comp::Collider::Point)
         } else {
-            projectile_base = projectile_base.with(capsule(&body))
+            projectile_base = projectile_base.with(body.collider())
         }
 
         projectile_base.with(projectile).with(body)
@@ -425,7 +422,10 @@ impl StateExt for State {
             .with(pos)
             .with(comp::Vel(Vec3::zero()))
             .with(comp::Ori::default())
-            .with(capsule(&object.into()))
+            .with({
+                let body: comp::Body = object.into();
+                body.collider()
+            })
             .with(comp::Body::Object(object))
             .with(comp::Mass(100.0))
             // .with(comp::Sticky)
@@ -577,7 +577,7 @@ impl StateExt for State {
             // and we call nothing that can delete it in any of the subsequent
             // commands, so we can assume that all of these calls succeed,
             // justifying ignoring the result of insertion.
-            self.write_component_ignore_entity_dead(entity, capsule(&body));
+            self.write_component_ignore_entity_dead(entity, body.collider());
             self.write_component_ignore_entity_dead(entity, body);
             self.write_component_ignore_entity_dead(entity, body.mass());
             self.write_component_ignore_entity_dead(entity, body.density());
@@ -1040,15 +1040,3 @@ fn send_to_group(g: &Group, ecs: &specs::World, msg: &comp::ChatMsg) {
         }
     }
 }
-
-fn capsule(body: &comp::Body) -> comp::Collider {
-    let (p0, p1, radius) = body.sausage();
-
-    comp::Collider::CapsulePrism {
-        p0,
-        p1,
-        radius,
-        z_min: 0.0,
-        z_max: body.height(),
-    }
-}

From 69cea513eedae66d1df8414c8e84b5e7503d8d35 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Sat, 20 Aug 2022 19:23:05 +0300
Subject: [PATCH 3/3] Make comments to be doc-comments

---
 common/src/comp/body.rs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs
index 2c7ac05664..af15ed8991 100644
--- a/common/src/comp/body.rs
+++ b/common/src/comp/body.rs
@@ -567,7 +567,7 @@ impl Body {
         }
     }
 
-    // Body collider
+    /// Body collider
     pub fn collider(&self) -> Collider {
         if let Body::Ship(ship) = self {
             ship.make_collider()
@@ -584,10 +584,10 @@ impl Body {
         }
     }
 
-    // How far away other entities should try to be. Will be added upon the other
-    // entity's spacing_radius. So an entity with 2.0 and an entity with 3.0 will
-    // lead to that both entities will try to keep 5.0 units away from each
-    // other.
+    /// How far away other entities should try to be. Will be added upon the
+    /// other entity's spacing_radius. So an entity with 2.0 and an entity
+    /// with 3.0 will lead to that both entities will try to keep 5.0 units
+    /// away from each other.
     pub fn spacing_radius(&self) -> f32 {
         self.max_radius()
             + match self {