Theme

alex/beta-minecraft-rust

Minecraft Beta 1.7.3 Rewrite

BRANCH main
main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
Download file

root / crates / server / src / level / tiles.rs

use common::inventory::tick_furnace;
use common::world::{Block, ChunkPos, TileEntity};

use super::Level;

impl Level {
    pub fn tick_tiles(&mut self) {
        let mut positions = std::mem::take(&mut self.tile_tick_buffer);
        positions.extend(self.ticking_tiles.iter().copied());
        for &position in &positions {
            match self.tile_entity(position[0], position[1], position[2]) {
                Some(TileEntity::Furnace { .. }) => self.tick_furnace(position),
                Some(TileEntity::MobSpawner { .. }) => self.tick_spawner(position),
                Some(TileEntity::Piston { .. }) => crate::blocks::tick_piston(self, position),
                _ => {}
            }
        }
        positions.clear();
        self.tile_tick_buffer = positions;
    }

    fn tick_furnace(&mut self, [x, y, z]: [i32; 3]) {
        let pos = ChunkPos::containing(x, z);
        let Some(chunk) = self.chunks.get_mut(&pos) else {
            return;
        };
        let Some(tile @ TileEntity::Furnace { .. }) =
            chunk.tile_entity_mut((x & 15) as usize, y as usize, (z & 15) as usize)
        else {
            return;
        };
        let state = |tile: &TileEntity| match *tile {
            TileEntity::Furnace {
                burn_time,
                items,
                cook_time,
                ..
            } => (burn_time > 0, items, cook_time),
            _ => unreachable!(),
        };
        let (was_burning, old_items, old_cook) = state(tile);
        tick_furnace(tile);
        let (burning, items, cook) = state(tile);
        if was_burning || burning || cook != old_cook || items != old_items {
            self.unsaved.insert(pos);
        }
        if was_burning != burning {
            // `BlockFurnace.updateFurnaceBlockState` keeps the same furnace
            let generation = self.tile_generation([x, y, z]);
            let tile = self.remove_tile_entity(x, y, z).unwrap();
            let metadata = self.metadata(x, y, z);
            let block = if burning {
                Block::LIT_FURNACE
            } else {
                Block::FURNACE
            };
            self.set_block_with_metadata_notify(x, y, z, block, metadata);
            self.set_tile_entity(x, y, z, tile);
            match generation {
                Some(generation) => self.tile_generations.insert([x, y, z], generation),
                None => self.tile_generations.remove(&[x, y, z]),
            };
        } else if items != old_items {
            self.mark(x, y, z);
        }
    }
}