1
0
Lixcraft/src/datatypes.rs
2022-03-02 21:58:17 +01:00

236 Zeilen
6.2 KiB
Rust

use std::fmt::{Formatter, Write};
use std::ops::{Deref, DerefMut};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{EnumAccess, Error, MapAccess, SeqAccess, Visitor};
use lixcraft_derive::Wrapper;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Wrapper)]
pub struct VarInt(pub i32);
impl From<VarInt> for usize {
fn from(v: VarInt) -> Self {
v.0 as usize
}
}
impl From<usize> for VarInt {
fn from(v: usize) -> Self {
VarInt(v as i32)
}
}
impl Serialize for VarInt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
let mut v = self.0 as u32;
let mut result = Vec::with_capacity(5);
loop {
if v & 0x80 == 0 {
result.push(v as u8);
return serializer.serialize_bytes(&result);
}
result.push((v as u8 & 0x7f) | 0x80);
v >>= 7;
}
}
}
impl<'de> Deserialize<'de> for VarInt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
let mut num_read = 0;
let mut result = 0;
loop {
let read = (&mut *deserializer).deserialize_u8(VarIntVisitor{})?;
let value = i32::from(read & 0b0111_1111);
result |= value.overflowing_shl(7 * num_read).0;
num_read += 1;
if num_read > 5 {
return Err(D::Error::custom("VarInt too large"));
}
if read & 0b1000_0000 == 0 {
break;
}
}
Ok(VarInt(result))
}
}
#[derive(Debug)]
pub enum NextState {
Status,
Login
}
impl Serialize for NextState {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
VarInt::from(match self {
NextState::Status => 1,
NextState::Login => 2
}).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for NextState {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
match VarInt::deserialize(deserializer)? {
VarInt(1) => Ok(NextState::Status),
VarInt(2) => Ok(NextState::Login),
_ => Err(D::Error::custom("Invalid NextState"))
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct StatusResponseVersion {
pub name: String,
pub protocol: i32
}
#[derive(Debug, Serialize, Deserialize)]
pub struct StatusResponseSample {
pub name: String,
pub id: String
}
#[derive(Debug, Serialize, Deserialize)]
pub struct StatusResponsePlayers {
pub max: i32,
pub online: i32,
pub sample: Vec<StatusResponseSample>
}
#[derive(Debug, Serialize, Deserialize)]
pub struct StatusResponseDescription {
pub text: String
}
#[derive(Debug)]
pub struct StatusResponse {
pub version: StatusResponseVersion,
pub players: StatusResponsePlayers,
pub description: StatusResponseDescription,
//#[serde(skip_serializing_if = "Option::is_none")]
pub favicon: Option<String>
}
impl Serialize for StatusResponse {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
serializer.serialize_str(&match serde_json::to_string(self) {
Ok(v) => v,
Err(_) => return Err(serde::ser::Error::custom("Could not serialize status response"))
})
}
}
impl<'de> Deserialize<'de> for StatusResponse {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
match String::deserialize(deserializer) {
Ok(json) => match serde_json::from_str(&json) {
Ok(v) => Ok(v),
Err(_) => Err(D::Error::custom("Could not parse json status response"))
},
Err(err) => Err(err)
}
}
}
#[derive(Debug, Serialize, Deserialize)]
//TODO: Serialize, Deserialize
pub enum Font {
Uniform, //minecraft:uniform
Alt, //minecraft:alt
Default //minecraft:default
}
#[derive(Debug, Serialize, Deserialize)]
pub enum ClickEventAction {
open_url,
run_command,
suggest_command,
change_page,
copy_to_clipboard
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ClickEvent {
action: ClickEventAction,
value: String
}
#[derive(Debug, Serialize, Deserialize)]
pub enum HoverEventAction {
show_text,
show_item,
show_entity
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HoverEvent {
action: HoverEventAction,
value: String //or Chat (Recursion!)
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SharedChat {
//#[serde(skip_serializing_if = "Option::is_none")]
bold: bool,
//#[serde(skip_serializing_if = "Option::is_none")]
italic: bool,
//#[serde(skip_serializing_if = "Option::is_none")]
underlined: bool,
//#[serde(skip_serializing_if = "Option::is_none")]
strikethrough: bool,
//#[serde(skip_serializing_if = "Option::is_none")]
obfuscated: bool,
//#[serde(skip_serializing_if = "Option::is_none")]
font: Font,
//#[serde(skip_serializing_if = "Option::is_none")]
color: String, //TODO Color code, format code or hex code
//#[serde(skip_serializing_if = "Option::is_none")]
insertion: String,
//#[serde(skip_serializing_if = "Option::is_none")]
clickEvent: ClickEvent,
//#[serde(skip_serializing_if = "Option::is_none")]
hoverEvent: HoverEvent,
//#[serde(skip_serializing_if = "Option::is_none")]
extra: Vec<Chat>
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Score {
name: String, //Or UUID
objective: String,
value: String
}
#[derive(Debug, Serialize, Deserialize)]
//TODO: Serialize, Deserialize
pub enum Chat {
StringComponent {
#[serde(flatten)]
options: SharedChat,
text: String
},
TranslationComponent {
#[serde(flatten)]
options: SharedChat,
translate: String //TODO Special strings
},
KeybindComponent {
#[serde(flatten)]
options: SharedChat,
keybind: String
},
ScoreComponent {
#[serde(flatten)]
options: SharedChat,
score: Score
},
SelectorComponent {
#[serde(flatten)]
options: SharedChat,
selector: String //TODO ominous
}
}