Merge branch 'master' into master
This commit is contained in:
commit
72d95cd416
538
Cargo.lock
generated
538
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
22
Cargo.toml
22
Cargo.toml
@ -1,6 +1,17 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [ "pumpkin-config", "pumpkin-core", "pumpkin-entity", "pumpkin-inventory", "pumpkin-macros/", "pumpkin-plugin", "pumpkin-protocol/", "pumpkin-registry/", "pumpkin-world", "pumpkin/"]
|
||||
members = [
|
||||
"pumpkin-config",
|
||||
"pumpkin-core",
|
||||
"pumpkin-entity",
|
||||
"pumpkin-inventory",
|
||||
"pumpkin-macros/",
|
||||
"pumpkin-plugin",
|
||||
"pumpkin-protocol/",
|
||||
"pumpkin-registry/",
|
||||
"pumpkin-world",
|
||||
"pumpkin/",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
@ -13,7 +24,14 @@ codegen-units = 1
|
||||
|
||||
[workspace.dependencies]
|
||||
log = "0.4"
|
||||
tokio = { version = "1.39.2", features = ["net", "macros", "rt-multi-thread", "fs", "io-util", "sync"] }
|
||||
tokio = { version = "1.40", features = [
|
||||
"net",
|
||||
"macros",
|
||||
"rt-multi-thread",
|
||||
"fs",
|
||||
"io-util",
|
||||
"sync",
|
||||
] }
|
||||
rayon = "1.10.0"
|
||||
uuid = { version = "1.10.0", features = ["serde", "v3"] }
|
||||
derive_more = { version = "1.0.0", features = ["full"] }
|
||||
|
||||
@ -5,8 +5,8 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pumpkin-core = { path = "../pumpkin-core" }
|
||||
serde.workspace = true
|
||||
log.workspace = true
|
||||
|
||||
serde = "1.0"
|
||||
toml = "0.8"
|
||||
|
||||
log.workspace = true
|
||||
|
||||
@ -5,8 +5,8 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
||||
uuid.workspace = true
|
||||
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
||||
colored = "2"
|
||||
md5 = "0.7.0"
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ use super::Text;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "action", content = "contents", rename_all = "snake_case")]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum HoverEvent<'a> {
|
||||
/// Displays a tooltip with the given text.
|
||||
ShowText(Text<'a>),
|
||||
|
||||
@ -5,6 +5,3 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pumpkin-core = { path = "../pumpkin-core"}
|
||||
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.4"
|
||||
@ -2,8 +2,6 @@ use crate::container_click::MouseClick;
|
||||
use crate::{handle_item_change, Container, InventoryError, WindowType};
|
||||
use pumpkin_world::item::ItemStack;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub struct PlayerInventory {
|
||||
// Main Inventory + Hotbar
|
||||
crafting: [Option<ItemStack>; 4],
|
||||
|
||||
@ -7,6 +7,6 @@ edition.workspace = true
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.86"
|
||||
quote = "1.0.37"
|
||||
syn = "2.0.76"
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = "2.0"
|
||||
|
||||
@ -4,6 +4,6 @@ version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
extism = "1.5.0"
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
log.workspace = true
|
||||
extism = "1.6.0"
|
||||
|
||||
@ -13,12 +13,10 @@ bytes = "1.7"
|
||||
uuid.workspace = true
|
||||
|
||||
serde.workspace = true
|
||||
# to parse strings to json responses
|
||||
serde_json = "1.0"
|
||||
|
||||
flate2 = "1.0.33"
|
||||
|
||||
thiserror = "1.0.63"
|
||||
thiserror = "1.0"
|
||||
log.workspace = true
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.4"
|
||||
@ -26,6 +24,6 @@ num-derive = "0.4"
|
||||
# encryption
|
||||
aes = "0.8.4"
|
||||
cfb8 = "0.8.1"
|
||||
take_mut = "0.2.2"
|
||||
|
||||
itertools = "0.13.0"
|
||||
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
||||
|
||||
@ -45,77 +45,77 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<'a> {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_bool(self.inner.get_bool())
|
||||
visitor.visit_bool(self.inner.get_bool()?)
|
||||
}
|
||||
|
||||
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i8(self.inner.get_i8())
|
||||
visitor.visit_i8(self.inner.get_i8()?)
|
||||
}
|
||||
|
||||
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i16(self.inner.get_i16())
|
||||
visitor.visit_i16(self.inner.get_i16()?)
|
||||
}
|
||||
|
||||
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i32(self.inner.get_i32())
|
||||
visitor.visit_i32(self.inner.get_i32()?)
|
||||
}
|
||||
|
||||
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_i64(self.inner.get_i64())
|
||||
visitor.visit_i64(self.inner.get_i64()?)
|
||||
}
|
||||
|
||||
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u8(self.inner.get_u8())
|
||||
visitor.visit_u8(self.inner.get_u8()?)
|
||||
}
|
||||
|
||||
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u16(self.inner.get_u16())
|
||||
visitor.visit_u16(self.inner.get_u16()?)
|
||||
}
|
||||
|
||||
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u32(self.inner.get_u32())
|
||||
visitor.visit_u32(self.inner.get_u32()?)
|
||||
}
|
||||
|
||||
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_u64(self.inner.get_u64())
|
||||
visitor.visit_u64(self.inner.get_u64()?)
|
||||
}
|
||||
|
||||
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_f32(self.inner.get_f32())
|
||||
visitor.visit_f32(self.inner.get_f32()?)
|
||||
}
|
||||
|
||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_f64(self.inner.get_f64())
|
||||
visitor.visit_f64(self.inner.get_f64()?)
|
||||
}
|
||||
|
||||
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
|
||||
@ -129,7 +129,7 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<'a> {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let string = self.inner.get_string().map_err(DeserializerError::Stdio)?;
|
||||
let string = self.inner.get_string()?;
|
||||
visitor.visit_str(&string)
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<'a> {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let string = self.inner.get_string().map_err(DeserializerError::Stdio)?;
|
||||
let string = self.inner.get_string()?;
|
||||
visitor.visit_str(&string)
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use crate::{BitSet, FixedBitSet, VarInt, VarLongType};
|
||||
use bytes::{Buf, BufMut, BytesMut};
|
||||
use core::str;
|
||||
use std::io::{self, Error, ErrorKind};
|
||||
|
||||
mod deserializer;
|
||||
pub use deserializer::DeserializerError;
|
||||
@ -26,12 +25,12 @@ impl ByteBuffer {
|
||||
Self { buffer }
|
||||
}
|
||||
|
||||
pub fn get_var_int(&mut self) -> VarInt {
|
||||
pub fn get_var_int(&mut self) -> Result<VarInt, DeserializerError> {
|
||||
let mut value: i32 = 0;
|
||||
let mut position: i32 = 0;
|
||||
|
||||
loop {
|
||||
let read = self.buffer.get_u8();
|
||||
let read = self.get_u8()?;
|
||||
|
||||
value |= ((read & SEGMENT_BITS) as i32) << position;
|
||||
|
||||
@ -42,19 +41,19 @@ impl ByteBuffer {
|
||||
position += 7;
|
||||
|
||||
if position >= 32 {
|
||||
panic!("VarInt is too big");
|
||||
return Err(DeserializerError::Message("VarInt is too big".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
VarInt(value)
|
||||
Ok(VarInt(value))
|
||||
}
|
||||
|
||||
pub fn get_var_long(&mut self) -> VarLongType {
|
||||
pub fn get_var_long(&mut self) -> Result<VarLongType, DeserializerError> {
|
||||
let mut value: i64 = 0;
|
||||
let mut position: i64 = 0;
|
||||
|
||||
loop {
|
||||
let read = self.buffer.get_u8();
|
||||
let read = self.get_u8()?;
|
||||
|
||||
value |= ((read & SEGMENT_BITS) as i64) << position;
|
||||
|
||||
@ -65,49 +64,48 @@ impl ByteBuffer {
|
||||
position += 7;
|
||||
|
||||
if position >= 64 {
|
||||
panic!("VarInt is too big");
|
||||
return Err(DeserializerError::Message("VarLong is too big".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
value
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn get_string(&mut self) -> Result<String, io::Error> {
|
||||
pub fn get_string(&mut self) -> Result<String, DeserializerError> {
|
||||
self.get_string_len(32767)
|
||||
}
|
||||
|
||||
pub fn get_string_len(&mut self, max_size: usize) -> Result<String, io::Error> {
|
||||
let size = self.get_var_int().0;
|
||||
pub fn get_string_len(&mut self, max_size: usize) -> Result<String, DeserializerError> {
|
||||
let size = self.get_var_int()?.0;
|
||||
if size as usize > max_size {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"String length is bigger than max size",
|
||||
return Err(DeserializerError::Message(
|
||||
"String length is bigger than max size".to_string(),
|
||||
));
|
||||
}
|
||||
let data = self.buffer.copy_to_bytes(size as usize);
|
||||
|
||||
let data = self.copy_to_bytes(size as usize)?;
|
||||
if data.len() > max_size {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"String is bigger than max size",
|
||||
return Err(DeserializerError::Message(
|
||||
"String is bigger than max size".to_string(),
|
||||
));
|
||||
}
|
||||
match str::from_utf8(&data) {
|
||||
Ok(string_result) => Ok(string_result.to_string()),
|
||||
Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
|
||||
Err(e) => Err(DeserializerError::Message(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bool(&mut self) -> bool {
|
||||
self.buffer.get_u8() != 0
|
||||
pub fn get_bool(&mut self) -> Result<bool, DeserializerError> {
|
||||
Ok(self.get_u8()? != 0)
|
||||
}
|
||||
|
||||
pub fn get_uuid(&mut self) -> uuid::Uuid {
|
||||
pub fn get_uuid(&mut self) -> Result<uuid::Uuid, DeserializerError> {
|
||||
let mut bytes = [0u8; 16];
|
||||
self.buffer.copy_to_slice(&mut bytes);
|
||||
uuid::Uuid::from_slice(&bytes).expect("Failed to parse UUID")
|
||||
self.copy_to_slice(&mut bytes)?;
|
||||
Ok(uuid::Uuid::from_slice(&bytes).expect("Failed to parse UUID"))
|
||||
}
|
||||
|
||||
pub fn get_fixed_bitset(&mut self, bits: usize) -> FixedBitSet {
|
||||
pub fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, DeserializerError> {
|
||||
self.copy_to_bytes(bits.div_ceil(8))
|
||||
}
|
||||
|
||||
@ -161,11 +159,14 @@ impl ByteBuffer {
|
||||
|
||||
/// Reads a boolean. If true, the closure is called, and the returned value is
|
||||
/// wrapped in Some. Otherwise, this returns None.
|
||||
pub fn get_option<T>(&mut self, val: impl FnOnce(&mut Self) -> T) -> Option<T> {
|
||||
if self.get_bool() {
|
||||
Some(val(self))
|
||||
pub fn get_option<T>(
|
||||
&mut self,
|
||||
val: impl FnOnce(&mut Self) -> Result<T, DeserializerError>,
|
||||
) -> Result<Option<T>, DeserializerError> {
|
||||
if self.get_bool()? {
|
||||
Ok(Some(val(self)?))
|
||||
} else {
|
||||
None
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
/// Writes `true` if the option is Some, or `false` if None. If the option is
|
||||
@ -177,13 +178,16 @@ impl ByteBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_list<T>(&mut self, val: impl Fn(&mut Self) -> T) -> Vec<T> {
|
||||
let len = self.get_var_int().0 as usize;
|
||||
pub fn get_list<T>(
|
||||
&mut self,
|
||||
val: impl Fn(&mut Self) -> Result<T, DeserializerError>,
|
||||
) -> Result<Vec<T>, DeserializerError> {
|
||||
let len = self.get_var_int()?.0 as usize;
|
||||
let mut list = Vec::with_capacity(len);
|
||||
for _ in 0..len {
|
||||
list.push(val(self));
|
||||
list.push(val(self)?);
|
||||
}
|
||||
list
|
||||
Ok(list)
|
||||
}
|
||||
/// Writes a list to the buffer.
|
||||
pub fn put_list<T>(&mut self, list: &[T], write: impl Fn(&mut Self, &T)) {
|
||||
@ -211,50 +215,109 @@ impl ByteBuffer {
|
||||
pub fn buf(&mut self) -> &mut BytesMut {
|
||||
&mut self.buffer
|
||||
}
|
||||
|
||||
// Trait equivalents
|
||||
pub fn get_u8(&mut self) -> Result<u8, DeserializerError> {
|
||||
if self.buffer.has_remaining() {
|
||||
Ok(self.buffer.get_u8())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"No bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// trait
|
||||
impl ByteBuffer {
|
||||
pub fn get_u8(&mut self) -> u8 {
|
||||
self.buffer.get_u8()
|
||||
pub fn get_i8(&mut self) -> Result<i8, DeserializerError> {
|
||||
if self.buffer.has_remaining() {
|
||||
Ok(self.buffer.get_i8())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"No bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_i8(&mut self) -> i8 {
|
||||
self.buffer.get_i8()
|
||||
pub fn get_u16(&mut self) -> Result<u16, DeserializerError> {
|
||||
if self.buffer.remaining() >= 2 {
|
||||
Ok(self.buffer.get_u16())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 2 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_u16(&mut self) -> u16 {
|
||||
self.buffer.get_u16()
|
||||
pub fn get_i16(&mut self) -> Result<i16, DeserializerError> {
|
||||
if self.buffer.remaining() >= 2 {
|
||||
Ok(self.buffer.get_i16())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 2 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_i16(&mut self) -> i16 {
|
||||
self.buffer.get_i16()
|
||||
pub fn get_u32(&mut self) -> Result<u32, DeserializerError> {
|
||||
if self.buffer.remaining() >= 4 {
|
||||
Ok(self.buffer.get_u32())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 4 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_u32(&mut self) -> u32 {
|
||||
self.buffer.get_u32()
|
||||
pub fn get_i32(&mut self) -> Result<i32, DeserializerError> {
|
||||
if self.buffer.remaining() >= 4 {
|
||||
Ok(self.buffer.get_i32())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 4 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_i32(&mut self) -> i32 {
|
||||
self.buffer.get_i32()
|
||||
pub fn get_u64(&mut self) -> Result<u64, DeserializerError> {
|
||||
if self.buffer.remaining() >= 8 {
|
||||
Ok(self.buffer.get_u64())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 8 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_u64(&mut self) -> u64 {
|
||||
self.buffer.get_u64()
|
||||
pub fn get_i64(&mut self) -> Result<i64, DeserializerError> {
|
||||
if self.buffer.remaining() >= 8 {
|
||||
Ok(self.buffer.get_i64())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 8 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_i64(&mut self) -> i64 {
|
||||
self.buffer.get_i64()
|
||||
pub fn get_f32(&mut self) -> Result<f32, DeserializerError> {
|
||||
if self.buffer.remaining() >= 4 {
|
||||
Ok(self.buffer.get_f32())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 4 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_f32(&mut self) -> f32 {
|
||||
self.buffer.get_f32()
|
||||
}
|
||||
|
||||
pub fn get_f64(&mut self) -> f64 {
|
||||
self.buffer.get_f64()
|
||||
pub fn get_f64(&mut self) -> Result<f64, DeserializerError> {
|
||||
if self.buffer.remaining() >= 8 {
|
||||
Ok(self.buffer.get_f64())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Less than 8 bytes left to consume".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: SerializerError?
|
||||
pub fn put_u8(&mut self, n: u8) {
|
||||
self.buffer.put_u8(n)
|
||||
}
|
||||
@ -295,12 +358,25 @@ impl ByteBuffer {
|
||||
self.buffer.put_f64(n)
|
||||
}
|
||||
|
||||
pub fn copy_to_bytes(&mut self, len: usize) -> bytes::Bytes {
|
||||
self.buffer.copy_to_bytes(len)
|
||||
pub fn copy_to_bytes(&mut self, len: usize) -> Result<bytes::Bytes, DeserializerError> {
|
||||
if self.buffer.len() >= len {
|
||||
Ok(self.buffer.copy_to_bytes(len))
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Unable to copy bytes".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_to_slice(&mut self, dst: &mut [u8]) {
|
||||
self.buffer.copy_to_slice(dst)
|
||||
pub fn copy_to_slice(&mut self, dst: &mut [u8]) -> Result<(), DeserializerError> {
|
||||
if self.buffer.remaining() >= dst.len() {
|
||||
self.buffer.copy_to_slice(dst);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DeserializerError::Message(
|
||||
"Unable to copy slice".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put_slice(&mut self, src: &[u8]) {
|
||||
|
||||
@ -83,12 +83,13 @@ where
|
||||
P: Packet + Serialize,
|
||||
{
|
||||
fn write(&self, bytebuf: &mut ByteBuffer) {
|
||||
take_mut::take(bytebuf, |bytebuf| {
|
||||
let mut serializer = serializer::Serializer::new(bytebuf);
|
||||
let mut serializer = serializer::Serializer::new(ByteBuffer::empty());
|
||||
self.serialize(&mut serializer)
|
||||
.expect("Could not serialize packet");
|
||||
serializer.into()
|
||||
});
|
||||
// We write the packet in an empty bytebuffer and then put it into our current one.
|
||||
// In the future we may do packet batching thats the reason i don't let every packet create a new bytebuffer and use
|
||||
// an existing instead
|
||||
bytebuf.put(serializer.output.buf());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ use thiserror::Error;
|
||||
use super::ByteBuffer;
|
||||
|
||||
pub struct Serializer {
|
||||
output: ByteBuffer,
|
||||
pub output: ByteBuffer,
|
||||
}
|
||||
|
||||
impl Serializer {
|
||||
|
||||
@ -30,7 +30,7 @@ pub struct CLogin<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CLogin<'a> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
entity_id: i32,
|
||||
is_hardcore: bool,
|
||||
|
||||
@ -21,7 +21,7 @@ pub struct CParticle<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CParticle<'a> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
long_distance: bool,
|
||||
x: f64,
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct CPlayerChatMessage<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CPlayerChatMessage<'a> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
sender: UUID,
|
||||
index: VarInt,
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct CSpawnEntity {
|
||||
}
|
||||
|
||||
impl CSpawnEntity {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
entity_id: VarInt,
|
||||
entity_uuid: UUID,
|
||||
|
||||
@ -22,8 +22,6 @@ pub struct PacketEncoder {
|
||||
}
|
||||
|
||||
impl PacketEncoder {
|
||||
// i think clippy is broken
|
||||
#[allow(clippy::needless_borrows_for_generic_args)]
|
||||
pub fn append_packet<P: ClientPacket>(&mut self, packet: &P) -> Result<(), PacketError> {
|
||||
let start_len = self.buf.len();
|
||||
|
||||
@ -87,6 +85,7 @@ impl PacketEncoder {
|
||||
|
||||
let mut front = &mut self.buf[start_len..];
|
||||
|
||||
#[allow(clippy::needless_borrows_for_generic_args)]
|
||||
VarInt(packet_len as i32)
|
||||
.encode(&mut front)
|
||||
.map_err(|_| PacketError::EncodeLength)?;
|
||||
|
||||
@ -16,10 +16,10 @@ pub struct SHandShake {
|
||||
impl ServerPacket for SHandShake {
|
||||
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
|
||||
Ok(Self {
|
||||
protocol_version: bytebuf.get_var_int(),
|
||||
server_address: bytebuf.get_string_len(255).unwrap(),
|
||||
server_port: bytebuf.get_u16(),
|
||||
next_state: bytebuf.get_var_int().into(),
|
||||
protocol_version: bytebuf.get_var_int()?,
|
||||
server_address: bytebuf.get_string_len(255)?,
|
||||
server_port: bytebuf.get_u16()?,
|
||||
next_state: bytebuf.get_var_int()?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,10 +15,10 @@ pub struct SEncryptionResponse {
|
||||
|
||||
impl ServerPacket for SEncryptionResponse {
|
||||
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
|
||||
let shared_secret_length = bytebuf.get_var_int();
|
||||
let shared_secret = bytebuf.copy_to_bytes(shared_secret_length.0 as usize);
|
||||
let verify_token_length = bytebuf.get_var_int();
|
||||
let verify_token = bytebuf.copy_to_bytes(shared_secret_length.0 as usize);
|
||||
let shared_secret_length = bytebuf.get_var_int()?;
|
||||
let shared_secret = bytebuf.copy_to_bytes(shared_secret_length.0 as usize)?;
|
||||
let verify_token_length = bytebuf.get_var_int()?;
|
||||
let verify_token = bytebuf.copy_to_bytes(shared_secret_length.0 as usize)?;
|
||||
Ok(Self {
|
||||
shared_secret_length,
|
||||
shared_secret: shared_secret.to_vec(),
|
||||
|
||||
@ -14,8 +14,8 @@ pub struct SLoginStart {
|
||||
impl ServerPacket for SLoginStart {
|
||||
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
|
||||
Ok(Self {
|
||||
name: bytebuf.get_string_len(16).unwrap(),
|
||||
uuid: bytebuf.get_uuid(),
|
||||
name: bytebuf.get_string_len(16)?,
|
||||
uuid: bytebuf.get_uuid()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,9 @@ pub struct SLoginPluginResponse {
|
||||
impl ServerPacket for SLoginPluginResponse {
|
||||
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
|
||||
Ok(Self {
|
||||
message_id: bytebuf.get_var_int(),
|
||||
successful: bytebuf.get_bool(),
|
||||
data: bytebuf.get_option(|v| v.get_slice()),
|
||||
message_id: bytebuf.get_var_int()?,
|
||||
successful: bytebuf.get_bool()?,
|
||||
data: bytebuf.get_option(|v| Ok(v.get_slice()))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,12 +21,12 @@ pub struct SChatMessage {
|
||||
impl ServerPacket for SChatMessage {
|
||||
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
|
||||
Ok(Self {
|
||||
message: bytebuf.get_string().unwrap(),
|
||||
timestamp: bytebuf.get_i64(),
|
||||
salt: bytebuf.get_i64(),
|
||||
signature: bytebuf.get_option(|v| v.copy_to_bytes(256)),
|
||||
message_count: bytebuf.get_var_int(),
|
||||
acknowledged: bytebuf.get_fixed_bitset(20),
|
||||
message: bytebuf.get_string()?,
|
||||
timestamp: bytebuf.get_i64()?,
|
||||
salt: bytebuf.get_i64()?,
|
||||
signature: bytebuf.get_option(|v| v.copy_to_bytes(256))?,
|
||||
message_count: bytebuf.get_var_int()?,
|
||||
acknowledged: bytebuf.get_fixed_bitset(20)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,8 +18,8 @@ impl ServerPacket for SInteract {
|
||||
fn read(
|
||||
bytebuf: &mut crate::bytebuf::ByteBuffer,
|
||||
) -> Result<Self, crate::bytebuf::DeserializerError> {
|
||||
let entity_id = bytebuf.get_var_int();
|
||||
let typ = bytebuf.get_var_int();
|
||||
let entity_id = bytebuf.get_var_int()?;
|
||||
let typ = bytebuf.get_var_int()?;
|
||||
let action = ActionType::from_i32(typ.0).ok_or(DeserializerError::Message(
|
||||
"invalid action type".to_string(),
|
||||
))?;
|
||||
@ -27,13 +27,13 @@ impl ServerPacket for SInteract {
|
||||
ActionType::Interact => None,
|
||||
ActionType::Attack => None,
|
||||
ActionType::InteractAt => {
|
||||
Some((bytebuf.get_f32(), bytebuf.get_f32(), bytebuf.get_f32()))
|
||||
Some((bytebuf.get_f32()?, bytebuf.get_f32()?, bytebuf.get_f32()?))
|
||||
}
|
||||
};
|
||||
let hand = match action {
|
||||
ActionType::Interact => Some(bytebuf.get_var_int()),
|
||||
ActionType::Interact => Some(bytebuf.get_var_int()?),
|
||||
ActionType::Attack => None,
|
||||
ActionType::InteractAt => Some(bytebuf.get_var_int()),
|
||||
ActionType::InteractAt => Some(bytebuf.get_var_int()?),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
@ -41,7 +41,7 @@ impl ServerPacket for SInteract {
|
||||
typ,
|
||||
target_position,
|
||||
hand,
|
||||
sneaking: bytebuf.get_bool(),
|
||||
sneaking: bytebuf.get_bool()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,9 +25,9 @@ pub enum Action {
|
||||
impl ServerPacket for SPlayerCommand {
|
||||
fn read(bytebuf: &mut crate::bytebuf::ByteBuffer) -> Result<Self, DeserializerError> {
|
||||
Ok(Self {
|
||||
entity_id: bytebuf.get_var_int(),
|
||||
action: bytebuf.get_var_int(),
|
||||
jump_boost: bytebuf.get_var_int(),
|
||||
entity_id: bytebuf.get_var_int()?,
|
||||
action: bytebuf.get_var_int()?,
|
||||
jump_boost: bytebuf.get_var_int()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ use serde::{
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct Slot {
|
||||
item_count: VarInt,
|
||||
item_id: Option<VarInt>,
|
||||
|
||||
@ -9,6 +9,5 @@ pumpkin-core = { path = "../pumpkin-core"}
|
||||
|
||||
# nbt
|
||||
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
||||
fastsnbt = "0.2"
|
||||
|
||||
serde.workspace = true
|
||||
|
||||
@ -33,12 +33,12 @@ impl Registry {
|
||||
registry_id: "minecraft:worldgen/biome".to_string(),
|
||||
registry_entries: vec![
|
||||
RegistryEntry {
|
||||
entry_id: "minecraft:snowy_taiga",
|
||||
entry_id: "minecraft:plains",
|
||||
data: fastnbt::to_bytes_with_opts(&Biome::default(), SerOpts::network_nbt())
|
||||
.unwrap(),
|
||||
},
|
||||
RegistryEntry {
|
||||
entry_id: "minecraft:plains",
|
||||
entry_id: "minecraft:snowy_taiga",
|
||||
data: fastnbt::to_bytes_with_opts(&Biome::default(), SerOpts::network_nbt())
|
||||
.unwrap(),
|
||||
},
|
||||
|
||||
@ -6,20 +6,22 @@ edition.workspace = true
|
||||
[dependencies]
|
||||
pumpkin-core = { path = "../pumpkin-core"}
|
||||
|
||||
|
||||
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
||||
fastsnbt = "0.2"
|
||||
tokio.workspace = true
|
||||
rayon.workspace = true
|
||||
derive_more.workspace = true
|
||||
itertools = "0.13.0"
|
||||
thiserror = "1.0.63"
|
||||
futures = "0.3.30"
|
||||
flate2 = "1.0.33"
|
||||
thiserror = "1.0"
|
||||
futures = "0.3"
|
||||
flate2 = "1.0"
|
||||
serde.workspace = true
|
||||
serde_json = "1.0"
|
||||
static_assertions = "1.1.0"
|
||||
log.workspace = true
|
||||
|
||||
noise = "0.9.0"
|
||||
|
||||
rand = "0.8.5"
|
||||
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.4"
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// TODO make this work with the protocol
|
||||
// Send by the registry
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
#[non_exhaustive]
|
||||
pub enum Biome {
|
||||
Plains,
|
||||
SnowyTiga,
|
||||
// TODO list all Biomes
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ pub struct ChunkHeightmaps {
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
struct ChunkSection {
|
||||
#[serde(rename = "Y")]
|
||||
y: i32,
|
||||
@ -64,7 +64,7 @@ struct ChunkSection {
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
struct ChunkNbt {
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
data_version: usize,
|
||||
|
||||
#[serde(rename = "sections")]
|
||||
@ -171,7 +171,7 @@ impl ChunkBlocks {
|
||||
index.y.get_absolute() as usize * CHUNK_AREA + *index.z as usize * 16 + *index.x as usize
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
fn calculate_heightmap(&self) -> ChunkHeightmaps {
|
||||
// figure out how LongArray is formatted
|
||||
// figure out how to find out if block is motion blocking
|
||||
|
||||
@ -24,7 +24,6 @@ pub fn get_protocol_id(category: &str, entry: &str) -> u32 {
|
||||
.expect("No Entry found")
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_default<'a>(category: &str) -> Option<&'a str> {
|
||||
REGISTRY
|
||||
.get(category)
|
||||
|
||||
@ -28,12 +28,12 @@ pub struct ItemElement {
|
||||
components: ItemComponents,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
pub fn get_item_element(item_id: &str) -> &ItemComponents {
|
||||
&ITEMS.get(item_id).expect("Item not found").components
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
pub fn get_item_protocol_id(item_id: &str) -> u32 {
|
||||
global_registry::get_protocol_id(ITEM_REGISTRY, item_id)
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ pub struct Level {
|
||||
}
|
||||
|
||||
struct SaveFile {
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
root_folder: PathBuf,
|
||||
region_folder: PathBuf,
|
||||
}
|
||||
@ -277,7 +277,7 @@ impl Level {
|
||||
match compression {
|
||||
Compression::Gzip => {
|
||||
let mut z = GzDecoder::new(&compressed_data[..]);
|
||||
let mut chunk_data = Vec::new();
|
||||
let mut chunk_data = Vec::with_capacity(compressed_data.len());
|
||||
match z.read_to_end(&mut chunk_data) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
@ -288,7 +288,7 @@ impl Level {
|
||||
}
|
||||
Compression::Zlib => {
|
||||
let mut z = ZlibDecoder::new(&compressed_data[..]);
|
||||
let mut chunk_data = Vec::new();
|
||||
let mut chunk_data = Vec::with_capacity(compressed_data.len());
|
||||
match z.read_to_end(&mut chunk_data) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use noise::Perlin;
|
||||
use pumpkin_core::math::vector2::Vector2;
|
||||
use static_assertions::assert_obj_safe;
|
||||
|
||||
@ -12,7 +13,6 @@ pub trait GeneratorInit {
|
||||
}
|
||||
|
||||
pub trait WorldGenerator: Sync + Send {
|
||||
#[allow(dead_code)]
|
||||
fn generate_chunk(&self, at: Vector2<i32>) -> ChunkData;
|
||||
}
|
||||
assert_obj_safe! {WorldGenerator}
|
||||
@ -21,6 +21,17 @@ pub(crate) trait BiomeGenerator: Sync + Send {
|
||||
fn generate_biome(&self, at: XZBlockCoordinates) -> Biome;
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub(crate) trait TerrainGenerator: Sync + Send {
|
||||
fn prepare_chunk(&self, at: &Vector2<i32>);
|
||||
|
||||
/// Is static
|
||||
fn generate_block(&self, at: BlockCoordinates, biome: Biome) -> BlockId;
|
||||
}
|
||||
|
||||
pub(crate) trait PerlinTerrainGenerator: Sync + Send {
|
||||
fn prepare_chunk(&self, at: &Vector2<i32>, perlin: &Perlin);
|
||||
|
||||
/// Dependens on the perlin noise height
|
||||
fn generate_block(&self, at: BlockCoordinates, chunk_height: i16, biome: Biome) -> BlockId;
|
||||
}
|
||||
|
||||
@ -1,36 +1,89 @@
|
||||
use noise::{NoiseFn, Perlin};
|
||||
use pumpkin_core::math::vector2::Vector2;
|
||||
|
||||
use crate::{
|
||||
chunk::{ChunkBlocks, ChunkData},
|
||||
coordinates::{ChunkRelativeBlockCoordinates, ChunkRelativeXZBlockCoordinates},
|
||||
WORLD_LOWEST_Y, WORLD_MAX_Y,
|
||||
WORLD_LOWEST_Y,
|
||||
};
|
||||
|
||||
use super::{
|
||||
generator::{BiomeGenerator, GeneratorInit, TerrainGenerator, WorldGenerator},
|
||||
generator::{BiomeGenerator, GeneratorInit, PerlinTerrainGenerator, WorldGenerator},
|
||||
Seed,
|
||||
};
|
||||
|
||||
pub struct GenericGenerator<B: BiomeGenerator, T: TerrainGenerator> {
|
||||
pub struct GenericGenerator<B: BiomeGenerator, T: PerlinTerrainGenerator> {
|
||||
biome_generator: B,
|
||||
terrain_generator: T,
|
||||
// TODO: May make this optional?. But would be pain to use in most biomes then. Maybe make a new trait like
|
||||
// PerlinTerrainGenerator
|
||||
perlin: Perlin,
|
||||
}
|
||||
|
||||
impl<B: BiomeGenerator + GeneratorInit, T: TerrainGenerator + GeneratorInit> GeneratorInit
|
||||
impl<B: BiomeGenerator + GeneratorInit, T: PerlinTerrainGenerator + GeneratorInit> GeneratorInit
|
||||
for GenericGenerator<B, T>
|
||||
{
|
||||
fn new(seed: Seed) -> Self {
|
||||
Self {
|
||||
biome_generator: B::new(seed),
|
||||
terrain_generator: T::new(seed),
|
||||
perlin: Perlin::new(seed.0 as u32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BiomeGenerator, T: TerrainGenerator> WorldGenerator for GenericGenerator<B, T> {
|
||||
impl<B: BiomeGenerator, T: PerlinTerrainGenerator> WorldGenerator for GenericGenerator<B, T> {
|
||||
fn generate_chunk(&self, at: Vector2<i32>) -> ChunkData {
|
||||
let mut blocks = ChunkBlocks::default();
|
||||
self.terrain_generator.prepare_chunk(&at, &self.perlin);
|
||||
let noise_value = self.perlin.get([at.x as f64 / 16.0, at.z as f64 / 16.0]);
|
||||
|
||||
let base_height = 64.0;
|
||||
let height_variation = 16.0;
|
||||
let chunk_height = (noise_value * height_variation + base_height) as i32;
|
||||
|
||||
for x in 0..16u8 {
|
||||
for z in 0..16u8 {
|
||||
let biome = self.biome_generator.generate_biome(
|
||||
ChunkRelativeXZBlockCoordinates {
|
||||
x: x.into(),
|
||||
z: z.into(),
|
||||
}
|
||||
.with_chunk_coordinates(at),
|
||||
);
|
||||
|
||||
// Iterate from the highest block to the lowest, in order to minimize the heightmap updates
|
||||
for y in (WORLD_LOWEST_Y..chunk_height as i16).rev() {
|
||||
let coordinates = ChunkRelativeBlockCoordinates {
|
||||
x: x.into(),
|
||||
y: y.into(),
|
||||
z: z.into(),
|
||||
};
|
||||
|
||||
blocks.set_block(
|
||||
coordinates,
|
||||
self.terrain_generator.generate_block(
|
||||
coordinates.with_chunk_coordinates(at),
|
||||
chunk_height as i16,
|
||||
biome,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChunkData {
|
||||
blocks,
|
||||
position: at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement static terrain generator
|
||||
/*
|
||||
fn generate_chunk(&mut self, at: Vector2<i32>) -> ChunkData {
|
||||
let mut blocks = ChunkBlocks::default();
|
||||
self.terrain_generator.prepare_chunk(&at, &self.perlin);
|
||||
for x in 0..16u8 {
|
||||
for z in 0..16u8 {
|
||||
let biome = self.biome_generator.generate_biome(
|
||||
@ -63,4 +116,4 @@ impl<B: BiomeGenerator, T: TerrainGenerator> WorldGenerator for GenericGenerator
|
||||
position: at,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@ -1 +1,2 @@
|
||||
pub mod overworld;
|
||||
pub mod superflat;
|
||||
@ -0,0 +1 @@
|
||||
pub mod plains;
|
||||
@ -0,0 +1,60 @@
|
||||
use noise::Perlin;
|
||||
use pumpkin_core::math::vector2::Vector2;
|
||||
|
||||
use crate::{
|
||||
biome::Biome,
|
||||
block::BlockId,
|
||||
coordinates::{BlockCoordinates, XZBlockCoordinates},
|
||||
world_gen::{
|
||||
generator::{BiomeGenerator, GeneratorInit, PerlinTerrainGenerator},
|
||||
generic_generator::GenericGenerator,
|
||||
Seed,
|
||||
},
|
||||
};
|
||||
|
||||
pub type PlainsGenerator = GenericGenerator<PlainsBiomeGenerator, PlainsTerrainGenerator>;
|
||||
|
||||
pub(crate) struct PlainsBiomeGenerator {}
|
||||
|
||||
impl GeneratorInit for PlainsBiomeGenerator {
|
||||
fn new(_: Seed) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl BiomeGenerator for PlainsBiomeGenerator {
|
||||
// TODO make generic over Biome and allow changing the Biome in the config.
|
||||
fn generate_biome(&self, _: XZBlockCoordinates) -> Biome {
|
||||
Biome::Plains
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PlainsTerrainGenerator {}
|
||||
|
||||
impl GeneratorInit for PlainsTerrainGenerator {
|
||||
fn new(_: Seed) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl PerlinTerrainGenerator for PlainsTerrainGenerator {
|
||||
fn prepare_chunk(&self, _at: &Vector2<i32>, _perlin: &Perlin) {}
|
||||
// TODO allow specifying which blocks should be at which height in the config.
|
||||
fn generate_block(&self, at: BlockCoordinates, chunk_height: i16, _: Biome) -> BlockId {
|
||||
let begin_stone_height = chunk_height - 5;
|
||||
let begin_dirt_height = chunk_height - 1;
|
||||
|
||||
let y = *at.y;
|
||||
if y == -64 {
|
||||
BlockId::from_id(79) // BEDROCK
|
||||
} else if y >= -63 && y <= begin_stone_height {
|
||||
return BlockId::from_id(1); // STONE
|
||||
} else if y >= begin_stone_height && y < begin_dirt_height {
|
||||
return BlockId::from_id(10); // DIRT;
|
||||
} else if y == chunk_height - 1 {
|
||||
return BlockId::from_id(9); // GRASS BLOCK
|
||||
} else {
|
||||
BlockId::AIR
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
pub mod biome;
|
||||
@ -1,3 +1,5 @@
|
||||
use pumpkin_core::math::vector2::Vector2;
|
||||
|
||||
use crate::{
|
||||
biome::Biome,
|
||||
block::BlockId,
|
||||
@ -9,7 +11,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
pub type SuperflatGenerator = GenericGenerator<SuperflatBiomeGenerator, SuperflatTerrainGenerator>;
|
||||
|
||||
pub(crate) struct SuperflatBiomeGenerator {}
|
||||
@ -36,6 +38,7 @@ impl GeneratorInit for SuperflatTerrainGenerator {
|
||||
}
|
||||
|
||||
impl TerrainGenerator for SuperflatTerrainGenerator {
|
||||
fn prepare_chunk(&self, _at: &Vector2<i32>) {}
|
||||
// TODO allow specifying which blocks should be at which height in the config.
|
||||
fn generate_block(&self, at: BlockCoordinates, _: Biome) -> BlockId {
|
||||
match *at.y {
|
||||
@ -1,16 +1,15 @@
|
||||
mod generator;
|
||||
mod generic_generator;
|
||||
mod implementations;
|
||||
mod implementation;
|
||||
mod seed;
|
||||
|
||||
pub use generator::WorldGenerator;
|
||||
use implementation::overworld::biome::plains::PlainsGenerator;
|
||||
pub use seed::Seed;
|
||||
|
||||
use generator::GeneratorInit;
|
||||
use implementations::superflat::SuperflatGenerator;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_world_gen(seed: Seed) -> Box<dyn WorldGenerator> {
|
||||
// TODO decide which WorldGenerator to pick based on config.
|
||||
Box::new(SuperflatGenerator::new(seed))
|
||||
Box::new(PlainsGenerator::new(seed))
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Seed(pub i64);
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@ pumpkin-registry = { path = "../pumpkin-registry"}
|
||||
# config
|
||||
serde.workspace = true
|
||||
serde_json = "1.0"
|
||||
toml = "0.8.19"
|
||||
|
||||
bytes = "1.7"
|
||||
|
||||
@ -29,7 +28,7 @@ rand = "0.8.5"
|
||||
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.4"
|
||||
num-bigint = "0.4.6"
|
||||
num-bigint = "0.4"
|
||||
|
||||
ctrlc = "3.4"
|
||||
|
||||
@ -47,7 +46,7 @@ digest = "=0.11.0-pre.9"
|
||||
hmac = "0.12.1"
|
||||
sha2 = "0.10.8"
|
||||
|
||||
thiserror = "1.0.63"
|
||||
thiserror = "1.0"
|
||||
|
||||
# icon loading
|
||||
base64 = "0.22.1"
|
||||
@ -59,7 +58,6 @@ log.workspace = true
|
||||
|
||||
# networking
|
||||
mio = { version = "1.0.2", features = ["os-poll", "net"]}
|
||||
crossbeam-channel = "0.5.13"
|
||||
|
||||
uuid.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
@ -13,8 +13,8 @@ use uuid::Uuid;
|
||||
use crate::server::Server;
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(dead_code)]
|
||||
#[expect(non_snake_case)]
|
||||
#[expect(dead_code)]
|
||||
pub struct ProfileTextures {
|
||||
timestamp: i64,
|
||||
profileId: Uuid,
|
||||
@ -24,8 +24,7 @@ pub struct ProfileTextures {
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
pub struct Texture {
|
||||
url: String,
|
||||
metadata: Option<HashMap<String, String>>,
|
||||
|
||||
@ -72,7 +72,7 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
)));
|
||||
} else {
|
||||
// TODO
|
||||
#[allow(clippy::let_underscore_future)]
|
||||
#[expect(clippy::let_underscore_future)]
|
||||
let _ = target.set_gamemode(gamemode);
|
||||
target.send_system_message(TextComponent::text(&format!(
|
||||
"Game mode was set to {:?}",
|
||||
@ -97,7 +97,7 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
)));
|
||||
} else {
|
||||
// TODO
|
||||
#[allow(clippy::let_underscore_future)]
|
||||
#[expect(clippy::let_underscore_future)]
|
||||
let _ = target.set_gamemode(gamemode);
|
||||
target.send_system_message(TextComponent::text(&format!(
|
||||
"Game mode was set to {:?}",
|
||||
|
||||
@ -23,8 +23,9 @@ pub(crate) enum NodeType<'a> {
|
||||
run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
||||
+ Sync),
|
||||
},
|
||||
#[allow(dead_code)] // todo: remove (so far no commands requiring this are implemented)
|
||||
Literal { string: &'a str },
|
||||
Literal {
|
||||
string: &'a str,
|
||||
},
|
||||
Argument {
|
||||
name: &'a str,
|
||||
consumer: ArgumentConsumer<'a>,
|
||||
|
||||
@ -131,7 +131,7 @@ impl<'a> NonLeafNodeBuilder<'a> {
|
||||
}
|
||||
|
||||
/// Matches a sting literal.
|
||||
#[allow(dead_code)] // todo: remove (so far no commands requiring this are implemented)
|
||||
#[expect(dead_code)] // todo: remove (so far no commands requiring this are implemented)
|
||||
pub fn literal(string: &str) -> NonLeafNodeBuilder {
|
||||
NonLeafNodeBuilder {
|
||||
node_type: NodeType::Literal { string },
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
#![allow(clippy::await_holding_refcell_ref)]
|
||||
#![allow(clippy::await_holding_lock)]
|
||||
#![expect(clippy::await_holding_lock)]
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
compile_error!("Compiling for WASI targets is not supported!");
|
||||
|
||||
@ -52,7 +52,7 @@ pub fn receive_plugin_response(
|
||||
buf.put_slice(data_without_signature);
|
||||
|
||||
// check velocity version
|
||||
let version = buf.get_var_int();
|
||||
let version = buf.get_var_int().unwrap();
|
||||
let version = version.0;
|
||||
if version > MAX_SUPPORTED_FORWARDING_VERSION {
|
||||
client.kick(&format!(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user