Skip to content

Commit

Permalink
feat: Track ore veins and restrict block breaking
Browse files Browse the repository at this point in the history
- Add `OreVeins` component to track mineable ore positions
- Modify block destruction system to only allow breaking tracked ore blocks
- Replace broken ore blocks with stone instead of air
- Add `derive_more` dependency for deriving Deref/DerefMut traits

This changes block breaking mechanics to only allow mining at designated ore vein
positions, replacing mined blocks with stone rather than air. Non-ore blocks will
be restored if a player attempts to break them.
  • Loading branch information
andrewgazelka committed Nov 12, 2024
1 parent ce1fb4c commit 2352773
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions events/proof-of-concept/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ tracing-tracy.workspace = true
tracing.workspace = true
rayon.workspace = true
gxhash.workspace = true
derive_more.workspace = true

[dev-dependencies]
tracing = {workspace = true, features = ["release_max_level_info"]}
Expand Down
6 changes: 6 additions & 0 deletions events/proof-of-concept/src/command/replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use gxhash::GxBuildHasher;
use hyperion::{BlockState, glam::IVec3, simulation::blocks::Blocks};
use rayon::iter::ParallelIterator;

use crate::OreVeins;

#[derive(clap::Parser, Debug)]
#[command(name = "replace")]
pub struct ReplaceCommand;
Expand Down Expand Up @@ -115,6 +117,10 @@ impl hyperion_clap::MinecraftCommand for ReplaceCommand {

let groups = group(&concrete_positions);

world.get::<&mut OreVeins>(|ore_veins| {
**ore_veins = concrete_positions;
});

for group in groups {
let ore = pick_ore();
for position in group {
Expand Down
10 changes: 10 additions & 0 deletions events/proof-of-concept/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use module::block::BlockModule;
mod component;
mod module;

use derive_more::{Deref, DerefMut};
use hyperion::glam::IVec3;
use module::{attack::AttackModule, level::LevelModule, regeneration::RegenerationModule};

use crate::{
Expand All @@ -33,10 +35,18 @@ pub struct ProofOfConceptModule;
mod command;
mod skin;

#[derive(Component, Default, Deref, DerefMut)]
struct OreVeins {
ores: gxhash::HashSet<IVec3>,
}

impl Module for ProofOfConceptModule {
fn module(world: &World) {
world.component::<component::team::Team>();

world.component::<OreVeins>();
world.set(OreVeins::default());

world
.component::<Player>()
.add_trait::<(flecs::With, component::team::Team)>();
Expand Down
58 changes: 38 additions & 20 deletions events/proof-of-concept/src/module/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ use hyperion_inventory::PlayerInventory;
use hyperion_scheduled::Scheduled;
use tracing::{error, info_span};

use crate::OreVeins;

#[derive(Component)]
pub struct BlockModule;

Expand All @@ -55,8 +57,7 @@ impl Module for BlockModule {
system!("handle_pending_air", world, &mut PendingDestruction($), &mut Blocks($), &Compose($))
.multi_threaded()
.each_iter(
move |
it: TableIter<'_, false>,
move |it: TableIter<'_, false>,
_,
(pending_air, blocks, compose): (&mut PendingDestruction, &mut Blocks, &Compose)| {
let span = info_span!("handle_pending_air");
Expand Down Expand Up @@ -102,17 +103,17 @@ impl Module for BlockModule {
.send(&world)
.unwrap();

let sound = agnostic::sound(
ident!("minecraft:entity.zombie.break_wooden_door"),
center_block.as_vec3(),
).volume(1.0)
.pitch(0.8)
.seed(fastrand::i64(..))
.build();
let sound = agnostic::sound(
ident!("minecraft:entity.zombie.break_wooden_door"),
center_block.as_vec3(),
).volume(1.0)
.pitch(0.8)
.seed(fastrand::i64(..))
.build();

compose.broadcast(&sound, SystemId(999))
.send(&world)
.unwrap();
compose.broadcast(&sound, SystemId(999))
.send(&world)
.unwrap();

blocks.set_block(position, BlockState::AIR).unwrap();
}
Expand All @@ -122,26 +123,43 @@ impl Module for BlockModule {
// todo: this is a hack. We want the system ID to be automatically assigned based on the location of the system.
let system_id = SystemId(8);

system!("handle_destroyed_blocks", world, &mut Blocks($), &mut EventQueue<event::DestroyBlock>($), &Compose($))
system!("handle_destroyed_blocks", world, &mut Blocks($), &mut EventQueue<event::DestroyBlock>($), &Compose($), &OreVeins($))
.multi_threaded()
.each_iter(move |it: TableIter<'_, false>, _, (mc, event_queue, compose): (&mut Blocks, &mut EventQueue<event::DestroyBlock>, &Compose)| {
.each_iter(move |it: TableIter<'_, false>, _, (blocks, event_queue, compose, ore_veins): (&mut Blocks, &mut EventQueue<event::DestroyBlock>, &Compose, &OreVeins)| {
let span = info_span!("handle_blocks");
let _enter = span.enter();
let world = it.world();


for event in event_queue.drain() {
let Ok(previous) = mc.set_block(event.position, BlockState::AIR) else {
blocks.to_confirm.push(EntityAndSequence {
entity: event.from,
sequence: event.sequence,
});
if !ore_veins.ores.contains(&event.position) {
let current = blocks.get_block(event.position).unwrap();

// make sure the player knows the block was placed back
let pkt = play::BlockUpdateS2c {
position: BlockPos::new(event.position.x, event.position.y, event.position.z),
block_id: current,
};

event.from.entity_view(world).get::<&NetworkStreamRef>(|stream| {
compose.unicast(&pkt, *stream, SystemId(100), &world).unwrap();
});

continue;
}

// replace with stone
let Ok(previous) = blocks.set_block(event.position, BlockState::STONE) else {
return;
};

let from = event.from;
let from_entity = world.entity_from_id(from);
from_entity.get::<(&NetworkStreamRef, &mut PlayerInventory)>(|(&net, inventory)| {
mc.to_confirm.push(EntityAndSequence {
entity: event.from,
sequence: event.sequence,
});


let previous_kind = previous.to_kind().to_item_kind();
Expand Down Expand Up @@ -243,7 +261,7 @@ impl Module for BlockModule {
Some(_) => {
error!("Door property 'Half' must be either 'Upper' or 'Lower'");
continue;
},
}
None => None
};

Expand Down

0 comments on commit 2352773

Please sign in to comment.