Add Clientbound Player Info Update
Also adds support for Skins!
This commit is contained in:
parent
dbcb3c8052
commit
05977223e3
@ -39,6 +39,7 @@ Pumpkin is currently under heavy development.
|
|||||||
- [ ] World Borders
|
- [ ] World Borders
|
||||||
- [ ] World Saving
|
- [ ] World Saving
|
||||||
- Player
|
- Player
|
||||||
|
- [x] Player Skin
|
||||||
- [x] Player Client brand
|
- [x] Player Client brand
|
||||||
- [x] Player Teleport
|
- [x] Player Teleport
|
||||||
- [ ] Player Movement
|
- [ ] Player Movement
|
||||||
|
|||||||
@ -112,6 +112,7 @@ impl ByteBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn put_uuid(&mut self, v: uuid::Uuid) {
|
pub fn put_uuid(&mut self, v: uuid::Uuid) {
|
||||||
|
// thats the vanilla way
|
||||||
let pair = v.as_u64_pair();
|
let pair = v.as_u64_pair();
|
||||||
self.put_u64(pair.0);
|
self.put_u64(pair.0);
|
||||||
self.put_u64(pair.1);
|
self.put_u64(pair.1);
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
use serde::Deserialize;
|
use crate::{bytebuf::ByteBuffer, ClientPacket, Property, VarInt};
|
||||||
|
|
||||||
use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt};
|
|
||||||
|
|
||||||
pub struct CLoginDisconnect<'a> {
|
pub struct CLoginDisconnect<'a> {
|
||||||
reason: &'a str,
|
reason: &'a str,
|
||||||
@ -83,15 +81,6 @@ impl<'a> CLoginSuccess<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Debug)]
|
|
||||||
pub struct Property {
|
|
||||||
pub name: String,
|
|
||||||
// base 64
|
|
||||||
pub value: String,
|
|
||||||
// base 64
|
|
||||||
pub signature: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ClientPacket for CLoginSuccess<'a> {
|
impl<'a> ClientPacket for CLoginSuccess<'a> {
|
||||||
const PACKET_ID: VarInt = 0x02;
|
const PACKET_ID: VarInt = 0x02;
|
||||||
|
|
||||||
@ -102,6 +91,7 @@ impl<'a> ClientPacket for CLoginSuccess<'a> {
|
|||||||
p.put_string(&v.name);
|
p.put_string(&v.name);
|
||||||
p.put_string(&v.value);
|
p.put_string(&v.value);
|
||||||
// has signature ?
|
// has signature ?
|
||||||
|
// todo: for some reason we get "got too many bytes error when using a signature"
|
||||||
p.put_bool(false);
|
p.put_bool(false);
|
||||||
// p.put_option(&v.signature, |p,v| p.put_string(v));
|
// p.put_option(&v.signature, |p,v| p.put_string(v));
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::{bytebuf::ByteBuffer, text::Text, BitSet, ClientPacket, VarInt};
|
use crate::{bytebuf::ByteBuffer, text::Text, BitSet, ClientPacket, Property, VarInt};
|
||||||
|
|
||||||
pub struct SetHeldItem {
|
pub struct SetHeldItem {
|
||||||
slot: i8,
|
slot: i8,
|
||||||
@ -18,6 +18,65 @@ impl ClientPacket for SetHeldItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CPlayerInfoUpdate<'a> {
|
||||||
|
actions: i8,
|
||||||
|
players: &'a [Player<'a>],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Player<'a> {
|
||||||
|
pub uuid: uuid::Uuid,
|
||||||
|
pub actions: &'a [PlayerAction],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PlayerAction {
|
||||||
|
AddPlayer {
|
||||||
|
name: String,
|
||||||
|
properties: Vec<Property>,
|
||||||
|
},
|
||||||
|
InitializeChat(u8),
|
||||||
|
UpdateGameMode(u8),
|
||||||
|
UpdateListed(u8),
|
||||||
|
UpdateLatency(u8),
|
||||||
|
UpdateDisplayName(u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CPlayerInfoUpdate<'a> {
|
||||||
|
pub fn new(actions: i8, players: &'a [Player]) -> Self {
|
||||||
|
Self { actions, players }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ClientPacket for CPlayerInfoUpdate<'a> {
|
||||||
|
const PACKET_ID: VarInt = 0x3E;
|
||||||
|
|
||||||
|
fn write(&self, bytebuf: &mut ByteBuffer) {
|
||||||
|
bytebuf.put_i8(self.actions);
|
||||||
|
bytebuf.put_list::<Player>(self.players, |p, v| {
|
||||||
|
p.put_uuid(v.uuid);
|
||||||
|
for action in v.actions {
|
||||||
|
match action {
|
||||||
|
PlayerAction::AddPlayer { name, properties } => {
|
||||||
|
p.put_string(name);
|
||||||
|
p.put_list::<Property>(properties, |p, v| {
|
||||||
|
p.put_string(&v.name);
|
||||||
|
p.put_string(&v.value);
|
||||||
|
// has signature ?
|
||||||
|
// todo: for some reason we get "got too many bytes error when using a signature"
|
||||||
|
p.put_bool(false);
|
||||||
|
// todo signature
|
||||||
|
});
|
||||||
|
}
|
||||||
|
PlayerAction::InitializeChat(_) => todo!(),
|
||||||
|
PlayerAction::UpdateGameMode(_) => todo!(),
|
||||||
|
PlayerAction::UpdateListed(_) => todo!(),
|
||||||
|
PlayerAction::UpdateLatency(_) => todo!(),
|
||||||
|
PlayerAction::UpdateDisplayName(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CPlayerAbilities {
|
pub struct CPlayerAbilities {
|
||||||
flags: i8,
|
flags: i8,
|
||||||
flying_speed: f32,
|
flying_speed: f32,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use std::io::{self, Write};
|
|||||||
|
|
||||||
use bytebuf::ByteBuffer;
|
use bytebuf::ByteBuffer;
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
use serde::Serialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub mod bytebuf;
|
pub mod bytebuf;
|
||||||
@ -183,6 +183,16 @@ pub struct Sample {
|
|||||||
pub id: String, // uuid
|
pub id: String, // uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// basicly game profile
|
||||||
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
|
pub struct Property {
|
||||||
|
pub name: String,
|
||||||
|
// base 64
|
||||||
|
pub value: String,
|
||||||
|
// base 64
|
||||||
|
pub signature: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct KnownPack<'a> {
|
pub struct KnownPack<'a> {
|
||||||
pub namespace: &'a str,
|
pub namespace: &'a str,
|
||||||
pub id: &'a str,
|
pub id: &'a str,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::{net::IpAddr};
|
use std::net::IpAddr;
|
||||||
|
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use pumpkin_protocol::client::login::Property;
|
use pumpkin_protocol::Property;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use mio::{event::Event, Poll};
|
|||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
client::{
|
client::{
|
||||||
config::CPluginMessage,
|
config::CPluginMessage,
|
||||||
play::{CChunkDataUpdateLight, CGameEvent, CLogin},
|
play::{CChunkDataUpdateLight, CGameEvent, CLogin, CPlayerInfoUpdate, PlayerAction},
|
||||||
},
|
},
|
||||||
BitSet, PacketError, Players, Sample, StatusResponse, VarInt, VarInt32, Version,
|
BitSet, PacketError, Players, Sample, StatusResponse, VarInt, VarInt32, Version,
|
||||||
};
|
};
|
||||||
@ -129,6 +129,19 @@ impl Server {
|
|||||||
.unwrap_or_else(|e| client.kick(&e.to_string()));
|
.unwrap_or_else(|e| client.kick(&e.to_string()));
|
||||||
// teleport
|
// teleport
|
||||||
client.teleport(10.0, 500.0, 10.0, 10.0, 10.0);
|
client.teleport(10.0, 500.0, 10.0, 10.0, 10.0);
|
||||||
|
let gameprofile = client.gameprofile.as_ref().unwrap();
|
||||||
|
client
|
||||||
|
.send_packet(CPlayerInfoUpdate::new(
|
||||||
|
0x01,
|
||||||
|
&[pumpkin_protocol::client::play::Player {
|
||||||
|
uuid: gameprofile.id,
|
||||||
|
actions: &[PlayerAction::AddPlayer {
|
||||||
|
name: gameprofile.name.clone(),
|
||||||
|
properties: gameprofile.properties.clone(),
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
))
|
||||||
|
.unwrap_or_else(|e| client.kick(&e.to_string()));
|
||||||
|
|
||||||
// Start waiting for level chunks
|
// Start waiting for level chunks
|
||||||
client
|
client
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user