Skip to content

Commit

Permalink
Implement noteblocks for direct backend
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul1365972 committed Dec 14, 2023
1 parent 70d1e58 commit 16a211e
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 18 deletions.
4 changes: 4 additions & 0 deletions crates/blocks/src/blocks/props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,3 +542,7 @@ impl FromStr for Instrument {
})
}
}

pub fn noteblock_note_to_pitch(note: u32) -> f32 {
f32::powf(2.0, (note as f32 - 12.0) / 12.0)
}
72 changes: 67 additions & 5 deletions crates/core/src/redpiler/backend/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::redpiler::compile_graph::{CompileGraph, LinkType, NodeIdx};
use crate::redpiler::{block_powered_mut, bool_to_ss};
use crate::world::World;
use mchprs_blocks::block_entities::BlockEntity;
use mchprs_blocks::blocks::{Block, ComparatorMode};
use mchprs_blocks::blocks::{noteblock_note_to_pitch, Block, ComparatorMode, Instrument};
use mchprs_blocks::BlockPos;
use mchprs_world::{TickEntry, TickPriority};
use nodes::{NodeId, Nodes};
Expand All @@ -28,7 +28,7 @@ mod nodes {
use super::Node;
use std::ops::{Index, IndexMut};

#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct NodeId(u32);

impl NodeId {
Expand Down Expand Up @@ -136,6 +136,7 @@ enum NodeType {
Trapdoor,
Wire,
Constant,
NoteBlock,
}

impl NodeType {
Expand All @@ -147,6 +148,7 @@ impl NodeType {
| NodeType::Lever
| NodeType::Trapdoor
| NodeType::PressurePlate
| NodeType::NoteBlock { .. }
)
}
}
Expand Down Expand Up @@ -185,6 +187,7 @@ impl Node {
node_idx: NodeIdx,
nodes_len: usize,
nodes_map: &FxHashMap<NodeIdx, usize>,
noteblock_map: &mut FxHashMap<NodeId, (BlockPos, Instrument, u32)>,
stats: &mut FinalGraphStats,
) -> Self {
let node = &graph[node_idx];
Expand Down Expand Up @@ -261,6 +264,16 @@ impl Node {
CNodeType::Trapdoor => NodeType::Trapdoor,
CNodeType::Wire => NodeType::Wire,
CNodeType::Constant => NodeType::Constant,
CNodeType::NoteBlock { instrument, note } => {
let idx = nodes_map[&node_idx];
assert!(idx < nodes_len);
let idx = unsafe {
// Safety: bounds checked
NodeId::from_index(idx)
};
noteblock_map.insert(idx, (node.block.unwrap().0, instrument, note));
NodeType::NoteBlock
}
};

Node {
Expand Down Expand Up @@ -360,12 +373,18 @@ impl TickScheduler {
}
}

enum Event {
NoteBlockPlay(NodeId),
}

#[derive(Default)]
pub struct DirectBackend {
nodes: Nodes,
blocks: Vec<Option<(BlockPos, Block)>>,
pos_map: FxHashMap<BlockPos, NodeId>,
scheduler: TickScheduler,
events: Vec<Event>,
noteblock_map: FxHashMap<NodeId, (BlockPos, Instrument, u32)>,
}

impl DirectBackend {
Expand Down Expand Up @@ -407,7 +426,12 @@ impl DirectBackend {
*inputs.ss_counts.get_unchecked_mut(new_power as usize) += 1;
}

update_node(&mut self.scheduler, &mut self.nodes, update);
update_node(
&mut self.scheduler,
&mut self.events,
&mut self.nodes,
update,
);
}
}
}
Expand Down Expand Up @@ -575,7 +599,16 @@ impl JITBackend for DirectBackend {
let mut stats = FinalGraphStats::default();
let nodes = graph
.node_indices()
.map(|idx| Node::from_compile_node(&graph, idx, nodes_len, &nodes_map, &mut stats))
.map(|idx| {
Node::from_compile_node(
&graph,
idx,
nodes_len,
&nodes_map,
&mut self.noteblock_map,
&mut stats,
)
})
.collect();
stats.nodes_bytes = nodes_len * std::mem::size_of::<Node>();
trace!("{:#?}", stats);
Expand Down Expand Up @@ -604,6 +637,20 @@ impl JITBackend for DirectBackend {
}

fn flush<W: World>(&mut self, world: &mut W, io_only: bool) {
for event in self.events.drain(..) {
match event {
Event::NoteBlockPlay(node_id) => {
let &(pos, instrument, note) = self.noteblock_map.get(&node_id).unwrap();
world.play_sound(
pos,
instrument.to_sound_id(),
2, // Sound Caregory ID for Records
3.0,
noteblock_note_to_pitch(note),
);
}
}
}
for (i, node) in self.nodes.inner_mut().iter_mut().enumerate() {
let Some((pos, block)) = &mut self.blocks[i] else {
continue;
Expand Down Expand Up @@ -679,7 +726,12 @@ fn get_all_input(node: &Node) -> (u8, u8) {
}

#[inline(always)]
fn update_node(scheduler: &mut TickScheduler, nodes: &mut Nodes, node_id: NodeId) {
fn update_node(
scheduler: &mut TickScheduler,
sound_events: &mut Vec<Event>,
nodes: &mut Nodes,
node_id: NodeId,
) {
let node = &nodes[node_id];

match node.ty {
Expand Down Expand Up @@ -773,6 +825,16 @@ fn update_node(scheduler: &mut TickScheduler, nodes: &mut Nodes, node_id: NodeId
set_node(node, should_be_powered);
}
}
NodeType::NoteBlock { .. } => {
let should_be_powered = get_bool_input(node);
if node.powered != should_be_powered {
let node = &mut nodes[node_id];
set_node(node, should_be_powered);
if should_be_powered {
sound_events.push(Event::NoteBlockPlay(node_id));
}
}
}
NodeType::Wire => {
let (input_power, _) = get_all_input(node);
if node.output_power != input_power {
Expand Down
8 changes: 6 additions & 2 deletions crates/core/src/redpiler/compile_graph.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use mchprs_blocks::blocks::ComparatorMode;
use mchprs_blocks::blocks::{ComparatorMode, Instrument};
use mchprs_blocks::BlockPos;
use petgraph::stable_graph::{NodeIndex, StableGraph};

Expand All @@ -16,11 +16,15 @@ pub enum NodeType {
Trapdoor,
Wire,
Constant,
NoteBlock { instrument: Instrument, note: u32 },
}

impl NodeType {
pub fn is_output(self) -> bool {
matches!(self, NodeType::Lamp | NodeType::Trapdoor)
matches!(
self,
NodeType::Lamp | NodeType::Trapdoor | NodeType::NoteBlock { .. }
)
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/core/src/redpiler/passes/export_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ fn convert_node(
CNodeType::Trapdoor => NodeType::Trapdoor,
CNodeType::Wire => NodeType::Wire,
CNodeType::Constant => NodeType::Constant,
CNodeType::NoteBlock { .. } => NodeType::NoteBlock,
},
block: node.block.map(|(pos, id)| {
(
Expand Down
16 changes: 14 additions & 2 deletions crates/core/src/redpiler/passes/identify_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use crate::redpiler::{CompilerInput, CompilerOptions};
use crate::redstone;
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;
use mchprs_blocks::blocks::{Block, Instrument, RedstoneComparator, RedstoneRepeater};
use mchprs_blocks::{BlockFace, BlockPos};

pub struct IdentifyNodes;

Expand Down Expand Up @@ -113,6 +113,18 @@ fn identify_block<W: World>(
}
Block::IronTrapdoor { powered, .. } => (NodeType::Trapdoor, NodeState::simple(powered)),
Block::RedstoneBlock {} => (NodeType::Constant, NodeState::ss(15)),
Block::NoteBlock {
instrument: _,
note,
powered,
} if world.get_block(pos.offset(BlockFace::Top)) == (Block::Air {}) => {
let below = world.get_block(pos.offset(BlockFace::Bottom));
let instrument = Instrument::from_block_below(below);
(
NodeType::NoteBlock { instrument, note },
NodeState::simple(powered),
)
}
block if redstone::has_comparator_override(block) => (
NodeType::Constant,
NodeState::ss(redstone::get_comparator_override(block, world, pos)),
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/redpiler/passes/input_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ impl<'a, W: World> InputSearchState<'a, W> {
Block::RedstoneWire { .. } => {
self.search_wire(id, pos, LinkType::Default, 0);
}
Block::RedstoneLamp { .. } | Block::IronTrapdoor { .. } => {
Block::RedstoneLamp { .. } | Block::IronTrapdoor { .. } | Block::NoteBlock { .. } => {
for face in &BlockFace::values() {
let neighbor_pos = pos.offset(*face);
let neighbor_block = self.world.get_block(neighbor_pos);
Expand Down
13 changes: 10 additions & 3 deletions crates/core/src/redstone/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod wire;

use crate::world::World;
use mchprs_blocks::block_entities::BlockEntity;
use mchprs_blocks::blocks::{Block, ButtonFace, Instrument, LeverFace};
use mchprs_blocks::blocks::{noteblock_note_to_pitch, Block, ButtonFace, Instrument, LeverFace};
use mchprs_blocks::{BlockDirection, BlockFace, BlockPos};
use mchprs_world::TickPriority;

Expand Down Expand Up @@ -233,18 +233,25 @@ pub fn update(block: Block, world: &mut impl World, pos: BlockPos) {
powered: should_be_powered,
};

world.set_block(pos, new_block);
// TODO: There is a weird double activation bug, so we need to check if block is not already powered
let is_not_powered = matches!(
world.get_block(pos),
Block::NoteBlock { powered: false, .. }
);

if should_be_powered
&& is_not_powered
&& world.get_block(pos.offset(BlockFace::Top)) == (Block::Air {})
{
world.play_sound(
pos,
instrument.to_sound_id(),
2, // Sound Caregory ID for Records
3.0,
f32::powf(2.0, (note as f32 - 12.0) / 12.0),
noteblock_note_to_pitch(note),
);
}
world.set_block(pos, new_block);
}
}
_ => {}
Expand Down
11 changes: 6 additions & 5 deletions crates/core/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ pub trait World {
false
}

#[allow(unused_variables)]
fn play_sound(
&mut self,
_pos: BlockPos,
_sound_id: i32,
_sound_category: i32,
_volume: f32,
_pitch: f32,
pos: BlockPos,
sound_id: i32,
sound_category: i32,
volume: f32,
pitch: f32,
) {
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/redpiler_graph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub enum NodeType {
Trapdoor,
Wire,
Constant,
NoteBlock,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
Expand Down

0 comments on commit 16a211e

Please sign in to comment.