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 / dedicated / admin.rs

use std::collections::BTreeSet;
use std::fs;
use std::net::IpAddr;
use std::path::{Path, PathBuf};

/// One of the lower-case name lists of `ServerConfigurationManager`, one entry per line.
pub struct List {
    path: PathBuf,
    entries: BTreeSet<String>,
}

impl List {
    fn load(path: PathBuf, what: &str) -> Self {
        let entries = match fs::read_to_string(&path) {
            Ok(text) => text
                .lines()
                .map(|line| line.trim().to_lowercase())
                .filter(|line| !line.is_empty())
                .collect(),
            Err(error) => {
                tracing::warn!("Failed to load {what}: {error}");
                BTreeSet::new()
            }
        };
        let list = Self { path, entries };
        list.save();
        list
    }

    fn save(&self) {
        let text: String = self.entries.iter().map(|e| format!("{e}\n")).collect();
        if let Err(error) = fs::write(&self.path, text) {
            tracing::warn!("Failed to save {}: {error}", self.path.display());
        }
    }

    pub fn contains(&self, entry: &str) -> bool {
        self.entries.contains(&entry.trim().to_lowercase())
    }

    pub fn add(&mut self, entry: &str) {
        self.entries.insert(entry.to_lowercase());
        self.save();
    }

    pub fn remove(&mut self, entry: &str) {
        self.entries.remove(&entry.to_lowercase());
        self.save();
    }

    pub fn reload(&mut self, what: &str) {
        *self = Self::load(std::mem::take(&mut self.path), what);
    }

    pub fn iter(&self) -> impl Iterator<Item = &str> {
        self.entries.iter().map(String::as_str)
    }
}

/// The persistent admission and operator lists.
pub struct Admin {
    pub banned: List,
    pub banned_ips: List,
    pub ops: List,
    pub whitelist: List,
    pub whitelist_enforced: bool,
}

impl Admin {
    pub fn load(dir: &Path, whitelist_enforced: bool) -> Self {
        Self {
            banned: List::load(dir.join("banned-players.txt"), "ban list"),
            banned_ips: List::load(dir.join("banned-ips.txt"), "ip ban list"),
            ops: List::load(dir.join("ops.txt"), "ops list"),
            whitelist: List::load(dir.join("white-list.txt"), "white-list"),
            whitelist_enforced,
        }
    }

    /// `ServerConfigurationManager.login`: why the player may not join, if so.
    pub fn refusal(&self, name: &str, address: IpAddr) -> Option<&'static str> {
        if self.banned.contains(name) {
            Some("You are banned from this server!")
        } else if self.whitelist_enforced
            && !self.ops.contains(name)
            && !self.whitelist.contains(name)
        {
            Some("You are not white-listed on this server!")
        } else if self.banned_ips.contains(&address.to_string()) {
            Some("Your IP address is banned from this server!")
        } else {
            None
        }
    }
}