Create pumpkin-text
This commit is contained in:
parent
5f3a4d34d1
commit
f122b47e50
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -1155,6 +1155,7 @@ dependencies = [
|
|||||||
"pumpkin-entity",
|
"pumpkin-entity",
|
||||||
"pumpkin-protocol",
|
"pumpkin-protocol",
|
||||||
"pumpkin-registry",
|
"pumpkin-registry",
|
||||||
|
"pumpkin-text",
|
||||||
"pumpkin-world",
|
"pumpkin-world",
|
||||||
"rand",
|
"rand",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@ -1194,12 +1195,12 @@ dependencies = [
|
|||||||
"aes",
|
"aes",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cfb8",
|
"cfb8",
|
||||||
"fastnbt 2.5.0 (git+https://github.com/owengage/fastnbt.git)",
|
|
||||||
"flate2",
|
"flate2",
|
||||||
"log",
|
"log",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"pumpkin-macros",
|
"pumpkin-macros",
|
||||||
|
"pumpkin-text",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"take_mut",
|
"take_mut",
|
||||||
@ -1217,6 +1218,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pumpkin-text"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"fastnbt 2.5.0 (git+https://github.com/owengage/fastnbt.git)",
|
||||||
|
"serde",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-world"
|
name = "pumpkin-world"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = [ "pumpkin-entity", "pumpkin-macros/", "pumpkin-protocol/", "pumpkin-registry/", "pumpkin-world", "pumpkin/" ]
|
members = [ "pumpkin-entity", "pumpkin-macros/", "pumpkin-protocol/", "pumpkin-registry/", "pumpkin-text", "pumpkin-world", "pumpkin/" ]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@ -4,8 +4,8 @@ version.workspace = true
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
pumpkin-macros = { path = "../pumpkin-macros" }
|
pumpkin-macros = { path = "../pumpkin-macros" }
|
||||||
|
pumpkin-text = { path = "../pumpkin-text" }
|
||||||
|
|
||||||
bytes = "1.7"
|
bytes = "1.7"
|
||||||
|
|
||||||
@ -22,9 +22,6 @@ log = "0.4"
|
|||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
num-derive = "0.4"
|
num-derive = "0.4"
|
||||||
|
|
||||||
# for text component
|
|
||||||
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
|
||||||
|
|
||||||
# encryption
|
# encryption
|
||||||
aes = "0.8.4"
|
aes = "0.8.4"
|
||||||
cfb8 = "0.8.1"
|
cfb8 = "0.8.1"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use pumpkin_text::TextComponent;
|
||||||
|
|
||||||
use crate::{text::TextComponent, ClientPacket, VarInt};
|
use crate::{ClientPacket, VarInt};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[packet(0x1E)]
|
#[packet(0x1E)]
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use pumpkin_text::TextComponent;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::text::TextComponent;
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[packet(0x1D)]
|
#[packet(0x1D)]
|
||||||
pub struct CPlayDisconnect {
|
pub struct CPlayDisconnect {
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use pumpkin_text::TextComponent;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{text::TextComponent, VarInt};
|
use crate::{ VarInt};
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
#[packet(0x39)]
|
#[packet(0x39)]
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use pumpkin_text::TextComponent;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::text::TextComponent;
|
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
#[packet(0x6C)]
|
#[packet(0x6C)]
|
||||||
pub struct CSystemChatMessge {
|
pub struct CSystemChatMessge {
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use thiserror::Error;
|
|||||||
pub mod bytebuf;
|
pub mod bytebuf;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod text;
|
|
||||||
|
|
||||||
pub mod packet_decoder;
|
pub mod packet_decoder;
|
||||||
pub mod packet_encoder;
|
pub mod packet_encoder;
|
||||||
|
|||||||
9
pumpkin-text/Cargo.toml
Normal file
9
pumpkin-text/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "pumpkin-text"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
||||||
|
uuid = "1.10"
|
||||||
19
pumpkin-text/src/click.rs
Normal file
19
pumpkin-text/src/click.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Action to take on click of the text.
|
||||||
|
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "action", content = "value", rename_all = "snake_case")]
|
||||||
|
pub enum ClickEvent {
|
||||||
|
/// Opens an URL
|
||||||
|
OpenUrl(String),
|
||||||
|
/// Works in signs, but only on the root text component
|
||||||
|
RunCommand(String),
|
||||||
|
/// Replaces the contents of the chat box with the text, not necessarily a
|
||||||
|
/// command.
|
||||||
|
SuggestCommand(String),
|
||||||
|
/// Only usable within written books. Changes the page of the book. Indexing
|
||||||
|
/// starts at 1.
|
||||||
|
ChangePage(i32),
|
||||||
|
/// Copies the given text to system clipboard
|
||||||
|
CopyToClipboard(String),
|
||||||
|
}
|
||||||
36
pumpkin-text/src/color.rs
Normal file
36
pumpkin-text/src/color.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Text color
|
||||||
|
#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Color {
|
||||||
|
/// The default color for the text will be used, which varies by context
|
||||||
|
/// (in some cases, it's white; in others, it's black; in still others, it
|
||||||
|
/// is a shade of gray that isn't normally used on text).
|
||||||
|
#[default]
|
||||||
|
Reset,
|
||||||
|
/// One of the 16 named Minecraft colors
|
||||||
|
Named(NamedColor),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Named Minecraft color
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum NamedColor {
|
||||||
|
Black = 0,
|
||||||
|
DarkBlue,
|
||||||
|
DarkGreen,
|
||||||
|
DarkAqua,
|
||||||
|
DarkRed,
|
||||||
|
DarkPurple,
|
||||||
|
Gold,
|
||||||
|
Gray,
|
||||||
|
DarkGray,
|
||||||
|
Blue,
|
||||||
|
Green,
|
||||||
|
Aqua,
|
||||||
|
Red,
|
||||||
|
LightPurple,
|
||||||
|
Yellow,
|
||||||
|
White,
|
||||||
|
}
|
||||||
32
pumpkin-text/src/hover.rs
Normal file
32
pumpkin-text/src/hover.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::Text;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "action", content = "contents", rename_all = "snake_case")]
|
||||||
|
#[allow(clippy::enum_variant_names)]
|
||||||
|
pub enum HoverEvent {
|
||||||
|
/// Displays a tooltip with the given text.
|
||||||
|
ShowText(Text),
|
||||||
|
/// Shows an item.
|
||||||
|
ShowItem {
|
||||||
|
/// Resource identifier of the item
|
||||||
|
id: String,
|
||||||
|
/// Number of the items in the stack
|
||||||
|
count: Option<i32>,
|
||||||
|
/// NBT information about the item (sNBT format)
|
||||||
|
tag: String,
|
||||||
|
},
|
||||||
|
/// Shows an entity.
|
||||||
|
ShowEntity {
|
||||||
|
/// The entity's UUID
|
||||||
|
id: uuid::Uuid,
|
||||||
|
/// Resource identifier of the entity
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
kind: Option<String>,
|
||||||
|
/// Optional custom name for the entity
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
name: Option<Text>,
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -1,11 +1,18 @@
|
|||||||
use core::str;
|
use core::str;
|
||||||
|
|
||||||
|
use click::ClickEvent;
|
||||||
|
use color::Color;
|
||||||
use fastnbt::SerOpts;
|
use fastnbt::SerOpts;
|
||||||
|
use hover::HoverEvent;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub mod color;
|
||||||
|
pub mod click;
|
||||||
|
pub mod hover;
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct Text(Box<TextComponent>);
|
pub struct Text(pub Box<TextComponent>);
|
||||||
|
|
||||||
// Fepresents a Text component
|
// Fepresents a Text component
|
||||||
// Reference: https://wiki.vg/Text_formatting#Text_components
|
// Reference: https://wiki.vg/Text_formatting#Text_components
|
||||||
@ -42,6 +49,12 @@ pub struct TextComponent {
|
|||||||
/// When the text is shift-clicked by a player, this string is inserted in their chat input. It does not overwrite any existing text the player was writing. This only works in chat messages
|
/// When the text is shift-clicked by a player, this string is inserted in their chat input. It does not overwrite any existing text the player was writing. This only works in chat messages
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub insertion: Option<String>,
|
pub insertion: Option<String>,
|
||||||
|
/// Allows for events to occur when the player clicks on text. Only work in chat.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub click_event: Option<ClickEvent>,
|
||||||
|
/// Allows for a tooltip to be displayed when the player hovers their mouse over text.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub hover_event: Option<HoverEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl serde::Serialize for TextComponent {
|
impl serde::Serialize for TextComponent {
|
||||||
@ -59,7 +72,7 @@ impl TextComponent {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn color_named(mut self, color: NamedColor) -> Self {
|
pub fn color_named(mut self, color: color::NamedColor) -> Self {
|
||||||
self.color = Some(Color::Named(color));
|
self.color = Some(Color::Named(color));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -100,6 +113,18 @@ impl TextComponent {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allows for events to occur when the player clicks on text. Only work in chat.
|
||||||
|
pub fn click_event(mut self, event: ClickEvent) -> Self {
|
||||||
|
self.click_event = Some(event);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allows for a tooltip to be displayed when the player hovers their mouse over text.
|
||||||
|
pub fn hover_event(mut self, event: HoverEvent) -> Self {
|
||||||
|
self.hover_event = Some(event);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn encode(&self) -> Vec<u8> {
|
pub fn encode(&self) -> Vec<u8> {
|
||||||
// TODO: Somehow fix this ugly mess
|
// TODO: Somehow fix this ugly mess
|
||||||
#[derive(serde::Serialize, Debug)]
|
#[derive(serde::Serialize, Debug)]
|
||||||
@ -121,6 +146,10 @@ impl TextComponent {
|
|||||||
pub obfuscated: &'a Option<u8>,
|
pub obfuscated: &'a Option<u8>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub insertion: &'a Option<String>,
|
pub insertion: &'a Option<String>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub click_event: &'a Option<ClickEvent>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub hover_event: &'a Option<HoverEvent>,
|
||||||
}
|
}
|
||||||
let astruct = TempStruct {
|
let astruct = TempStruct {
|
||||||
text: &self.content,
|
text: &self.content,
|
||||||
@ -131,7 +160,10 @@ impl TextComponent {
|
|||||||
strikethrough: &self.strikethrough,
|
strikethrough: &self.strikethrough,
|
||||||
obfuscated: &self.obfuscated,
|
obfuscated: &self.obfuscated,
|
||||||
insertion: &self.insertion,
|
insertion: &self.insertion,
|
||||||
|
click_event: &self.click_event,
|
||||||
|
hover_event: &self.hover_event,
|
||||||
};
|
};
|
||||||
|
// dbg!(&serde_json::to_string(&astruct));
|
||||||
let nbt = fastnbt::to_bytes_with_opts(&astruct, SerOpts::network_nbt()).unwrap();
|
let nbt = fastnbt::to_bytes_with_opts(&astruct, SerOpts::network_nbt()).unwrap();
|
||||||
nbt
|
nbt
|
||||||
}
|
}
|
||||||
@ -148,6 +180,8 @@ impl From<String> for TextComponent {
|
|||||||
strikethrough: None,
|
strikethrough: None,
|
||||||
obfuscated: None,
|
obfuscated: None,
|
||||||
insertion: None,
|
insertion: None,
|
||||||
|
click_event: None,
|
||||||
|
hover_event: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,6 +199,8 @@ impl From<&str> for TextComponent {
|
|||||||
strikethrough: None,
|
strikethrough: None,
|
||||||
obfuscated: None,
|
obfuscated: None,
|
||||||
insertion: None,
|
insertion: None,
|
||||||
|
click_event: None,
|
||||||
|
hover_event: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,38 +232,3 @@ impl Default for TextContent {
|
|||||||
Self::Text { text: "".into() }
|
Self::Text { text: "".into() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Text color
|
|
||||||
#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub enum Color {
|
|
||||||
/// The default color for the text will be used, which varies by context
|
|
||||||
/// (in some cases, it's white; in others, it's black; in still others, it
|
|
||||||
/// is a shade of gray that isn't normally used on text).
|
|
||||||
#[default]
|
|
||||||
Reset,
|
|
||||||
/// One of the 16 named Minecraft colors
|
|
||||||
Named(NamedColor),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Named Minecraft color
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum NamedColor {
|
|
||||||
Black = 0,
|
|
||||||
DarkBlue,
|
|
||||||
DarkGreen,
|
|
||||||
DarkAqua,
|
|
||||||
DarkRed,
|
|
||||||
DarkPurple,
|
|
||||||
Gold,
|
|
||||||
Gray,
|
|
||||||
DarkGray,
|
|
||||||
Blue,
|
|
||||||
Green,
|
|
||||||
Aqua,
|
|
||||||
Red,
|
|
||||||
LightPurple,
|
|
||||||
Yellow,
|
|
||||||
White,
|
|
||||||
}
|
|
||||||
@ -5,6 +5,7 @@ description = "Empowering everyone to host fast and efficient Minecraft servers.
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
pumpkin-text = { path = "../pumpkin-text" }
|
||||||
pumpkin-world = { path = "../pumpkin-world"}
|
pumpkin-world = { path = "../pumpkin-world"}
|
||||||
pumpkin-entity = { path = "../pumpkin-entity"}
|
pumpkin-entity = { path = "../pumpkin-entity"}
|
||||||
pumpkin-protocol = { path = "../pumpkin-protocol"}
|
pumpkin-protocol = { path = "../pumpkin-protocol"}
|
||||||
|
|||||||
@ -32,9 +32,9 @@ use pumpkin_protocol::{
|
|||||||
},
|
},
|
||||||
status::{SPingRequest, SStatusRequest},
|
status::{SPingRequest, SStatusRequest},
|
||||||
},
|
},
|
||||||
text::TextComponent,
|
|
||||||
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket,
|
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket,
|
||||||
};
|
};
|
||||||
|
use pumpkin_text::TextComponent;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|||||||
@ -8,8 +8,8 @@ use pumpkin_protocol::{
|
|||||||
SChatCommand, SChatMessage, SConfirmTeleport, SPlayerCommand, SPlayerPosition,
|
SChatCommand, SChatMessage, SConfirmTeleport, SPlayerCommand, SPlayerPosition,
|
||||||
SPlayerPositionRotation, SPlayerRotation, SSwingArm,
|
SPlayerPositionRotation, SPlayerRotation, SSwingArm,
|
||||||
},
|
},
|
||||||
text::TextComponent,
|
|
||||||
};
|
};
|
||||||
|
use pumpkin_text::TextComponent;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
commands::{handle_command, CommandSender},
|
commands::{handle_command, CommandSender},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use gamemode::GamemodeCommand;
|
use gamemode::GamemodeCommand;
|
||||||
use pumpkin::PumpkinCommand;
|
use pumpkin::PumpkinCommand;
|
||||||
use pumpkin_protocol::text::TextComponent;
|
use pumpkin_text::TextComponent;
|
||||||
|
|
||||||
use crate::client::Client;
|
use crate::client::Client;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
use pumpkin_protocol::{text::TextComponent, CURRENT_MC_PROTOCOL};
|
use pumpkin_protocol::{
|
||||||
|
CURRENT_MC_PROTOCOL,
|
||||||
|
};
|
||||||
|
use pumpkin_text::{click::ClickEvent, color::NamedColor, hover::HoverEvent, TextComponent};
|
||||||
|
|
||||||
use crate::server::CURRENT_MC_VERSION;
|
use crate::server::CURRENT_MC_VERSION;
|
||||||
|
|
||||||
@ -20,92 +23,6 @@ impl<'a> Command<'a> for PumpkinCommand {
|
|||||||
fn on_execute(sender: &mut super::CommandSender<'a>, _command: String) {
|
fn on_execute(sender: &mut super::CommandSender<'a>, _command: String) {
|
||||||
let version = env!("CARGO_PKG_VERSION");
|
let version = env!("CARGO_PKG_VERSION");
|
||||||
let description = env!("CARGO_PKG_DESCRIPTION");
|
let description = env!("CARGO_PKG_DESCRIPTION");
|
||||||
// sender.send_message(TextComponent::from(format!("Pumpkin {version}, {description} (Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL})")).color_named(pumpkin_protocol::text::NamedColor::Green))
|
sender.send_message(TextComponent::from(format!("Pumpkin {version}, {description} (Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL})")).color_named(NamedColor::Green))
|
||||||
|
|
||||||
// test
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("Pumpkin")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Black)
|
|
||||||
.bold(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("is")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::DarkBlue)
|
|
||||||
.italic(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("such")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::DarkGreen)
|
|
||||||
.underlined(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("a")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::DarkAqua)
|
|
||||||
.strikethrough(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("super")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::DarkRed)
|
|
||||||
.obfuscated(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("mega")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::DarkPurple)
|
|
||||||
.bold(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("great")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Gold)
|
|
||||||
.italic(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("project")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Gray)
|
|
||||||
.underlined(),
|
|
||||||
);
|
|
||||||
sender.send_message(TextComponent::from(""));
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("no")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::DarkGray)
|
|
||||||
.bold(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("worries")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Blue)
|
|
||||||
.bold(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("there")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Green)
|
|
||||||
.underlined(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("will")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Aqua)
|
|
||||||
.italic(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("be")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Red)
|
|
||||||
.obfuscated(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("chunk")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::LightPurple)
|
|
||||||
.bold(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("loading")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::Yellow)
|
|
||||||
.strikethrough(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("soon")
|
|
||||||
.color_named(pumpkin_protocol::text::NamedColor::White)
|
|
||||||
.bold(),
|
|
||||||
);
|
|
||||||
sender.send_message(
|
|
||||||
TextComponent::from("soon").color_named(pumpkin_protocol::text::NamedColor::White),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user