Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor QoL fixes and major compile time improvements #131

Merged
merged 5 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ server_context = "global"
### General Commands
| Command | Alias | Description |
| --- | --- |--- |
| `/rtps [rtps]` | None | Set the **redstone** ticks per second in the plot to `[rtps]`. (There are two game ticks in a redstone tick) |
| `/rtps [rtps\|unlimited]` | None | Set the **redstone** ticks per second in the plot to `[rtps]`. (There are two game ticks in a redstone tick) |
| `/radvance [ticks]` | `/radv` | Advances the plot by `[ticks]` redstone ticks. |
| `/teleport [player]` | `/tp` | Teleports you to `[player]`. |
| `/teleport [x] [y] [z]` | `/tp` | Teleports you to `[x] [y] [z]`. Supports relative coordinates. Floats can be expressed as described [here](https://doc.rust-lang.org/std/primitive.f64.html#grammar). |
Expand Down Expand Up @@ -122,7 +122,7 @@ These are the commands that are currently implemented:
| `//replace` | None | Replace all blocks in a selection with another |
| `//copy` | `//c` | Copy the selection to the clipboard |
| `//cut` | `//x` | Cut the selection to the clipboard |
| `//paste` | `//v` | Paste the clipboard's contents |
| `//paste` | `//v` | Paste the clipboard's contents (`-a` to copy air, `-u` to also update) |
Paul1365972 marked this conversation as resolved.
Show resolved Hide resolved
| `//undo` | None | Undoes the last action (from history) |
| `//redo` | None | Redoes the last action (from history) |
| `//rstack` | `//rs` | Stack with more options, Refer to [RedstoneTools](https://github.com/paulikauro/RedstoneTools) |
Expand All @@ -136,7 +136,7 @@ These are the commands that are currently implemented:
| `//shift` | None | Shift the selection area |
| `//flip` | `//f` | Flip the contents of the clipboard across the origin |
| `//rotate` | `//r` | Rotate the contents of the clipboard |
| `//update` | None | Updates all blocks in the selection |
| `//update` | None | Updates all blocks in the selection or entire plot |
| `//help` | None | Displays help for WorldEdit commands |

## Acknowledgments
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/plot/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ impl Plot {
return false;
}
Tps::Limited(tps)
} else if args[0] == "unlimited" {
} else if !args[0].is_empty() && "unlimited".starts_with(args[0]) {
Tps::Unlimited
} else {
self.players[player].send_error_message("Unable to parse rtps!");
Expand Down
2 changes: 0 additions & 2 deletions crates/core/src/plot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ impl World for PlotWorld {
)
}


/// Returns the block state id of the block at `pos`
fn get_block_raw(&self, pos: BlockPos) -> u32 {
let chunk_index = match self.get_chunk_index_for_block(pos.x, pos.z) {
Expand All @@ -173,7 +172,6 @@ impl World for PlotWorld {
chunk.get_block((pos.x & 0xF) as u32, pos.y as u32, (pos.z & 0xF) as u32)
}


fn delete_block_entity(&mut self, pos: BlockPos) {
let chunk_index = match self.get_chunk_index_for_block(pos.x, pos.z) {
Some(idx) => idx,
Expand Down
47 changes: 23 additions & 24 deletions crates/core/src/plot/worldedit/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::chat::{ChatComponentBuilder, ColorCode};
use crate::config::CONFIG;
use crate::player::PacketSender;
use crate::plot::PLOT_BLOCK_HEIGHT;
use crate::redstone;
use crate::utils::HyphenatedUUID;
use mchprs_blocks::block_entities::InventoryEntry;
use mchprs_blocks::blocks::{Block, FlipDirection, RotateAmt};
Expand Down Expand Up @@ -235,17 +234,17 @@ pub(super) fn execute_paste(ctx: CommandExecuteContext<'_>) {
let offset_x = pos.x - cb.offset_x;
let offset_y = pos.y - cb.offset_y;
let offset_z = pos.z - cb.offset_z;
capture_undo(
ctx.plot,
ctx.player,
BlockPos::new(offset_x, offset_y, offset_z),
BlockPos::new(
offset_x + cb.size_x as i32,
offset_y + cb.size_y as i32,
offset_z + cb.size_z as i32,
),
let first_pos = BlockPos::new(offset_x, offset_y, offset_z);
let second_pos = BlockPos::new(
offset_x + cb.size_x as i32,
offset_y + cb.size_y as i32,
offset_z + cb.size_z as i32,
);
capture_undo(ctx.plot, ctx.player, first_pos, second_pos);
paste_clipboard(ctx.plot, cb, pos, ctx.has_flag('a'));
if ctx.has_flag('u') {
update(ctx.plot, first_pos, second_pos);
}
ctx.player.send_worldedit_message(&format!(
"Your clipboard was pasted. ({:?})",
start_time.elapsed()
Expand Down Expand Up @@ -993,21 +992,21 @@ pub(super) fn execute_rstack(ctx: CommandExecuteContext<'_>) {
pub(super) fn execute_update(ctx: CommandExecuteContext<'_>) {
let start_time = Instant::now();

let operation = worldedit_start_operation(ctx.player);
for x in operation.x_range() {
for y in operation.y_range() {
for z in operation.z_range() {
let block_pos = BlockPos::new(x, y, z);
let block = ctx.plot.get_block(block_pos);
redstone::update(block, ctx.plot, block_pos);
}
}
}
let pos = match (ctx.player.first_position, ctx.player.second_position) {
(None, None) => Some(ctx.plot.get_corners()),
(Some(first_pos), Some(second_pos)) => Some((first_pos, second_pos)),
_ => None,
};
if let Some((first_pos, second_pos)) = pos {
update(ctx.plot, first_pos, second_pos);

ctx.player.send_worldedit_message(&format!(
"Your selection was updated sucessfully. ({:?})",
start_time.elapsed()
));
ctx.player.send_worldedit_message(&format!(
"Your selection was updated sucessfully. ({:?})",
start_time.elapsed()
));
} else {
ctx.player.send_error_message("Your selection is incomplete.");
}
}

pub(super) fn execute_replace_container(ctx: CommandExecuteContext<'_>) {
Expand Down
15 changes: 12 additions & 3 deletions crates/core/src/plot/worldedit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ mod schematic;

use super::{Plot, PlotWorld};
use crate::player::{PacketSender, Player, PlayerPos};
use crate::redstone;
use crate::world::storage::PalettedBitBuffer;
use crate::world::World;
use crate::world::{World, for_each_block_mut_optimized};
use execute::*;
use mchprs_blocks::block_entities::{BlockEntity, ContainerType};
use mchprs_blocks::blocks::Block;
Expand Down Expand Up @@ -540,7 +541,8 @@ static COMMANDS: Lazy<HashMap<&'static str, WorldeditCommand>> = Lazy::new(|| {
execute_fn: execute_paste,
description: "Paste the clipboard's contents",
flags: &[
flag!('a', None, "Skip air blocks")
flag!('a', None, "Skip air blocks"),
flag!('u', None, "Also update all affected blocks"),
],
permission_node: "worldedit.clipboard.paste",
..Default::default()
Expand Down Expand Up @@ -694,7 +696,7 @@ static COMMANDS: Lazy<HashMap<&'static str, WorldeditCommand>> = Lazy::new(|| {
execute_fn: execute_update,
description: "Updates all blocks in the selection",
permission_node: "mchprs.we.update",
requires_positions: true,
requires_positions: false,
..Default::default()
},
"/help" => WorldeditCommand {
Expand Down Expand Up @@ -1136,3 +1138,10 @@ fn expand_selection(player: &mut Player, amount: BlockPos, contract: bool) {
player.worldedit_set_second_position(p2);
}
}

fn update(plot: &mut PlotWorld, first_pos: BlockPos, second_pos: BlockPos) {
for_each_block_mut_optimized(plot, first_pos, second_pos, |plot, pos| {
let block = plot.get_block(pos);
redstone::update(block, plot, pos);
});
}
19 changes: 6 additions & 13 deletions crates/core/src/redpiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod passes;

use crate::redpiler::passes::make_default_pass_manager;
use crate::redstone;
use crate::world::World;
use crate::world::{World, for_each_block_mut_optimized};
use backend::JITBackend;
use mchprs_blocks::blocks::Block;
use mchprs_blocks::BlockPos;
Expand Down Expand Up @@ -130,19 +130,12 @@ impl Compiler {

if self.options.optimize {
let (first_pos, second_pos) = bounds;
let start_pos = first_pos.min(second_pos);
let end_pos = first_pos.max(second_pos);
for y in start_pos.y..=end_pos.y {
for z in start_pos.z..=end_pos.z {
for x in start_pos.x..=end_pos.x {
let pos = BlockPos::new(x, y, z);
let block = world.get_block(pos);
if matches!(block, Block::RedstoneWire { .. }) {
redstone::update(block, world, pos);
}
}
for_each_block_mut_optimized(world, first_pos, second_pos, |world, pos| {
let block = world.get_block(pos);
if matches!(block, Block::RedstoneWire { .. }) {
redstone::update(block, world, pos);
}
}
});
}
self.options = Default::default();
}
Expand Down
14 changes: 5 additions & 9 deletions crates/core/src/redpiler/passes/identify_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::Pass;
use crate::redpiler::compile_graph::{CompileGraph, CompileNode, NodeState, NodeType};
use crate::redpiler::{CompilerInput, CompilerOptions};
use crate::redstone;
use crate::world::World;
use crate::world::{for_each_block_optimized, World};
use mchprs_blocks::block_entities::BlockEntity;
use mchprs_blocks::blocks::{Block, RedstoneComparator, RedstoneRepeater};
use mchprs_blocks::BlockPos;
Expand All @@ -32,14 +32,10 @@ impl<W: World> Pass<W> for IdentifyNodes {

let start_pos = first_pos.min(second_pos);
let end_pos = first_pos.max(second_pos);
for y in start_pos.y..=end_pos.y {
for z in start_pos.z..=end_pos.z {
for x in start_pos.x..=end_pos.x {
let pos = BlockPos::new(x, y, z);
for_pos(ignore_wires, plot, graph, pos);
}
}
}

for_each_block_optimized(plot, start_pos, end_pos, |pos| {
for_pos(ignore_wires, plot, graph, pos)
});
}

fn should_run(&self, _: &CompilerOptions) -> bool {
Expand Down
99 changes: 99 additions & 0 deletions crates/core/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,102 @@ pub trait World {
false
}
}

// TODO: I have no idea how to deduplicate this in a sane way

/// Executes the given function for each block excluding most air blocks
pub fn for_each_block_optimized<F, W: World>(
world: &W,
first_pos: BlockPos,
second_pos: BlockPos,
mut f: F,
) where
F: FnMut(BlockPos),
{
let start_x = i32::min(first_pos.x, second_pos.x);
let end_x = i32::max(first_pos.x, second_pos.x);

let start_y = i32::min(first_pos.y, second_pos.y);
let end_y = i32::max(first_pos.y, second_pos.y);

let start_z = i32::min(first_pos.z, second_pos.z);
let end_z = i32::max(first_pos.z, second_pos.z);

// Iterate over chunks
for chunk_start_x in (start_x..=end_x).step_by(16) {
for chunk_start_z in (start_z..=end_z).step_by(16) {
let chunk = world
.get_chunk(chunk_start_x.div_euclid(16), chunk_start_z.div_euclid(16))
.unwrap();
for chunk_start_y in (start_y..=end_y).step_by(16) {
// Check if the chunk even has non air blocks
if chunk.sections[chunk_start_y as usize / 16].block_count() > 0 {
// Calculate the end position of the current chunk
let chunk_end_x = i32::min(chunk_start_x + 16 - 1, end_x);
let chunk_end_y = i32::min(chunk_start_y + 16 - 1, end_y);
let chunk_end_z = i32::min(chunk_start_z + 16 - 1, end_z);

// Iterate over each position within the current chunk
for y in chunk_start_y..=chunk_end_y {
for z in chunk_start_z..=chunk_end_z {
for x in chunk_start_x..=chunk_end_x {
let pos = BlockPos::new(x, y, z);
f(pos);
}
}
}
}
}
}
}
}

/// Executes the given function for each block excluding most air blocks
pub fn for_each_block_mut_optimized<F, W: World>(
world: &mut W,
first_pos: BlockPos,
second_pos: BlockPos,
mut f: F,
) where
F: FnMut(&mut W, BlockPos),
{
let start_x = i32::min(first_pos.x, second_pos.x);
let end_x = i32::max(first_pos.x, second_pos.x);

let start_y = i32::min(first_pos.y, second_pos.y);
let end_y = i32::max(first_pos.y, second_pos.y);

let start_z = i32::min(first_pos.z, second_pos.z);
let end_z = i32::max(first_pos.z, second_pos.z);

// Iterate over chunks
for chunk_start_x in (start_x..=end_x).step_by(16) {
for chunk_start_z in (start_z..=end_z).step_by(16) {
for chunk_start_y in (start_y..=end_y).step_by(16) {
// Check if the chunk even has non air blocks
if world
.get_chunk(chunk_start_x.div_euclid(16), chunk_start_z.div_euclid(16))
.unwrap()
.sections[chunk_start_y as usize / 16]
.block_count()
> 0
{
// Calculate the end position of the current chunk
let chunk_end_x = i32::min(chunk_start_x + 16 - 1, end_x);
let chunk_end_y = i32::min(chunk_start_y + 16 - 1, end_y);
let chunk_end_z = i32::min(chunk_start_z + 16 - 1, end_z);

// Iterate over each position within the current chunk
for y in chunk_start_y..=chunk_end_y {
for z in chunk_start_z..=chunk_end_z {
for x in chunk_start_x..=chunk_end_x {
let pos = BlockPos::new(x, y, z);
f(world, pos);
}
}
}
}
}
}
}
}
7 changes: 6 additions & 1 deletion crates/core/src/world/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ impl ChunkSection {
}
&self.multi_block
}

pub fn block_count(&self) -> u32 {
self.block_count
}
}

impl Default for ChunkSection {
Expand Down Expand Up @@ -416,7 +420,8 @@ impl Chunk {
pub fn encode_packet(&self) -> PacketEncoder {
// Integer arithmetic trick: ceil(log2(x)) can be calculated with 32 - (x - 1).leading_zeros().
// See also: https://wiki.vg/Protocol#Chunk_Data_and_Update_Light
const HEIGHTMAP_BITS: u8 = (32 - ((PLOT_BLOCK_HEIGHT as u32 + 1) - 1).leading_zeros()) as u8;
const HEIGHTMAP_BITS: u8 =
(32 - ((PLOT_BLOCK_HEIGHT as u32 + 1) - 1).leading_zeros()) as u8;
let mut heightmap_buffer = BitBuffer::create(HEIGHTMAP_BITS, 16 * 16);
for x in 0..16 {
for z in 0..16 {
Expand Down
Loading