mirror of
https://github.com/zyllian/classics.git
synced 2025-01-18 11:47:14 -08:00
add block info and modify permission checking to use it
This commit is contained in:
parent
947fd1271f
commit
21217a3597
5 changed files with 189 additions and 8 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod block;
|
||||||
pub mod generation;
|
pub mod generation;
|
||||||
|
|
||||||
/// a classic level
|
/// a classic level
|
||||||
|
|
156
src/level/block.rs
Normal file
156
src/level/block.rs
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
use std::{collections::BTreeMap, sync::LazyLock};
|
||||||
|
|
||||||
|
use crate::player::PlayerType;
|
||||||
|
|
||||||
|
/// information about all blocks implemented
|
||||||
|
pub static BLOCK_INFO: LazyLock<BTreeMap<u8, BlockInfo>> = LazyLock::new(|| {
|
||||||
|
[
|
||||||
|
(0x00, BlockInfo::new("air").block_type(BlockType::NonSolid)),
|
||||||
|
(0x01, BlockInfo::new("stone")),
|
||||||
|
(0x02, BlockInfo::new("grass")),
|
||||||
|
(0x03, BlockInfo::new("dirt")),
|
||||||
|
(0x04, BlockInfo::new("cobblestone")),
|
||||||
|
(0x05, BlockInfo::new("planks")),
|
||||||
|
(
|
||||||
|
0x06,
|
||||||
|
BlockInfo::new("sapling").block_type(BlockType::NonSolid),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0x07,
|
||||||
|
BlockInfo::new("bedrock").perm(PlayerType::Operator, PlayerType::Operator),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0x08,
|
||||||
|
BlockInfo::new("water_flowing")
|
||||||
|
.block_type(BlockType::FluidFlowing { stationary: 0x09 })
|
||||||
|
.perm(PlayerType::Operator, PlayerType::Normal),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0x09,
|
||||||
|
BlockInfo::new("water_stationary")
|
||||||
|
.block_type(BlockType::FluidStationary { moving: 0x08 })
|
||||||
|
.perm(PlayerType::Operator, PlayerType::Normal),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0x0a,
|
||||||
|
BlockInfo::new("lava_flowing")
|
||||||
|
.block_type(BlockType::FluidFlowing { stationary: 0x0b })
|
||||||
|
.perm(PlayerType::Operator, PlayerType::Normal),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0x0b,
|
||||||
|
BlockInfo::new("lava_stationary")
|
||||||
|
.block_type(BlockType::FluidStationary { moving: 0x0a })
|
||||||
|
.perm(PlayerType::Operator, PlayerType::Normal),
|
||||||
|
),
|
||||||
|
(0x0c, BlockInfo::new("sand")),
|
||||||
|
(0x0d, BlockInfo::new("gravel")),
|
||||||
|
(0x0e, BlockInfo::new("gold_ore")),
|
||||||
|
(0x0f, BlockInfo::new("iron_ore")),
|
||||||
|
(0x10, BlockInfo::new("coal_ore")),
|
||||||
|
(0x11, BlockInfo::new("wood")),
|
||||||
|
(0x12, BlockInfo::new("leaves")),
|
||||||
|
(0x13, BlockInfo::new("sponge")),
|
||||||
|
(0x14, BlockInfo::new("glass")),
|
||||||
|
(0x15, BlockInfo::new("cloth_red")),
|
||||||
|
(0x16, BlockInfo::new("cloth_orange")),
|
||||||
|
(0x17, BlockInfo::new("cloth_yellow")),
|
||||||
|
(0x18, BlockInfo::new("cloth_chartreuse")),
|
||||||
|
(0x19, BlockInfo::new("cloth_green")),
|
||||||
|
(0x1a, BlockInfo::new("cloth_spring_green")),
|
||||||
|
(0x1b, BlockInfo::new("cloth_cyan")),
|
||||||
|
(0x1c, BlockInfo::new("cloth_capri")),
|
||||||
|
(0x1d, BlockInfo::new("cloth_ultramarine")),
|
||||||
|
(0x1e, BlockInfo::new("cloth_violet")),
|
||||||
|
(0x1f, BlockInfo::new("cloth_purple")),
|
||||||
|
(0x20, BlockInfo::new("cloth_magenta")),
|
||||||
|
(0x21, BlockInfo::new("cloth_rose")),
|
||||||
|
(0x22, BlockInfo::new("cloth_dark_gray")),
|
||||||
|
(0x23, BlockInfo::new("cloth_light_gray")),
|
||||||
|
(0x24, BlockInfo::new("cloth_white")),
|
||||||
|
(
|
||||||
|
0x25,
|
||||||
|
BlockInfo::new("flower").block_type(BlockType::NonSolid),
|
||||||
|
),
|
||||||
|
(0x26, BlockInfo::new("rose").block_type(BlockType::NonSolid)),
|
||||||
|
(
|
||||||
|
0x27,
|
||||||
|
BlockInfo::new("brown_mushroom").block_type(BlockType::NonSolid),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0x28,
|
||||||
|
BlockInfo::new("red_mushroom").block_type(BlockType::NonSolid),
|
||||||
|
),
|
||||||
|
(0x29, BlockInfo::new("gold_block")),
|
||||||
|
(0x2a, BlockInfo::new("iron_block")),
|
||||||
|
(0x2b, BlockInfo::new("double_slab")),
|
||||||
|
(0x2c, BlockInfo::new("slab").block_type(BlockType::Slab)),
|
||||||
|
(0x2d, BlockInfo::new("bricks")),
|
||||||
|
(0x2e, BlockInfo::new("tnt")),
|
||||||
|
(0x2f, BlockInfo::new("bookshelf")),
|
||||||
|
(0x30, BlockInfo::new("mossy_cobblestone")),
|
||||||
|
(0x31, BlockInfo::new("obsidian")),
|
||||||
|
]
|
||||||
|
.into()
|
||||||
|
});
|
||||||
|
|
||||||
|
/// map of block string ids to their byte ids
|
||||||
|
pub static BLOCK_STRING_ID_MAP: LazyLock<BTreeMap<&'static str, u8>> = LazyLock::new(|| {
|
||||||
|
BLOCK_INFO
|
||||||
|
.iter()
|
||||||
|
.map(|(id, info)| (info.str_id, *id))
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
|
/// information about a block type
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BlockInfo {
|
||||||
|
/// the block's string id
|
||||||
|
pub str_id: &'static str,
|
||||||
|
/// the type of block
|
||||||
|
pub block_type: BlockType,
|
||||||
|
/// permissions needed to place this block
|
||||||
|
pub place_permissions: PlayerType,
|
||||||
|
/// permissions needed to break this block (includes replacing fluids)
|
||||||
|
pub break_permissions: PlayerType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockInfo {
|
||||||
|
/// creates a new block info
|
||||||
|
pub const fn new(str_id: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
str_id,
|
||||||
|
block_type: BlockType::Solid,
|
||||||
|
place_permissions: PlayerType::Normal,
|
||||||
|
break_permissions: PlayerType::Normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sets the info's block type
|
||||||
|
pub const fn block_type(mut self, block_type: BlockType) -> Self {
|
||||||
|
self.block_type = block_type;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sets placement and breaking permissions for the info
|
||||||
|
pub const fn perm(mut self, place: PlayerType, brk: PlayerType) -> Self {
|
||||||
|
self.place_permissions = place;
|
||||||
|
self.break_permissions = brk;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// types of blocks
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum BlockType {
|
||||||
|
/// a regular solid block
|
||||||
|
Solid,
|
||||||
|
/// a block which has no collision
|
||||||
|
NonSolid,
|
||||||
|
/// a slab
|
||||||
|
Slab,
|
||||||
|
/// fluid which is actively flowing
|
||||||
|
FluidFlowing { stationary: u8 },
|
||||||
|
/// fluid which is stationary
|
||||||
|
FluidStationary { moving: u8 },
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(lazy_cell)]
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use server::{config::ServerConfig, Server};
|
use server::{config::ServerConfig, Server};
|
||||||
|
|
|
@ -31,7 +31,7 @@ pub struct Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// enum describing types of players
|
/// enum describing types of players
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum PlayerType {
|
pub enum PlayerType {
|
||||||
/// a normal player
|
/// a normal player
|
||||||
|
|
|
@ -9,7 +9,7 @@ use tokio::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
level::Level,
|
level::{block::BLOCK_INFO, Level},
|
||||||
packet::{
|
packet::{
|
||||||
client::ClientPacket, server::ServerPacket, PacketReader, PacketWriter, ARRAY_LENGTH,
|
client::ClientPacket, server::ServerPacket, PacketReader, PacketWriter, ARRAY_LENGTH,
|
||||||
},
|
},
|
||||||
|
@ -226,19 +226,41 @@ async fn handle_stream_inner(
|
||||||
} => {
|
} => {
|
||||||
let block_type = if mode == 0x00 { 0 } else { block_type };
|
let block_type = if mode == 0x00 { 0 } else { block_type };
|
||||||
let mut data = data.write().await;
|
let mut data = data.write().await;
|
||||||
|
let new_block_info = BLOCK_INFO.get(&block_type);
|
||||||
|
let mut cancel = new_block_info.is_none();
|
||||||
let block =
|
let block =
|
||||||
data.level.get_block(x as usize, y as usize, z as usize);
|
data.level.get_block(x as usize, y as usize, z as usize);
|
||||||
// check if bedrock
|
let block_info = BLOCK_INFO
|
||||||
// TODO: genericize this
|
.get(&block)
|
||||||
if (block == 0x07 || block_type == 0x07)
|
.expect("missing block information for block!");
|
||||||
&& data
|
|
||||||
|
// check if player has ability to place/break these blocks
|
||||||
|
if let Some(new_block_info) = new_block_info {
|
||||||
|
let player_type = data
|
||||||
.players
|
.players
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|p| {
|
.find_map(|p| {
|
||||||
(p.id == *own_id).then_some(p.player_type)
|
(p.id == *own_id).then_some(p.player_type)
|
||||||
})
|
})
|
||||||
.unwrap_or_default() != PlayerType::Operator
|
.unwrap_or_default();
|
||||||
{
|
if player_type < new_block_info.place_permissions {
|
||||||
|
cancel = true;
|
||||||
|
reply_queue.push_back(ServerPacket::Message {
|
||||||
|
player_id: -1,
|
||||||
|
message: "Not allowed to place this block."
|
||||||
|
.to_string(),
|
||||||
|
});
|
||||||
|
} else if player_type < block_info.break_permissions {
|
||||||
|
cancel = true;
|
||||||
|
reply_queue.push_back(ServerPacket::Message {
|
||||||
|
player_id: -1,
|
||||||
|
message: "Not allowed to break this block."
|
||||||
|
.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cancel {
|
||||||
reply_queue.push_back(ServerPacket::SetBlock {
|
reply_queue.push_back(ServerPacket::SetBlock {
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
|
Loading…
Add table
Reference in a new issue