#Script to detect blocks

1 messages Β· Page 1 of 1 (latest)

dark olive
#

I want a script to run to detect a specific block and run a command when broken
And how i adjust it for multiple blocks with different commands

limpid echo
#
import { world, system } from "@minecraft/server"

let blocks = ["minecraft:iron_ore"]
let cmds = ["kill @p"]

world.beforeEvents.playerBreakBlock.subscribe(event => {
    let block = event.block
    let player = event.player
    
    for (let i = 0; i < blocks.length; i++) {
        if (block.typeId == blocks[i]) {
            player.runCommandAsync(`${cmds[i]}`)
        }
    }
})
#

might work ( prob not lmao )

#

it basically kills the player that broke iron ores

dark olive
#

@limpid echo thats not what im looking for each block has a different scoreboard command

limpid echo
#

whu

#

thats the point tho, u can assign different cmds to each block

#
import { world, system } from "@minecraft/server"

let blocks = ["minecraft:iron_ore", "minecraft:diamond_ore"]
let cmds = ["kill @p", "gamemode c"]

world.beforeEvents.playerBreakBlock.subscribe(event => {
    let block = event.block
    let player = event.player
    
    for (let i = 0; i < blocks.length; i++) {
        if (block.typeId == blocks[i]) {
            player.runCommandAsync(`${cmds[i]}`)
        }
    }
})
  • iron ore kills u when broke
  • diamond ore gives u gm c when broke
rare carbon
#

a map or lookup object would be a much better choice than 2 arrays there

limpid echo
#

lmao

#

am not really that experienced in javascript yet Cry

limpid echo
rare carbon
#
import { world } from "@minecraft/server"

const BLOCKS = {
    "minecraft:iron_ore": "kill @p"
}

world.afterEvents.playerBreakBlock.subscribe(({block, player}) => {
    const command = BLOCKS[block.typeId]
    if (command) player.runCommand(command)
})```
#

(also use after events where you can, before events are a bit finicky with state sometimes)

limpid echo
dark olive
#

Ok but commands different per block

limpid echo
rare carbon
dark olive
#

Ohhh i see tyvm

limpid echo
rare carbon
#
const BLOCKS = {
    "minecraft:iron_ore": "kill @p",
    "minecraft:stick": "gamemode creative",
}``` etc
rare carbon
limpid echo
#

huhhh

limpid echo
rare carbon
#

objects are like Dictionary Proβ„’, they do simple kv pairs like this but also can have methods and are the basis for functions and classes and literally everything that's not a primitive

#

it's a deep deep rabbit hole

limpid echo
#

huhhh

rare carbon
limpid echo
#

i just viewed it as json lmao-

placid saffron
#

I dont know why people complicate it

rare carbon
#

no it is not

#

they are much much more than that

placid saffron
rare carbon
#

literally everything that is not a primitive

placid saffron
#

huh

limpid echo
#

huhhhh

rare carbon
#

functions are objects, as are classes

#

as are instances of those classes

placid saffron
rare carbon
#

yes

#

that is exactly what they are

placid saffron
#

so how is this related to this project

rare carbon
#

idk you're the one that brought this up shrug

placid saffron
#

πŸ˜”

#

i see how it is now

placid saffron
limpid echo
#

dayum Cry

placid saffron
# limpid echo dayum <:Cry:1140309016224997426>
import { world } from "@minecraft/server";

const BLOCKS = {
    "minecraft:iron_ore": ['kill @p', 'say "You broke iron ore!"'],
};

world.afterEvents.playerBreakBlock.subscribe(({ block, player }) => {
    BLOCKS[block.typeId]?.forEach(cmd => player.runCommand(cmd));
});
#

even smaller

placid saffron
#

no, this should work fine

limpid echo
#

omgmg i understand it now shockinginformation

placid saffron
odd peak
limpid echo
limpid echo
#

( i came up with the original use of block Cry )

placid saffron
odd peak
scenic moon
rare carbon
#

look

#

it is 5:30pm and my brain is fried

scenic moon
#

Giggling to myself for no reason LMAO

rare carbon
#

cut me some slack ;-;

scenic moon
#

Happens to the best of us

rare carbon
#

but yeah serty is right about brokenblockpermutation, forgot to update it when i switched from before to after, my bad

placid saffron
#

πŸ€” ye your right on that one

#

I have not used afterEvent for a block broken in a while

limpid echo
placid saffron
#
import { world } from "@minecraft/server";

const BLOCKS = {
    "minecraft:dirt": ['kill @p', 'say "You broke dirt!"'],
};

world.afterEvents.playerBreakBlock.subscribe(({ brokenBlockPermutation, player }) => {
    BLOCKS[brokenBlockPermutation.type.id]?.forEach(cmd => player.runCommand(cmd));
});
#

actually

#

you should be using runCommandAsync

placid saffron
#

The script will run kill @p wait until thats done then run say "You broke dirt!"

#

with runCommandAsync

#

It will run both commands in the same tick

rare carbon
#

runcommand runs both commands there and then

odd peak
#

It will wait until it is executed, yes, but all commands will be launched in one tick

rare carbon
#

async does the same, just queueing them for later (which will still be in the same tick)

placid saffron
#
    /**
     * @remarks
     * Runs a synchronous command on the entity.
     *
     * This function can't be called in read-only mode.
     *
     * @param commandString
     * The command string. Note: This should not include a leading
     * forward slash.
     * @returns
     * A command result containing whether the command was
     * successful.
     * @throws This function can throw errors.
     *
     * {@link CommandError}
     *
     * {@link Error}
     */
    runCommand(commandString: string): CommandResult;``` 

**Runs a synchronous command on the entity.**
#
'say "You broke dirt!"'``` Here you should be using player.sendMessage anyways
#

and here player.kill()

rare carbon
#

what's the problem with that

#

async isn't magically better

#

the work still has to be done somewhere

placid saffron
rare carbon
#

????

#

what you're describing there is exactly what async does, queues them to run in the future

placid saffron
#

Reread [my ](#1331670949443010620 message)

scenic moon
#

Clearly due to the usage of a smart word in the name, async solos (/j)

placid saffron
#
import { world } from "@minecraft/server";

const BLOCKS = {
    "minecraft:dirt": {
        action: (player) => {
            player.kill();
            player.sendMessage("You broke dirt!");
        },
    },
};

world.afterEvents.playerBreakBlock.subscribe(({ brokenBlockPermutation, player }) => {
    BLOCKS[brokenBlockPermutation.type.id]?.action(player);
});

You shoudnt even be using runCommand anymore, when you have this

rare carbon
#

yeah but that's not what op asked for

#

also you don't need the inner action field, you could just have the type map to the method directly

placid saffron
#

"run a command", code is jujst a list of commands

rare carbon
#

uh not really

#

they are different

scenic moon
rare carbon
#

otherwise runcommand wouldn't exist in the first place

placid saffron
#

this is not 2022

#

you can use gametest api's for most things

#
import { world } from "@minecraft/server";

const BLOCKS = {
    "minecraft:dirt": (player) => {
        player.kill();
        player.sendMessage("You broke dirt!");
    },
};

world.afterEvents.playerBreakBlock.subscribe(({ brokenBlockPermutation, player }) => {
    BLOCKS[brokenBlockPermutation.type.id]?.(player);
});
limpid echo
#

😭 bro even tested it ingame to be absolutely sure-

#

😭🀌🀌🀌

scenic moon
limpid echo
#

lmao-

placid saffron
#

@minor surge so what your saying is

limpid echo
placid saffron
#

There is no difference between runCommand and runCommandAsync?

#

I just want to make sure

rare carbon
#

no

#

they just have different use cases

#

here, the distinction isn't important

placid saffron
#

Ok, so runCommand has no performance nor speed difference?

#

Is that what you said?

rare carbon
#

no?

#

i never said that

placid saffron
#

So what did you say?

rare carbon
#

i said that there's no need to use async here

placid saffron
rare carbon
#

yeah, that's what it does

placid saffron
#

you imply here there is no speed difference

#
import { world, system } from "@minecraft/server";

const iterations = 100;
const commands = ['scoreboard objectives list'];

function testRunCommand(player) {
    const startTime = Date.now();
    for (let i = 0; i < iterations; i++) {
        commands.forEach(cmd => {
            try {
                player.runCommand(cmd);
            } catch (e) {
                console.error(`Error executing command: ${cmd}`, e);
            }
        });
    }
    return Date.now() - startTime;
}

async function testRunCommandAsync(player) {
    const startTime = Date.now();
    for (let i = 0; i < iterations; i++) {
        for (const cmd of commands) {
            try {
                await player.runCommandAsync(cmd);
            } catch (e) {
                console.error(`Error executing command: ${cmd}`, e);
            }
        }
    }
    return Date.now() - startTime;
}

world.beforeEvents.chatSend.subscribe(async (eventData) => {
    const { message, sender: player } = eventData;
    if (message.trim().toLowerCase() === "start") {
        system.run(async () => {
            eventData.cancel = true;
            player.sendMessage("Starting performance test...");
            const syncTime = testRunCommand(player);
            player.sendMessage(`Synchronous runCommand took: ${syncTime} ms`);
            const asyncTime = await testRunCommandAsync(player);
            player.sendMessage(`Asynchronous runCommandAsync took: ${asyncTime} ms`);
            player.sendMessage("Performance test completed.");
        });
    }
});
limpid echo
#

y there a entire argument now Cry ( am so sorry- )

limpid echo
#

am so depressed

scenic moon
#

That's an absurd level of spite LMAO

placid saffron
rare carbon
#

your benchmark is kinda meaningless, you're doing something completely arbitrary and introducing a hell of a load of overhead through promise resolution

minor surge
rare carbon
#

i really don't understand what you're trying to achieve here, i'm not looking for an argument

placid saffron
#

You claim that runCommand is suitable, when it really isnt

#

Your giving bad performance advice

rare carbon
#

your own benchmark just proved that it runs 2 orders of magnitude faster

#

the reason your benchmark takes so long is because you schedule a command to run later, then wait for it before scheduling the next one

placid saffron
#

No, my benchmark proves what is written on the documentation, in which runCommandAsync queues the commands to run in that tick, making it so all 2(or max 128 commands) run all at once without waiting for the next one

rare carbon
#

that's not the case because you await each one

#

await = wait for completion

#

doing anything async inherently introduces a small performance overhead just from scheduling, it's not automatically better

placid saffron
#
import { world, system } from "@minecraft/server";

const iterations = 256;
const commands = ['scoreboard objectives list'];

function testRunCommand(player) {
    const startTime = Date.now();
    for (let i = 0; i < iterations; i++) {
        commands.forEach(cmd => {
            try {
                player.runCommand(cmd);
            } catch (e) {
                console.error(`Error executing command: ${cmd}`, e);
            }
        });
    }
    return Date.now() - startTime;
}

async function testRunCommandAsync(player) {
    const startTime = Date.now();
    for (let i = 0; i < iterations; i++) {
        for (const cmd of commands) {
            try {
                player.runCommandAsync(cmd);
            } catch (e) {
                console.error(`Error executing command: ${cmd}`, e);
            }
        }
    }
    return Date.now() - startTime;
}

world.beforeEvents.chatSend.subscribe(async (eventData) => {
    const { message, sender: player } = eventData;
    if (message.trim().toLowerCase() === "start") {
        system.run(async () => {
            eventData.cancel = true;
            player.sendMessage("Starting performance test...");
            const syncTime = testRunCommand(player);
            player.sendMessage(`Synchronous runCommand took: ${syncTime} ms`);


            const asyncTime = await testRunCommandAsync(player);
            player.sendMessage(`Asynchronous runCommandAsync took: ${asyncTime} ms`);
            player.sendMessage("Performance test completed.");
        });
    }
});```
rare carbon
#

that looks much more like what i'd expect

#

it looks so much faster because the commands haven't actually ran yet when the benchmark finishes timing, they've just been scheduled for later

#

that work will still happen

#

just later

placid saffron
#

so yes, in this situtation they should use runCommandAsync, since they are not awaiting for the command completion result

rare carbon
#

i'd still argue runcommand is better here, it also makes potential exception handling easier

#

promises will swallow exceptions unless explicitly caught

#

the perceived speedup gained here is so tiny and really doesn't serve to gain you anything that introducing that extra complexity isn't worth it

placid saffron
#

I dont see where the extra complexity is

#

Your not doing error handling with runCommand anyways, not sure why error handling is a priority for the case of not using AsyncRunCommand

rare carbon
#

i mean you yourself wrap your runcommandasync in a non-functional try catch

#

exceptions couold crop up anywhere in your code, why make them harder to track down when you could not?

placid saffron
#
            player.runCommandAsync(cmd).catch(e => {
                console.error(`Error executing command: ${cmd}`, e);
            });```
#

The performance loss is less then anything

rare carbon
#

you'll still lose your stack trace with that

#

and is still just another thing that could very easily get left out

placid saffron
#
player.runCommandAsync(cmd).catch(e => {
                console.error(`hey im here in x function: ${cmd}`, e);
            });```
rare carbon
#

you still don't have a full stack trace there

placid saffron
#

in the original code they dont have error logging

rare carbon
#

which they don't need, because it's running synchronously

placid saffron
#

so i dont see why you should lose on your performance on somthing you wont even do

rare carbon
#

if an error gets thrown then it has the full stack already there

rare carbon
#

this is premature optimisation

placid saffron
#

Yes, so it literally does improve performance

rare carbon
#

not meaningfully

placid saffron
#

what lol, it does have meaning

#

The name ASYNC in the function

rare carbon
#

do you know what the word async actually means?

placid saffron
#

πŸ›οΈ

rare carbon
#

k i'll take that as a no

placid saffron
#

operations run without blocking the main execution thread

#

Which is what Ive been saying, if you have a list of commands like the original poster did, then you should use commandAsync so your done with the action as quick as possible

rare carbon
#

the same amount of work is still being done, whether it's done there and then in your event handler, or later on in the tick (or in a future tick etc)

#

it does not affect how quickly that thing happens

#

just when

placid saffron
#

If you spent 1 hour doing 1 task, and then spend another hour doing another task

#

you take 2 hours doing it?

rare carbon
#

yes

placid saffron
#

If you spent 1 hour doing 2 tasks

#

You take 1 hour doing the same work

rare carbon
#

yes but that's parallelism, not asynchronous

#

different things

#

js does not support parallelism

#

not in this context at least

#

async just lets you different things while you wait for other things to happen (often entirely externally to the js runtime), it still can only do one thing at a time

placid saffron
#

if you have runCommand, it will wait until the runCommand is finished before running other things in your script(including allowing a beforeEvent) to finish

rare carbon
#

yes, that's correct

placid saffron
#

yes, so there is no reason to use runCommand

rare carbon
#

we're just going in circles here

#

there is literally nothing else in that script that needs to run, it blocking the rest of the event handler is fine

placid saffron
#

okay

dark olive
#

I did not know this would cause a debate lol

#

So im still thinking the best is

import { world } from "@minecraft/server"

const BLOCKS = {
    "minecraft:iron_ore": "kill @p"
}

world.afterEvents.playerBreakBlock.subscribe(({block, player}) => {
    const command = BLOCKS[block.typeId]
    if (command) player.runCommand(command)
})```
#

Or did you all debate on a better way

rare carbon
#

sorry about that, we got a little carried away :’)

#

there’s a very slight correction that needs to be made to that

#

replace both instances of block with brokenBlockPermutation

#

so

import { world } from "@minecraft/server"

const BLOCKS = {
    "minecraft:iron_ore": "kill @p"
}

world.afterEvents.playerBreakBlock.subscribe(({brokenBlockPermutation, player}) => {
    const command = BLOCKS[brokenBlockPermutation.typeId]
    if (command) player.runCommand(command)
})
dark olive
#

@rare carbon i need help cause im having weird script version conflict errors

rare carbon
#

what errors?

dark olive
#

Can i call ypu snd screen share this

rare carbon
#

sorry not atm

#

do send the error though

dark olive
#

1 sec i may have corrected that error just need to fix the script itself

#

Nope that script doesnt work

rare carbon
#

what does it do? do you see an error? anything at all?

dark olive
#

Nothing

rare carbon
#

there are infinite things it could be doing, narrowing it down to β€œnot working” leaves us with infinity - 1 options :P

dark olive
#

So first off i changed it to just say hi

But it doesnt throw an error it acts like normal minecraft

lament nymph
#

Are you sure the script is even running?

#

Use an interval giving out a console.error message

dark olive
#

Not 100%

But it should

lament nymph
#

Okay run the log then to see if your file is running properly

dark olive
#

Is it console.log or a dif syntax

lament nymph
#

I would use console.error()

dark olive
#

import { world } from "@minecraft/server"

const BLOCKS = {
"minecraft:iron_ore": "say hi"
}

world.afterEvents.playerBreakBlock.subscribe(({ brokenBlockPermutation, player }) => {
const command = BLOCKS[brokenBlockPermutation.typeId]
if (command) player.runCommand(command)
})

function test() {
console.error("its running");
}

setInterval(test, 5)

#

so umm thats how normal java script does it is it different here

#

@lament nymph

#

@rare carbon

rare carbon
#

setInterval is a web api and doesn't work here

dark olive
#

oh whats the minecraft way to do it

rare carbon
#

it's system.runInterval

#

the time is measured in ticks, system is imported from @minecraft/server

dark olive
#

do i need to import systems

rare carbon
#

yep

#

although the fact you're getting errors means that your script is running, which is a good sign

dark olive
#

import { system,world } from "@minecraft/server"

const BLOCKS = {
"minecraft:iron_ore": "say hi"
}

world.afterEvents.playerBreakBlock.subscribe(({ brokenBlockPermutation, player }) => {
const command = BLOCKS[brokenBlockPermutation.typeId]
if (command) player.runCommand(command)
})

function test() {
console.error("its running");
}

system.runInterval(test, 5)

#

yuo so its working but the breaking blocks is not

rare carbon
#

what happens if you log the value of command in the event handler?

dark olive
#

Huh

#

Oh

#

1 sec

#

Is not defined

rare carbon
#

as in you see the word undefined?

#

or an error

dark olive
#

It says command is not defined

rare carbon
#

where in the event handler did you put it?

dark olive
#

Thats what it logs

rare carbon
#

it needs to be below the first line, const command = ...

dark olive
#

oh ill move it

#

the whole thing including run interval

rare carbon
#

what did it log?

dark olive
#

import { system, world } from "@minecraft/server"

const BLOCKS = {
"minecraft:iron_ore": "say hi"
}

world.afterEvents.playerBreakBlock.subscribe(({ brokenBlockPermutation, player }) => {
const command = BLOCKS[brokenBlockPermutation.typeId]
function test() {
console.error(command);
}

system.runInterval(test, 5)
if (command) player.runCommand(command)
})

#

like that or am i mistaken i feel thats not right tho

rare carbon
#

HUH you've now got two functions intersecting eachother

#

you can remove the interval stuff, we know it's running now

dark olive
#

World after event works but command is undefined

rare carbon
#

ok that's good

#

well not good but at least we know what's going wrong now

#

can you log brokenBlockPermutation.typeId too?

#

oh hang on i know why

#

replace brokenBlockPermutation.typeId with brokenBlockPermutation.type.id

limpid echo
#

wththt-

#

( how is yall still- )

rare carbon
limpid echo
#

wthth ( am so sorry? )

rare carbon
#

we went on a bit of a magical off-topic adventure discussing the intricacies of async command dispatching

#

but we're back on topic now

dark olive
#

Still undefined

rare carbon
#

can you send your complete code?

dark olive
#

import { system, world } from "@minecraft/server"

const BLOCKS = {
"minecraft:iron_ore": "say hi"
}

world.afterEvents.playerBreakBlock.subscribe(({ brokenBlockPermutation, player }) => {
const command = BLOCKS[brokenBlockPermutation.type.Id]
if (command) player.runCommand(command)
console.error(command);
})

function test() {

}

rare carbon
#

lowercase i in id

#

js names are all case-sensitive

dark olive
#

It worked

rare carbon
#

yay!

dark olive
#

But

#

The command did not

limpid echo
#

😭😭😭🀌🀌🀌

dark olive
#

Just now the scripting error shows the right stuff

rare carbon
#

hey that's progress

#

what's the error now? is it just an issue from the command itself?

limpid echo
#

i literally watched like a entire anime and this problem is still going on-

#

😭🀌🀌🀌

dark olive
#

Its just the scripting error i put in

rare carbon
#

ohh right ok i see what you mean

#

the command should be running then

dark olive
#

Nvm it runs

#

But say hi for some reason wont show up in chat

#

When i change it to tp me 5 blocks in the air it works but it wont be nice and say hi to me

#

Omfg im an idiot

#

I toggled chat off

limpid echo
#

😭😭😭

rare carbon
#

lmao it happens to the best of us

#

glad to hear you got it working tho!

dark olive
#

Ty all so much i do have another question

#

If i want to change a block to req a certain scoreboard to drop how do i do that

limpid echo
#

wym drop-

dark olive
#

Like i want it so if say you want to cut a birch tree but wood cutting is only 5 it wont let you

limpid echo
#

oh

#

oh noo 😭😭😭

dark olive
#

Ill also need to make it req a hatchet no more chad punching trees

limpid echo
#

🀌🀌🀌

dark olive
#

Huh

rare carbon
#

that's quite a jump in complexity there

limpid echo
#

😭😭😭🀌🀌🀌

dark olive
#

It doesnt matter as long as they cant get the block without the correct level

limpid echo
dark olive
#

Btw i dont mind if i need to go in and dobeach blocks json manually

rare carbon
#

this is what before events are for :P

limpid echo
#

okay

#

i just thought like uhh

#

u spent like possibly 3 hour on dis-

#

and like-

#

it being scarpped just like dat-

dark olive
#

Why cant i just change its loot table

rare carbon
#

we're solving a different problem now

limpid echo
#

okay

rare carbon
#

i'm not experienced enough with behaviour packs to really help with this kinda stuff, sorry :(

#

i am a script girlie and not much else

dark olive
#

Middy we solved the first issue its not scrapped

limpid echo
#

oh

lament nymph
#

what is going on here

limpid echo
#

idk

#

i didnt fully read their convo lmao-

dark olive
#

Onto another issue about making a way to not be able to get a block if your scoreboard is not high enough

tawdry yacht
lament nymph
#

you need to get the player's scoreboard value and do an if statement to see if they meet those requirements

rare carbon
#

yeah that basically

#

listen to the event i linked earlier, check the scoreboard, if their level isn't high enough then cancel

rare carbon
dark olive
#

Is anyone who knows this able to vc or will be able to vc later

#

Ai is such an amazing time saver

limpid echo
#

lmao-

dark olive
#

Im having it duplicate and edit another file

#

120 line file in minutes i cant complain

lament nymph
#
import {world} from '@minecraft/server';

const oreTypes =  [
    { blockId: "minecraft:iron_ore", command: "say iron ore", requiredPlayerLvl: 10, increaseXpAmount: 5 },
    { blockId: "minecraft:gold_ore", command: "say gold ore", requiredPlayerLvl: 20, increaseXpAmount: 10},
];

world.beforeEvents.playerBreakBlock.subscribe(({player, block, cancel}) => {
    const getPlayerLevel = world.scoreboard.getObjective('playerLevel');
    const playerLevelExp = world.scoreboard.getObjective('playerLevelExp');
    if (!getPlayerLevel || !playerLevelExp) return;

    const lvl = getPlayerLevel.getScore(player) as number;
    const xp = playerLevelExp.getScore(player) as number;

    for (const ore of oreTypes) {
        if (block.typeId === ore.blockId) {
            if (lvl < ore.requiredPlayerLvl) {
                console.error(`breaking block ${ore.blockId} requires level ${ore.requiredPlayerLvl}`);
                cancel = true;
            } else {
                playerLevelExp.setScore(player, xp + ore.increaseXpAmount);
            }
        }
    }
});
#

this should work. Try it out

#

@dark olive

dark olive
#

i have functions doing the levels the command i was going to run was the scoreboard command to set xp

#

@lament nymph and idk whats to change can we voice chat

lament nymph
#

I'm not available to Vc

dark olive
#

that method may run into an issue where different blocks give dif skills xp such as logs give wc xp req wc ores give mining xp req mining

lament nymph
#

I just gave you an example. It's up to you to figure out the rest

dark olive
#

idk how to edit that to do multiple skills is that to replace the other 1 i have

dark olive
#

@lament nymph is there a dif way to do that since the way i have it already set up makes the way you did it confuse me

placid saffron
dark olive
#

Ima post my other js question in another chat then