Skip to content

Commit

Permalink
Merge branch 'master' into mobs
Browse files Browse the repository at this point in the history
  • Loading branch information
OfficialKris committed Dec 26, 2024
2 parents 705eb71 + febbfd8 commit 2c84e70
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 46 deletions.
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM rust:1-alpine3.20 AS builder
FROM rust:1-alpine3.21 AS builder
ARG GIT_VERSION=Docker
ENV GIT_VERSION=$GIT_VERSION
ENV RUSTFLAGS="-C target-feature=-crt-static -C target-cpu=native"
ENV RUSTFLAGS="-C target-feature=-crt-static"
RUN apk add --no-cache musl-dev

WORKDIR /pumpkin
Expand All @@ -16,7 +16,7 @@ RUN --mount=type=cache,sharing=private,target=/pumpkin/target \
# strip debug symbols from binary
RUN strip pumpkin.release

FROM alpine:3.20
FROM alpine:3.21

# Identifying information for registries like ghcr.io
LABEL org.opencontainers.image.source=https://github.com/Snowiiii/Pumpkin
Expand Down
8 changes: 6 additions & 2 deletions pumpkin-inventory/src/drag_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,12 @@ impl DragHandler {
let changing_slots =
drag.possibly_changing_slots(&slots_cloned, carried_item.item_id);
let amount_of_slots = changing_slots.clone().count();
let (amount_per_slot, remainder) =
(carried_item.item_count as usize).div_rem_euclid(&amount_of_slots);
let (amount_per_slot, remainder) = if amount_of_slots == 0 {
// TODO: please work lol
(1, 0)
} else {
(carried_item.item_count as usize).div_rem_euclid(&amount_of_slots)
};
let mut item_in_each_slot = *carried_item;
item_in_each_slot.item_count = amount_per_slot as u8;
changing_slots.for_each(|slot| *slots[slot] = Some(item_in_each_slot));
Expand Down
10 changes: 5 additions & 5 deletions pumpkin/src/command/args/arg_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ impl ArgumentConsumer for CommandTreeArgumentConsumer {
) -> Option<Arg<'a>> {
let s = args.pop()?;

let dispatcher = &server.command_dispatcher;
return dispatcher
let dispatcher = server.command_dispatcher.read().await;
dispatcher
.get_tree(s)
.map_or_else(|_| None, |tree| Some(Arg::CommandTree(tree)));
.map_or_else(|_| None, |tree| Some(Arg::CommandTree(tree)))
}

async fn suggest<'a>(
Expand All @@ -53,8 +53,8 @@ impl ArgumentConsumer for CommandTreeArgumentConsumer {
return Ok(None);
};

let suggestions = server
.command_dispatcher
let dispatcher = server.command_dispatcher.read().await;
let suggestions = dispatcher
.commands
.keys()
.filter(|suggestion| suggestion.starts_with(input))
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/src/command/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub(crate) enum Arg<'a> {
Pos2D(Vector2<f64>),
Rotation(f32, f32),
GameMode(GameMode),
CommandTree(&'a CommandTree<'a>),
CommandTree(CommandTree<'a>),
Item(&'a str),
ResourceLocation(&'a str),
Block(&'a str),
Expand Down
8 changes: 5 additions & 3 deletions pumpkin/src/command/client_cmd_suggestions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::sync::Arc;

use pumpkin_protocol::client::play::{CCommands, ProtoNode, ProtoNodeType};
use tokio::sync::RwLock;

use crate::entity::player::Player;

Expand All @@ -11,11 +12,12 @@ use super::{

pub async fn send_c_commands_packet<'a>(
player: &Arc<Player>,
dispatcher: &'a CommandDispatcher<'a>,
dispatcher: &RwLock<CommandDispatcher<'a>>,
) {
let cmd_src = super::CommandSender::Player(player.clone());
let mut first_level = Vec::new();

let dispatcher = dispatcher.read().await;
for key in dispatcher.commands.keys() {
let Ok(tree) = dispatcher.get_tree(key) else {
continue;
Expand Down Expand Up @@ -72,8 +74,8 @@ impl<'a> ProtoNodeBuilder<'a> {

fn nodes_to_proto_node_builders<'a>(
cmd_src: &super::CommandSender,
nodes: &'a [Node<'a>],
children: &'a [usize],
nodes: &[Node<'a>],
children: &[usize],
) -> (bool, Vec<ProtoNodeBuilder<'a>>) {
let mut child_nodes = Vec::new();
let mut is_executable = false;
Expand Down
4 changes: 2 additions & 2 deletions pumpkin/src/command/commands/cmd_help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ impl CommandExecutor for BaseHelpExecutor {
}
};

let mut commands: Vec<&CommandTree> = server
.command_dispatcher
let dispatcher = server.command_dispatcher.read().await;
let mut commands: Vec<&CommandTree> = dispatcher
.commands
.values()
.filter_map(|cmd| match cmd {
Expand Down
24 changes: 18 additions & 6 deletions pumpkin/src/command/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl<'a> CommandDispatcher<'a> {
// try paths and collect the nodes that fail
// todo: make this more fine-grained
for path in tree.iter_paths() {
match Self::try_find_suggestions_on_path(src, server, &path, tree, &mut raw_args, cmd)
match Self::try_find_suggestions_on_path(src, server, &path, &tree, &mut raw_args, cmd)
.await
{
Err(InvalidConsumption(s)) => {
Expand Down Expand Up @@ -151,7 +151,7 @@ impl<'a> CommandDispatcher<'a> {

// try paths until fitting path is found
for path in tree.iter_paths() {
if Self::try_is_fitting_path(src, server, &path, tree, &mut raw_args.clone()).await? {
if Self::try_is_fitting_path(src, server, &path, &tree, &mut raw_args.clone()).await? {
return Ok(());
}
}
Expand All @@ -160,22 +160,22 @@ impl<'a> CommandDispatcher<'a> {
)))
}

pub(crate) fn get_tree(&'a self, key: &str) -> Result<&'a CommandTree<'a>, CommandError> {
pub(crate) fn get_tree(&self, key: &str) -> Result<CommandTree<'a>, CommandError> {
let command = self
.commands
.get(key)
.ok_or(GeneralCommandIssue("Command not found".to_string()))?;

match command {
Command::Tree(tree) => Ok(tree),
Command::Tree(tree) => Ok(tree.clone()),
Command::Alias(target) => {
let Some(Command::Tree(tree)) = &self.commands.get(target) else {
let Some(Command::Tree(tree)) = self.commands.get(target) else {
log::error!("Error while parsing command alias \"{key}\": pointing to \"{target}\" which is not a valid tree");
return Err(GeneralCommandIssue(
"Internal Error (See logs for details)".into(),
));
};
Ok(tree)
Ok(tree.clone())
}
}
}
Expand Down Expand Up @@ -282,3 +282,15 @@ impl<'a> CommandDispatcher<'a> {
self.commands.insert(primary_name, Command::Tree(tree));
}
}

#[cfg(test)]
mod test {
use crate::command::{default_dispatcher, tree::CommandTree};

#[test]
fn test_dynamic_command() {
let mut dispatcher = default_dispatcher();
let tree = CommandTree::new(["test"], "test_desc");
dispatcher.register(tree);
}
}
4 changes: 2 additions & 2 deletions pumpkin/src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl<'a> CommandSender<'a> {
}

#[must_use]
pub fn default_dispatcher<'a>() -> Arc<CommandDispatcher<'a>> {
pub fn default_dispatcher<'a>() -> CommandDispatcher<'a> {
let mut dispatcher = CommandDispatcher::default();

dispatcher.register(cmd_pumpkin::init_command_tree());
Expand All @@ -129,7 +129,7 @@ pub fn default_dispatcher<'a>() -> Arc<CommandDispatcher<'a>> {
dispatcher.register(cmd_transfer::init_command_tree());
dispatcher.register(cmd_fill::init_command_tree());

Arc::new(dispatcher)
dispatcher
}

#[async_trait]
Expand Down
5 changes: 3 additions & 2 deletions pumpkin/src/command/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ use std::{collections::VecDeque, fmt::Debug};
/// see [`crate::commands::tree_builder::argument`]
pub type RawArgs<'a> = Vec<&'a str>;

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Node<'a> {
pub(crate) children: Vec<usize>,
pub(crate) node_type: NodeType<'a>,
}

#[derive(Clone)]
pub enum NodeType<'a> {
ExecuteLeaf {
executor: &'a dyn CommandExecutor,
Expand Down Expand Up @@ -50,7 +51,7 @@ pub enum Command<'a> {
Alias(&'a str),
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct CommandTree<'a> {
pub(crate) nodes: Vec<Node<'a>>,
pub(crate) children: Vec<usize>,
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ fn setup_console(server: Arc<Server>) {
.expect("Failed to read console line");

if !out.is_empty() {
let dispatcher = server.command_dispatcher.clone();
let dispatcher = server.command_dispatcher.read().await;
dispatcher
.handle_command(&mut command::CommandSender::Console, &server, &out)
.await;
Expand Down
36 changes: 23 additions & 13 deletions pumpkin/src/net/packet/play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use pumpkin_protocol::{
SSetCreativeSlot, SSetHeldItem, SSwingArm, SUseItemOn, Status,
},
};
use pumpkin_world::block::block_registry::Block;
use pumpkin_world::item::item_registry::get_item_by_id;
use pumpkin_world::{
block::{block_registry::get_block_by_item, BlockFace},
Expand Down Expand Up @@ -293,7 +294,7 @@ impl Player {
server: &Arc<Server>,
command: SChatCommand,
) {
let dispatcher = server.command_dispatcher.clone();
let dispatcher = server.command_dispatcher.read().await;
dispatcher
.handle_command(
&mut CommandSender::Player(self.clone()),
Expand Down Expand Up @@ -747,7 +748,7 @@ impl Player {
// check if item is a block, Because Not every item can be placed :D
if let Some(block) = get_block_by_item(item_stack.item_id) {
should_try_decrement = self
.run_is_block_place(block.default_state_id, use_item_on, location, &face)
.run_is_block_place(block.clone(), server, use_item_on, location, &face)
.await?;
}
// check if item is a spawn egg
Expand Down Expand Up @@ -779,11 +780,10 @@ impl Player {
&mut state_id,
)
.await;

// drop(inventory);
}
}
}

Ok(())
} else {
Err(BlockPlacingError::InvalidBlockFace.into())
Expand Down Expand Up @@ -870,10 +870,8 @@ impl Player {
return;
};

let suggestions = server
.command_dispatcher
.find_suggestions(&mut src, server, cmd)
.await;
let dispatcher = server.command_dispatcher.read().await;
let suggestions = dispatcher.find_suggestions(&mut src, server, cmd).await;

let response = CCommandSuggestions::new(
packet.id,
Expand Down Expand Up @@ -941,7 +939,8 @@ impl Player {

async fn run_is_block_place(
&self,
block: u16,
block: Block,
server: &Server,
use_item_on: SUseItemOn,
location: WorldPosition,
face: &BlockFace,
Expand Down Expand Up @@ -974,10 +973,21 @@ impl Player {
}

let block_bounding_box = BoundingBox::from_block(&world_pos);
let bounding_box = entity.bounding_box.load();
//TODO: Make this check for every entity in that posistion
if !bounding_box.intersects(&block_bounding_box) {
world.set_block_state(world_pos, block).await;
let mut intersects = false;
for player in world.get_nearby_players(entity.pos.load(), 20).await {
let bounding_box = player.1.living_entity.entity.bounding_box.load();
if bounding_box.intersects(&block_bounding_box) {
intersects = true;
}
}
if !intersects {
world
.set_block_state(world_pos, block.default_state_id)
.await;
server
.block_manager
.on_placed(&block, self, world_pos, server)
.await;
}
self.client
.send_packet(&CAcknowledgeBlockChange::new(use_item_on.sequence))
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/src/net/rcon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl RCONClient {
ServerboundPacket::ExecCommand => {
if self.logged_in {
let output = tokio::sync::Mutex::new(Vec::new());
let dispatcher = server.command_dispatcher.clone();
let dispatcher = server.command_dispatcher.read().await;
dispatcher
.handle_command(
&mut crate::command::CommandSender::Rcon(&output),
Expand Down
4 changes: 2 additions & 2 deletions pumpkin/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub struct Server {
/// Saves server branding information.
server_branding: CachedBranding,
/// Saves and Dispatches commands to appropriate handlers.
pub command_dispatcher: Arc<CommandDispatcher<'static>>,
pub command_dispatcher: RwLock<CommandDispatcher<'static>>,
/// Saves and calls blocks blocks
pub block_manager: Arc<BlockManager>,
/// Manages multiple worlds within the server.
Expand Down Expand Up @@ -85,7 +85,7 @@ impl Server {
});

// First register default command, after that plugins can put in their own
let command_dispatcher = default_dispatcher();
let command_dispatcher = RwLock::new(default_dispatcher());

let world = World::load(
Dimension::OverWorld.into_level(
Expand Down
Loading

0 comments on commit 2c84e70

Please sign in to comment.