mirror of
https://github.com/G2-Games/minecraft_alpha_server.git
synced 2025-04-18 23:03:00 -05:00
Worked on state. Added preliminary item and block lists.
This commit is contained in:
parent
e898dfa859
commit
81dc4ec3d9
6 changed files with 386 additions and 65 deletions
188
src/blocks_items.rs
Normal file
188
src/blocks_items.rs
Normal file
|
@ -0,0 +1,188 @@
|
|||
#[repr(i16)]
|
||||
pub enum Block {
|
||||
Unknown = -1,
|
||||
Stone = 1,
|
||||
Grass = 2,
|
||||
Dirt = 3,
|
||||
Cobblestone = 4,
|
||||
Planks = 5,
|
||||
Sapling = 6,
|
||||
Bedrock = 7,
|
||||
WaterStill = 8,
|
||||
WaterMoving = 9,
|
||||
LavaStill = 10,
|
||||
LavaMoving = 11,
|
||||
Sand = 12,
|
||||
Gravel = 13,
|
||||
OreGold = 14,
|
||||
OreIron = 15,
|
||||
OreCoal = 16,
|
||||
Wood = 17,
|
||||
Leaves = 18,
|
||||
Sponge = 19,
|
||||
Glass = 20,
|
||||
Cloth = 35,
|
||||
PlantYellow = 37,
|
||||
PlantRed = 38,
|
||||
MushroomBrown = 39,
|
||||
MushroomRed = 40,
|
||||
BlockGold = 41,
|
||||
BlockSteel = 42,
|
||||
StairDouble = 43,
|
||||
StairSingle = 44,
|
||||
Brick = 45,
|
||||
Tnt = 46,
|
||||
BookShelf = 47,
|
||||
CobblestoneMossy = 48,
|
||||
Obsidian = 49,
|
||||
TorchWood = 50,
|
||||
Fire = 51,
|
||||
MobSpawner = 52,
|
||||
StairCompactPlanks = 53,
|
||||
Crate = 54,
|
||||
RedstoneWire = 55,
|
||||
OreDiamond = 56,
|
||||
BlockDiamond = 57,
|
||||
Workbench = 58,
|
||||
Crops = 59,
|
||||
TilledField = 60,
|
||||
StoneOvenIdle = 61,
|
||||
StoneOvenActive = 62,
|
||||
SignPost = 63,
|
||||
DoorWood = 64,
|
||||
Ladder = 65,
|
||||
MinecartTrack = 66,
|
||||
StairCompactCobblestone = 67,
|
||||
SignWall = 68,
|
||||
Lever = 69,
|
||||
PressurePlateStone = 70,
|
||||
DoorSteel = 71,
|
||||
PressurePlatePlanks = 72,
|
||||
OreRedstone = 73,
|
||||
OreRedstoneGlowing = 74,
|
||||
TorchRedstoneIdle = 75,
|
||||
TorchRedstoneActive = 76,
|
||||
Button = 77,
|
||||
Snow = 78,
|
||||
BlockIce = 79,
|
||||
BlockSnow = 80,
|
||||
Cactus = 81,
|
||||
BlockClay = 82,
|
||||
Reed = 83,
|
||||
Jukebox = 84,
|
||||
Fence = 85,
|
||||
Pumpkin = 86,
|
||||
BloodStone = 87,
|
||||
SlowSand = 88,
|
||||
LightStone = 89,
|
||||
Portal = 90,
|
||||
PumpkinLantern = 91,
|
||||
}
|
||||
|
||||
#[repr(i16)]
|
||||
pub enum Item {
|
||||
Unknown = -1,
|
||||
ShovelSteel = 256,
|
||||
PickaxeSteel = 257,
|
||||
AxeSteel = 258,
|
||||
FlintAndSteel = 259,
|
||||
AppleRed = 260,
|
||||
Bow = 261,
|
||||
Arrow = 262,
|
||||
Coal = 263,
|
||||
Diamond = 264,
|
||||
IngotIron = 265,
|
||||
IngotGold = 266,
|
||||
SwordSteel = 267,
|
||||
SwordWood = 268,
|
||||
ShovelWood = 269,
|
||||
PickaxeWood = 270,
|
||||
AxeWood = 271,
|
||||
SwordStone = 272,
|
||||
ShovelStone = 273,
|
||||
PickaxeStone = 274,
|
||||
AxeStone = 275,
|
||||
SwordDiamond = 276,
|
||||
ShovelDiamond = 277,
|
||||
PickaxeDiamond = 278,
|
||||
AxeDiamond = 279,
|
||||
Stick = 280,
|
||||
BowlEmpty = 281,
|
||||
BowlSoup = 282,
|
||||
SwordGold = 283,
|
||||
ShovelGold = 284,
|
||||
PickaxeGold = 285,
|
||||
AxeGold = 286,
|
||||
Silk = 287,
|
||||
Feather = 288,
|
||||
Gunpowder = 289,
|
||||
HoeWood = 290,
|
||||
HoeStone = 291,
|
||||
HoeSteel = 292,
|
||||
HoeDiamond = 293,
|
||||
HoeGold = 294,
|
||||
Seeds = 295,
|
||||
Wheat = 296,
|
||||
Bread = 297,
|
||||
HelmetLeather = 298,
|
||||
PlateLeather = 299,
|
||||
LegsLeather = 300,
|
||||
BootsLeather = 301,
|
||||
HelmetChain = 302,
|
||||
PlateChain = 303,
|
||||
LegsChain = 304,
|
||||
BootsChain = 305,
|
||||
HelmetSteel = 306,
|
||||
PlateSteel = 307,
|
||||
LegsSteel = 308,
|
||||
BootsSteel = 309,
|
||||
HelmetDiamond = 310,
|
||||
PlateDiamond = 311,
|
||||
LegsDiamond = 312,
|
||||
BootsDiamond = 313,
|
||||
HelmetGold = 314,
|
||||
PlateGold = 315,
|
||||
LegsGold = 316,
|
||||
BootsGold = 317,
|
||||
Flint = 318,
|
||||
PorkRaw = 319,
|
||||
PorkCooked = 320,
|
||||
Painting = 321,
|
||||
AppleGold = 322,
|
||||
Sign = 323,
|
||||
DoorWood = 324,
|
||||
BucketEmpty = 325,
|
||||
BucketWater = 326,
|
||||
BucketLava = 327,
|
||||
MinecartEmpty = 328,
|
||||
Saddle = 329,
|
||||
DoorSteel = 330,
|
||||
Redstone = 331,
|
||||
Snowball = 332,
|
||||
Boat = 333,
|
||||
Leather = 334,
|
||||
BucketMilk = 335,
|
||||
Brick = 336,
|
||||
Clay = 337,
|
||||
Reed = 338,
|
||||
Paper = 339,
|
||||
Book = 340,
|
||||
SlimeBall = 341,
|
||||
MinecartCrate = 342,
|
||||
MinecartPowered = 343,
|
||||
Egg = 344,
|
||||
Compass = 345,
|
||||
FishingRod = 346,
|
||||
PocketSundial = 347,
|
||||
LightStoneDust = 348,
|
||||
FishRaw = 349,
|
||||
FishCooked = 350,
|
||||
Record13 = 2000,
|
||||
RecordCat = 2001,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
fn index() -> i16 {
|
||||
256
|
||||
}
|
||||
}
|
11
src/chunk.rs
11
src/chunk.rs
|
@ -47,13 +47,12 @@ const CHUNK_TOTAL_BLOCKS: usize = CHUNK_WIDTH_X * CHUNK_WIDTH_Z * CHUNK_HEIGHT_Y
|
|||
impl BlockArray {
|
||||
fn compress(self) -> Vec<u8> {
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
encoder.write(&self.blocks).unwrap();
|
||||
encoder.write(&self.metadata).unwrap();
|
||||
encoder.write(&self.block_light).unwrap();
|
||||
encoder.write(&self.sky_light).unwrap();
|
||||
let output_buf = encoder.finish().unwrap();
|
||||
encoder.write_all(&self.blocks).unwrap();
|
||||
encoder.write_all(&self.metadata).unwrap();
|
||||
encoder.write_all(&self.block_light).unwrap();
|
||||
encoder.write_all(&self.sky_light).unwrap();
|
||||
|
||||
output_buf
|
||||
encoder.finish().unwrap()
|
||||
}
|
||||
|
||||
pub fn new_air() -> Self {
|
||||
|
|
157
src/main.rs
157
src/main.rs
|
@ -4,31 +4,33 @@ mod chunk;
|
|||
mod position;
|
||||
mod state;
|
||||
mod player;
|
||||
mod blocks_items;
|
||||
|
||||
use std::{io::{self, Write}, net::{TcpListener, TcpStream}, sync::RwLock};
|
||||
use std::{io::{self, Write}, net::{TcpListener, TcpStream}, sync::{atomic::{self, AtomicI32}, Arc, RwLock}, thread};
|
||||
|
||||
use base16ct::lower::encode_string;
|
||||
use chunk::{BlockArray, MapChunk, PreChunk};
|
||||
use log::{info, warn};
|
||||
use log::{error, info, warn};
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt, BE};
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use byte_ops::ToBytes;
|
||||
use player::{DiggingStatus, PlayerBlockPlacement};
|
||||
use position::{PlayerLook, PlayerPosition, PlayerPositionAndLook};
|
||||
use state::PlayerState;
|
||||
use position::{PlayerLook, PlayerPosition, PlayerPositionLook};
|
||||
use state::{GameState, PlayerState};
|
||||
use utils::{MCString, ReadMCString, WriteMCString};
|
||||
use rand::random;
|
||||
|
||||
/// List of players.
|
||||
const PLAYER_LIST: RwLock<Vec<PlayerState>> = RwLock::new(Vec::new());
|
||||
|
||||
/// The current Entity ID. Incremented by one every time there is a new entity.
|
||||
const ENTITY_ID: RwLock<i32> = RwLock::new(0);
|
||||
///
|
||||
/// This value should rarely be accessed directly, and definitely never updated.
|
||||
static ENTITY_ID: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
/// Get an Entity ID and increment the global value by 1.
|
||||
#[inline]
|
||||
fn get_eid() -> i32 {
|
||||
let eid = ENTITY_ID.read().unwrap().clone();
|
||||
*ENTITY_ID.write().unwrap() += 1;
|
||||
let eid = ENTITY_ID.load(atomic::Ordering::Relaxed);
|
||||
ENTITY_ID.store(eid + 1, atomic::Ordering::Relaxed);
|
||||
|
||||
eid
|
||||
}
|
||||
|
@ -38,31 +40,76 @@ fn main() {
|
|||
.filter_level(log::LevelFilter::Debug)
|
||||
.init();
|
||||
|
||||
info!("Setting up game state");
|
||||
let game_state: Arc<RwLock<GameState>> = Arc::new(RwLock::new(GameState::new()));
|
||||
|
||||
let listener = TcpListener::bind("0.0.0.0:25565").unwrap();
|
||||
info!("Server started and listening on {}", listener.local_addr().unwrap());
|
||||
|
||||
for mut connection in listener.incoming().filter_map(|c| c.ok()) {
|
||||
info!("Player joined from {}", connection.peer_addr().unwrap());
|
||||
while let Some(cmd) = connection.read_u8().ok() {
|
||||
let command = Command::from_u8(cmd);
|
||||
if command.is_none() {
|
||||
info!("COMMAND: {command:?} (0x{cmd:02X?})");
|
||||
panic!("This command isn't implemented yet");
|
||||
}
|
||||
handle_command(&mut connection, command.unwrap()).unwrap();
|
||||
}
|
||||
warn!("Lost connection to client");
|
||||
let mut game_state = Arc::clone(&game_state);
|
||||
thread::spawn(move || {
|
||||
player_loop(
|
||||
&mut connection,
|
||||
&mut game_state,
|
||||
).unwrap();
|
||||
|
||||
info!("Connection dropped for {}", connection.peer_addr().unwrap());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<(), io::Error> {
|
||||
fn player_loop(
|
||||
mut connection: &mut TcpStream,
|
||||
game_state: &mut Arc<RwLock<GameState>>,
|
||||
) -> Result<(), io::Error> {
|
||||
let mut player_state = PlayerState::new_invalid();
|
||||
loop {
|
||||
if let Ok(cmd) = connection.read_u8() {
|
||||
let command = Command::from_u8(cmd);
|
||||
if command.is_none() {
|
||||
error!("COMMAND: {command:?} (0x{cmd:02X?})");
|
||||
panic!("This command isn't implemented yet");
|
||||
}
|
||||
|
||||
handle_command(
|
||||
&mut connection,
|
||||
command.unwrap(),
|
||||
&mut player_state,
|
||||
).unwrap();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if player_state.is_valid() {
|
||||
if game_state.read().unwrap().player_list().get(player_state.username()).is_some_and(|p| *p != player_state)
|
||||
|| game_state.read().unwrap().player_list().get(player_state.username()).is_none()
|
||||
{
|
||||
game_state.write()
|
||||
.unwrap()
|
||||
.player_list_mut()
|
||||
.insert(player_state.username().clone(), player_state.clone());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_command(
|
||||
mut connection: &mut TcpStream,
|
||||
command: Command,
|
||||
player_state: &mut PlayerState,
|
||||
) -> Result<(), io::Error> {
|
||||
match command {
|
||||
Command::Handshake => {
|
||||
let username = connection.read_mcstring()?;
|
||||
let random_number = random::<u128>();
|
||||
let random_hash = encode_string(md5::compute(random_number.to_le_bytes()).as_slice());
|
||||
|
||||
connection.write_u8(0x02)?;
|
||||
connection.write_u8(Command::Handshake as u8)?;
|
||||
connection.write_mcstring(&MCString::try_from(random_hash).unwrap())?;
|
||||
|
||||
info!("Handshake with {username} successful");
|
||||
|
@ -75,20 +122,14 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
let _map_seed = connection.read_i64::<BE>()?;
|
||||
let _dimension = connection.read_i8()?;
|
||||
|
||||
// Return a successful login packet to the client
|
||||
let eid = get_eid();
|
||||
let login_packet = ServerLoginPacket {
|
||||
entity_id: eid,
|
||||
unknown1: MCString::default(),
|
||||
unknown2: MCString::default(),
|
||||
map_seed: 0,
|
||||
dimension: 0,
|
||||
};
|
||||
let login_packet = ServerLoginPacket::new(eid, 0, 0);
|
||||
connection.write_u8(Command::Login as u8).unwrap();
|
||||
connection.write(&login_packet.to_bytes())?;
|
||||
|
||||
PLAYER_LIST.write().unwrap().push(PlayerState::new(username.to_string(), eid));
|
||||
connection.write_all(&login_packet.to_bytes())?;
|
||||
|
||||
info!("{username} logged in. Protocol version {protocol_version}");
|
||||
*player_state = PlayerState::new(username.to_string(), eid);
|
||||
|
||||
for i in -10..10 {
|
||||
for o in -10..10 {
|
||||
|
@ -105,15 +146,15 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
|
||||
connection.write_u8(Command::SpawnPosition as u8)?;
|
||||
connection.write_u32::<BE>(0)?;
|
||||
connection.write_u32::<BE>(70)?;
|
||||
connection.write_u32::<BE>(0)?;
|
||||
connection.write_u32::<BE>(0)?;
|
||||
|
||||
let playerpos = PlayerPositionAndLook {
|
||||
let playerpos = PlayerPositionLook {
|
||||
position: PlayerPosition {
|
||||
position_x: 1.0,
|
||||
position_x: 0.5,
|
||||
stance: 0.0,
|
||||
position_y: 9.63,
|
||||
position_z: 1.0,
|
||||
position_z: 0.5,
|
||||
},
|
||||
look: PlayerLook {
|
||||
yaw: 0.0,
|
||||
|
@ -124,19 +165,28 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
connection.write_all(&playerpos.to_bytes())?;
|
||||
},
|
||||
Command::ChatMessage => {
|
||||
info!("Chat Message Recieved: {}", connection.read_mcstring().unwrap());
|
||||
let message = connection.read_mcstring().unwrap();
|
||||
info!("Chat Message Recieved: {message}");
|
||||
}
|
||||
Command::Player => {
|
||||
connection.read_u8()?;
|
||||
},
|
||||
Command::PlayerLook => {
|
||||
let _look = PlayerLook::from_bytes(&mut connection);
|
||||
let look = PlayerLook::from_bytes(&mut connection);
|
||||
player_state.set_look(look);
|
||||
}
|
||||
Command::PlayerPosition => {
|
||||
let _pos = PlayerPosition::from_bytes(&mut connection);
|
||||
let pos = PlayerPosition::from_bytes(&mut connection);
|
||||
player_state.set_position(pos);
|
||||
}
|
||||
Command::PlayerPositionAndLook => {
|
||||
let _poslook = PlayerPositionAndLook::from_bytes(&mut connection);
|
||||
let poslook = PlayerPositionLook::from_bytes(&mut connection);
|
||||
player_state.set_look(poslook.look);
|
||||
player_state.set_position(poslook.position);
|
||||
}
|
||||
Command::HoldingChange => {
|
||||
let _unused = connection.read_i32::<BE>()?;
|
||||
let block_id = connection.read_i16::<BE>()?;
|
||||
}
|
||||
Command::PlayerDigging => {
|
||||
let _status = DiggingStatus::from_u8(connection.read_u8()?).unwrap();
|
||||
|
@ -147,12 +197,10 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
}
|
||||
Command::PlayerBlockPlacement => {
|
||||
let _status = PlayerBlockPlacement::from_bytes(&mut connection);
|
||||
dbg!(_status);
|
||||
}
|
||||
Command::ArmAnimation => {
|
||||
Command::Animation => {
|
||||
let _eid = connection.read_i32::<BE>()?;
|
||||
let _animate = connection.read_u8()? != 0;
|
||||
dbg!(_animate);
|
||||
let _animate = connection.read_u8()?;
|
||||
}
|
||||
Command::Disconnect => {
|
||||
let disconnect_string = connection.read_mcstring()?;
|
||||
|
@ -160,12 +208,12 @@ fn handle_command(mut connection: &mut TcpStream, command: Command) -> Result<()
|
|||
connection.shutdown(std::net::Shutdown::Both)?;
|
||||
}
|
||||
Command::KeepAlive => {
|
||||
let _ = connection.write_u8(0x00);
|
||||
connection.write_u8(Command::KeepAlive as u8)?;
|
||||
}
|
||||
Command::UpdateHealth => {
|
||||
connection.read_u8()?;
|
||||
}
|
||||
c => unimplemented!("This command ({c:?}) is probably `Server -> Client` only")
|
||||
c => unimplemented!("This command ({c:?}) is probably `Server -> Client` only; thus it is unimplemented for the other way around!")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -190,9 +238,26 @@ enum Command {
|
|||
PlayerPositionAndLook = 0x0D,
|
||||
PlayerDigging = 0x0E,
|
||||
PlayerBlockPlacement = 0x0F,
|
||||
ArmAnimation = 0x12,
|
||||
HoldingChange = 0x10,
|
||||
AddToInventory = 0x11,
|
||||
Animation = 0x12,
|
||||
NamedEntitySpawn = 0x14,
|
||||
PickupSpawn = 0x15,
|
||||
CollectItem = 0x16,
|
||||
AddObject = 0x17,
|
||||
MobSpawn = 0x18,
|
||||
EntityVelocity = 0x1C,
|
||||
DestroyEntity = 0x1D,
|
||||
Entity = 0x1E,
|
||||
EntityRelativeMove = 0x1F,
|
||||
EntityLook = 0x20,
|
||||
EntityLookAndRelativeMove = 0x21,
|
||||
EntityTeleport = 0x22,
|
||||
AttachEntity = 0x27,
|
||||
PreChunk = 0x32,
|
||||
MapChunk = 0x33,
|
||||
BlockChange = 0x35,
|
||||
ComplexEntities = 0x3B,
|
||||
Disconnect = 0xFF,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::io::Read;
|
||||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt, BE};
|
||||
use byteorder::{ReadBytesExt, BE};
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@ use byteorder::{ReadBytesExt, WriteBytesExt, BE};
|
|||
|
||||
use crate::byte_ops::ToBytes;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PlayerPositionAndLook {
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct PlayerPositionLook {
|
||||
pub position: PlayerPosition,
|
||||
pub look: PlayerLook,
|
||||
}
|
||||
|
||||
impl ToBytes for PlayerPositionAndLook {
|
||||
impl ToBytes for PlayerPositionLook {
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
fn to_bytes(self) -> Self::Bytes {
|
||||
|
@ -27,7 +27,7 @@ impl ToBytes for PlayerPositionAndLook {
|
|||
}
|
||||
}
|
||||
|
||||
impl PlayerPositionAndLook {
|
||||
impl PlayerPositionLook {
|
||||
pub fn from_bytes<R: Read>(stream: &mut R) -> Self {
|
||||
let position_x = stream.read_f64::<BE>().unwrap();
|
||||
let position_y = stream.read_f64::<BE>().unwrap();
|
||||
|
@ -54,7 +54,7 @@ impl PlayerPositionAndLook {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct PlayerPosition {
|
||||
pub position_x: f64,
|
||||
pub position_y: f64,
|
||||
|
@ -95,7 +95,7 @@ impl PlayerPosition {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct PlayerLook {
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
|
|
81
src/state.rs
81
src/state.rs
|
@ -1,16 +1,36 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::{
|
||||
chunk::MapChunk, position::{PlayerLook, PlayerPosition},
|
||||
chunk::{BlockType, MapChunk},
|
||||
position::{PlayerLook, PlayerPosition, PlayerPositionLook},
|
||||
};
|
||||
|
||||
pub struct GameState {
|
||||
|
||||
player_list: BTreeMap<String, PlayerState>,
|
||||
}
|
||||
|
||||
impl GameState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
player_list: BTreeMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn player_list(&self) -> &BTreeMap<String, PlayerState> {
|
||||
&self.player_list
|
||||
}
|
||||
|
||||
pub fn player_list_mut(&mut self) -> &mut BTreeMap<String, PlayerState> {
|
||||
&mut self.player_list
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct PlayerState {
|
||||
eid: i32,
|
||||
username: String,
|
||||
position: PlayerPosition,
|
||||
look: PlayerLook,
|
||||
holding: i16,
|
||||
position_look: PlayerPositionLook,
|
||||
}
|
||||
|
||||
impl PlayerState {
|
||||
|
@ -19,10 +39,59 @@ impl PlayerState {
|
|||
Self {
|
||||
eid,
|
||||
username,
|
||||
position: PlayerPosition::default(),
|
||||
look: PlayerLook::default(),
|
||||
holding: -1,
|
||||
position_look: PlayerPositionLook::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_invalid() -> Self {
|
||||
Self {
|
||||
eid: -1,
|
||||
username: String::new(),
|
||||
holding: -1,
|
||||
position_look: PlayerPositionLook::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
if self.eid >= 0 && self.username != String::new() {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn username(&self) -> &String {
|
||||
&self.username
|
||||
}
|
||||
|
||||
pub fn look(&self) -> &PlayerLook {
|
||||
&self.position_look.look
|
||||
}
|
||||
|
||||
pub fn position(&self) -> &PlayerPosition {
|
||||
&self.position_look.position
|
||||
}
|
||||
|
||||
pub fn position_look(&self) -> &PlayerPositionLook {
|
||||
&self.position_look
|
||||
}
|
||||
|
||||
pub fn holding(&self) -> &BlockType {
|
||||
&self.holding
|
||||
}
|
||||
|
||||
pub fn set_position(&mut self, position: PlayerPosition) {
|
||||
self.position_look.position = position
|
||||
}
|
||||
|
||||
pub fn set_look(&mut self, look: PlayerLook) {
|
||||
self.position_look.look = look
|
||||
}
|
||||
|
||||
pub fn set_holding(&mut self, holding: i16) {
|
||||
self.holding = holding
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WorldState {
|
||||
|
|
Loading…
Reference in a new issue