diff --git a/server/src/cmd.rs b/server/src/cmd.rs
index f631b728f6..1ef7b2d810 100644
--- a/server/src/cmd.rs
+++ b/server/src/cmd.rs
@@ -3307,7 +3307,7 @@ fn handle_battlemode(
     let time = ecs.read_resource::<Time>();
     let settings = ecs.read_resource::<Settings>();
     if let Some(mode) = parse_args!(args, String) {
-        if !settings.battle_mode.allow_choosing() {
+        if !settings.gameplay.battle_mode.allow_choosing() {
             return Err("Command disabled in server settings".to_owned());
         }
 
@@ -3378,7 +3378,7 @@ fn handle_battlemode(
             "Error!"
         })?;
         let mut msg = format!("Current battle mode: {:?}.", player.battle_mode);
-        if settings.battle_mode.allow_choosing() {
+        if settings.gameplay.battle_mode.allow_choosing() {
             msg.push_str(" Possible to change.");
         } else {
             msg.push_str(" Global.");
@@ -3408,7 +3408,7 @@ fn handle_battlemode_force(
 ) -> CmdResult<()> {
     let ecs = server.state.ecs();
     let settings = ecs.read_resource::<Settings>();
-    if !settings.battle_mode.allow_choosing() {
+    if !settings.gameplay.battle_mode.allow_choosing() {
         return Err("Command disabled in server settings".to_owned());
     }
     let mode = parse_args!(args, String).ok_or_else(|| action.help_string())?;
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index df820db1a7..985c7f10ed 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -654,6 +654,7 @@ pub fn handle_respawn(server: &Server, entity: EcsEntity) {
 pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, owner: Option<Uid>) {
     // Go through all other entities
     let ecs = &server.state.ecs();
+    let settings = server.settings();
     let server_eventbus = ecs.read_resource::<EventBus<ServerEvent>>();
     let time = ecs.read_resource::<Time>();
     let owner_entity = owner.and_then(|uid| {
@@ -780,7 +781,9 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
                 let mut block_change = ecs.write_resource::<BlockChange>();
                 for block_pos in touched_blocks {
                     if let Ok(block) = terrain.get(block_pos) {
-                        if !matches!(block.kind(), BlockKind::Lava | BlockKind::GlowingRock) {
+                        if !matches!(block.kind(), BlockKind::Lava | BlockKind::GlowingRock)
+                            && settings.gameplay.explosion_burn_marks
+                        {
                             let diff2 = block_pos.map(|b| b as f32).distance_squared(pos);
                             let fade = (1.0 - diff2 / color_range.powi(2)).max(0.0);
                             if let Some(mut color) = block.get_color() {
diff --git a/server/src/settings.rs b/server/src/settings.rs
index ad17a09837..ecabef5284 100644
--- a/server/src/settings.rs
+++ b/server/src/settings.rs
@@ -43,6 +43,10 @@ pub enum ServerBattleMode {
     PerPlayer { default: BattleMode },
 }
 
+impl Default for ServerBattleMode {
+    fn default() -> Self { Self::Global(BattleMode::PvP) }
+}
+
 impl ServerBattleMode {
     pub fn allow_choosing(&self) -> bool {
         match self {
@@ -71,6 +75,26 @@ pub enum Protocol {
     },
 }
 
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct GameplaySettings {
+    #[serde(default)]
+    pub battle_mode: ServerBattleMode,
+    #[serde(default)]
+    pub safe_spawn: bool,
+    #[serde(default)]
+    pub explosion_burn_marks: bool,
+}
+
+impl Default for GameplaySettings {
+    fn default() -> Self {
+        Self {
+            battle_mode: ServerBattleMode::default(),
+            safe_spawn: false,
+            explosion_burn_marks: true,
+        }
+    }
+}
+
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub enum CalendarMode {
     None,
@@ -102,7 +126,6 @@ pub struct Settings {
     pub auth_server_address: Option<String>,
     pub max_players: usize,
     pub world_seed: u32,
-    pub battle_mode: ServerBattleMode,
     pub server_name: String,
     pub start_time: f64,
     /// When set to None, loads the default map file (if available); otherwise,
@@ -113,7 +136,6 @@ pub struct Settings {
     pub max_player_group_size: u32,
     pub client_timeout: Duration,
     pub spawn_town: Option<String>,
-    pub safe_spawn: bool,
     pub max_player_for_kill_broadcast: Option<usize>,
     pub calendar_mode: CalendarMode,
 
@@ -121,6 +143,9 @@ pub struct Settings {
     /// removed at *any time* with no migration.
     #[serde(default, skip_serializing)]
     pub experimental_terrain_persistence: bool,
+
+    #[serde(default)]
+    pub gameplay: GameplaySettings,
 }
 
 impl Default for Settings {
@@ -139,7 +164,6 @@ impl Default for Settings {
             world_seed: DEFAULT_WORLD_SEED,
             server_name: "Veloren Alpha".into(),
             max_players: 100,
-            battle_mode: ServerBattleMode::Global(BattleMode::PvP),
             start_time: 9.0 * 3600.0,
             map_file: None,
             max_view_distance: Some(65),
@@ -148,9 +172,9 @@ impl Default for Settings {
             calendar_mode: CalendarMode::Auto,
             client_timeout: Duration::from_secs(40),
             spawn_town: None,
-            safe_spawn: true,
             max_player_for_kill_broadcast: None,
             experimental_terrain_persistence: false,
+            gameplay: GameplaySettings::default(),
         }
     }
 }
@@ -229,7 +253,6 @@ impl Settings {
             max_players: 100,
             start_time: 9.0 * 3600.0,
             max_view_distance: None,
-            safe_spawn: false,
             client_timeout: Duration::from_secs(180),
             ..load // Fill in remaining fields from server_settings.ron.
         }
diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs
index da4588e9a3..d3057bd6b4 100644
--- a/server/src/state_ext.rs
+++ b/server/src/state_ext.rs
@@ -635,7 +635,7 @@ impl StateExt for State {
                     // but without this code, character gets battle_mode from
                     // another character on this account.
                     let settings = self.ecs().read_resource::<Settings>();
-                    let mode = settings.battle_mode.default_mode();
+                    let mode = settings.gameplay.battle_mode.default_mode();
                     if let Some(mut player_info) = players.get_mut(entity) {
                         player_info.battle_mode = mode;
                         player_info.last_battlemode_change = None;
diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs
index dc9c0cc9e5..5c8fe41568 100644
--- a/server/src/sys/msg/register.rs
+++ b/server/src/sys/msg/register.rs
@@ -175,7 +175,7 @@ impl<'a> System<'a> for Sys {
                 // NOTE: this is just default value.
                 //
                 // It will be overwritten in ServerExt::update_character_data.
-                let battle_mode = read_data.settings.battle_mode.default_mode();
+                let battle_mode = read_data.settings.gameplay.battle_mode.default_mode();
                 let player = Player::new(username, battle_mode, uuid, None);
 
                 let admin = read_data.editable_settings.admins.get(&uuid);
diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs
index 7dda1c5a52..e1efa23541 100644
--- a/server/src/sys/terrain.rs
+++ b/server/src/sys/terrain.rs
@@ -223,7 +223,7 @@ impl<'a> System<'a> for Sys {
             }
 
             // Insert a safezone if chunk contains the spawn position
-            if server_settings.safe_spawn && is_spawn_chunk(key, *spawn_point, &terrain) {
+            if server_settings.gameplay.safe_spawn && is_spawn_chunk(key, *spawn_point, &terrain) {
                 server_emitter.emit(ServerEvent::CreateSafezone {
                     range: Some(SAFE_ZONE_RADIUS),
                     pos: Pos(spawn_point.0),