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 Saving
|
||||
- Player
|
||||
- [x] Player Skin
|
||||
- [x] Player Client brand
|
||||
- [x] Player Teleport
|
||||
- [ ] Player Movement
|
||||
|
||||
@ -112,6 +112,7 @@ impl ByteBuffer {
|
||||
}
|
||||
|
||||
pub fn put_uuid(&mut self, v: uuid::Uuid) {
|
||||
// thats the vanilla way
|
||||
let pair = v.as_u64_pair();
|
||||
self.put_u64(pair.0);
|
||||
self.put_u64(pair.1);
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt};
|
||||
use crate::{bytebuf::ByteBuffer, ClientPacket, Property, VarInt};
|
||||
|
||||
pub struct CLoginDisconnect<'a> {
|
||||
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> {
|
||||
const PACKET_ID: VarInt = 0x02;
|
||||
|
||||
@ -102,6 +91,7 @@ impl<'a> ClientPacket for CLoginSuccess<'a> {
|
||||
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);
|
||||
// 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 {
|
||||
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 {
|
||||
flags: i8,
|
||||
flying_speed: f32,
|
||||
|
||||
@ -2,7 +2,7 @@ use std::io::{self, Write};
|
||||
|
||||
use bytebuf::ByteBuffer;
|
||||
use bytes::Buf;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod bytebuf;
|
||||
@ -183,6 +183,16 @@ pub struct Sample {
|
||||
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 namespace: &'a str,
|
||||
pub id: &'a str,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::{net::IpAddr};
|
||||
use std::net::IpAddr;
|
||||
|
||||
use num_bigint::BigInt;
|
||||
use pumpkin_protocol::client::login::Property;
|
||||
use pumpkin_protocol::Property;
|
||||
use reqwest::StatusCode;
|
||||
use serde::Deserialize;
|
||||
use thiserror::Error;
|
||||
|
||||
@ -8,7 +8,7 @@ use mio::{event::Event, Poll};
|
||||
use pumpkin_protocol::{
|
||||
client::{
|
||||
config::CPluginMessage,
|
||||
play::{CChunkDataUpdateLight, CGameEvent, CLogin},
|
||||
play::{CChunkDataUpdateLight, CGameEvent, CLogin, CPlayerInfoUpdate, PlayerAction},
|
||||
},
|
||||
BitSet, PacketError, Players, Sample, StatusResponse, VarInt, VarInt32, Version,
|
||||
};
|
||||
@ -129,6 +129,19 @@ impl Server {
|
||||
.unwrap_or_else(|e| client.kick(&e.to_string()));
|
||||
// teleport
|
||||
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
|
||||
client
|
||||
|
||||
Loading…
Reference in New Issue
Block a user