Carpet

Carpet

2M Downloads

[Scarpet] No way to get the position of the source

altrisi opened this issue ยท 5 comments

commented

Currently there is no way to get the position of the source that called a piece of code, be it via a custom command, script run/invoke/etc, or any other way.

That position, however, is saved and passed around through the code, given that using the run() API executes commands with a command source at the position of the original source.

This is easy to solve if the code is ran by a player, via pos(player()), but it becomes a problem when you try to do it for a command block, execute at, etc.

Not sure where could someone put this in the API, but maybe something along the lines of pos('source')?

For anyone now wanting to do this, here is a workaround to get the source location by (ab)using the run() API:

//# Ugly hack to get the position of the executing source, be it a command block or whatever.
//# Scarpet currently doesn't provide this in the API, but it's saved somewhere since it's used in run()
//# @returns A triple of coordinates being the source position of the execution, may be [0,0,0] if not available.
_getSourcePos() -> (
    run('summon minecraft:armor_stand ~ ~ ~ {CustomName:"{\\"text\\":\\"PosGetter\\"}",Small:1,Invisible:1}');
    queryResult = entity_selector('@e[type=minecraft:armor_stand,name=PosGetter,nbt={Small:1b,Invisible:1b},limit=1]');
    if (length(queryResult) != 1,
        throw('noPosGetter', 'user_exception', 'no pos getter found, aborting')
    );
    getter = queryResult:0;
    sourcePos = query(getter, 'pos');
    modify(getter, 'kill');
    sourcePos
);
commented

Do note that the workaround is quite inefficient, can only be ran up to around 100 times per tick on average on my machine.

commented

well, command source is something like... an implementation detail. Apps are either player centered which in this case, player() always returns the same player, or world centered where execution point doesn't really matter. Its the vanilla commands that the only way to pass a position is to steal it from a dummy entity, or pass it via command execution. I have never yet needed to fetch that that's why I haven't thought about adding it. The only usecase I can see is when the command comes directly from a command block executed via button and one wants to know that position. We could provide that via system_info (so all the source info, entity, position, dimension, etc.)

commented

what's the difference between this and #1011 ?

commented

what's the difference between this and #1011 ?

That one was when I was half asleep, and the other (this one) wasn't. I'll closed the other one.

commented

My use case is literally that, I'm running the code from a command block with a button where I want to toggle a lamp next to it.