Help with more complex if/else conditions

๐ŸŽ™๏ธ tryashtar ยท 2 points ยท Posted at 00:09:11 on January 29, 2016 ยท (Permalink)


Everyone knows how to do a simple if/else with commands. Do a block with a condition, have a conditional used for the true, and do /testforblock to check for the false. Simple.

The only issue is you only get one condition, one command to perform if true, and one command to perform if false.

Is there a good, clean, efficient way to accomplish the following things:

  • Assign many commands to one condition

  • Combine conditions (if A and B, do something, otherwise do something else)

  • Nest if/else blocks inside each other

I've been trying to wrap my brain around this and can't come up with a simple efficient solution to all these problems. I'm probably overlooking something. If any of you have a good method, please share! Thanks a bunch!

bananenbroek4 ยท 2 points ยท Posted at 03:45:53 on January 29, 2016 ยท (Permalink)*

Assign many commands to one condition

For this, you could probably use a pulse command block that is activated when the conditional chain command block is true. E.g:

/scoreboard players test testValue testObjective 1 1
(Conditional commandblock) /blockdata <pulse commandblock coords> {auto:1b}
(At the pulse command block) blockdata ~ ~ ~ {auto:0b}

When the conditional command block returns true, it should trigger the pulse command block to activate. You can attach more pulse command blocks to that.

Combine conditions

Just like the first one, you'll need a conditional command block to test for a successful command. If it succeeds, you'll need to add to the score of a fake player. E.g.:

If A (true), fakePlayer fakeObjective + 1
B (true), fakePlayer fakeObjective + 1
IF fakePlayer = 2, activate successful command line
IF fakePlayer =/= 2, keep to normal line or trigger unsuccessful command line.
fakePlayer = 0

I am not really sure what you mean with 'nest inside each other', but I think you might be able to test for a false return using the testforblock command, and use the NBT data {SuccessCount:0b} to test for an unsuccessful command, though you have already stated that at the top of the post ;P

Not sure if this what you need, but I hope it helps!

๐ŸŽ™๏ธ tryashtar ยท 2 points ยท Posted at 04:01:21 on January 29, 2016 ยท (Permalink)*

Wow! Thanks! Both your methods are pretty simple and compact; I can't believe I didn't think of them.

I haven't checked if your first thing (power then unpower an impulse block) will work on a repeat clock, but if it doesn't, I'll just tweak the implementation a little.

It should support nesting as well, so really thanks so much!

EDIT: From what I can see, it works with repeat blocks, but commands only execute 10 times per second instead of 20. Will need to investigate.

brianmcn ยท 2 points ยท Posted at 04:25:18 on January 29, 2016 ยท (Permalink)

power/unpower won't work at 20Hz unless you tweak it so that both the auto:1 and auto:0 happen in the same tick, which I highly recommend regardless (as I find leaving auto:1 impulse block lying around is a recipe for trouble)

๐ŸŽ™๏ธ tryashtar ยท 1 points ยท Posted at 04:38:05 on January 29, 2016 ยท (Permalink)*

Yeah, that's what I'm doing (I think...)

http://i.imgur.com/yZ4BCrb.png

Here's the simple experiment I set up. The command block chain is pointing in the -X direction (so to see which block it's referring to, just count down that number of lines). Here they are in order:


O testfor @p {OnGround:1b}
> blockdata ~-4 ~ ~ {auto:1b}
testforblock ~2 ~ ~ command_block -1 {SuccessCount:0}
> blockdata ~-5 ~ ~ {auto:1b}
blockdata ~-7 ~ ~ {auto:1b}
O blockdata ~ ~ ~ {auto:0b}
give @p tnt
give @p stone
O blockdata ~ ~ ~ {auto:0b}
give @p fish
give @p gunpowder
O blockdata ~ ~ ~ {auto:0b}
say done


Orange blocks are labelled with "O" and conditionals labelled with ">". You'll notice that every impulse block (save the first one) literally just contains "make me unactive."

I don't think anything is getting left behind between ticks, so I'm confused. Do you see anything bad there?

EDIT: Sorry, found a way to clean it up! It should make more sense now, but it's having the same problem. Updated command list and imgur link ;)

brianmcn ยท 2 points ยท Posted at 04:51:29 on January 29, 2016 ยท (Permalink)

Yes. If you 'activate' this on two consecutive ticks, it will only run once.

You can probably test that pretty easily by making the start of the chain a repeating testfor that does e.g. 'your score > 0', and then elsewhere put a repeating block that keeps subtracting 1 from your score, and then type in a command to set your score to 2. You'd expect to get two tnt and stone, but you'll only get one.

๐ŸŽ™๏ธ tryashtar ยท 1 points ยท Posted at 04:56:03 on January 29, 2016 ยท (Permalink)

I tested it by making another repeat block spam me with ghast tears and noticed that I was getting tnt and stone at half the rate.

Do you see the issue? I'm pretty sure I'm turning auto on and back off in the same tick, no?

brianmcn ยท 2 points ยท Posted at 05:00:26 on January 29, 2016 ยท (Permalink)

no, you're doing it a tick later. blockdata-ing auto:1b makes the target block run one tick from now. as a result, it doesn't get reset back to 0 until later, and you'll try to blockdata it to 1 again before then (with no effect).

The correct idiom is to always do e.g.

O testfor blah
> blockdata ~ ~ ~15 {auto:1b}
> blockdata ~ ~ ~14 {auto:0b}
๐ŸŽ™๏ธ tryashtar ยท 1 points ยท Posted at 05:13:45 on January 29, 2016 ยท (Permalink)

Oh, I see.

That's interesting. I assumed it would just cancel out if I put them one after the other like that, but I guess Minecraft is smarter at scheduling that kind of stuff than I thought.

Thanks!

brianmcn ยท 1 points ยท Posted at 05:46:46 on January 29, 2016 ยท (Permalink)

It's the 'rising edge' that causes scheduling, so the moment you go from 0 to 1, it gets scheduled.

bananenbroek4 ยท 2 points ยท Posted at 04:28:03 on January 29, 2016 ยท (Permalink)*

I have tried it with a pulse command just now, and it works! However, you must activate the lines in order, so you can't continue the line before you have ran the 'success' line (well, you could - you'd just run the whole 'continued' line before the 'success' line, which makes it kinda useless in most cases.

Here's an example! The blue represents the 'success' line, and the red represents the 'continuation' line. (I actually screwed up in the image - I didn't reset the score that's used to test for both conditions being correct :P

I doubt I'll use this ever myself, since I am probably always going to use CBP from now on.

EDIT: Ouch, just discovered that it can only run at 10 ticks a second :/
EDIT2: However, if you activate and DEACTIVATE at the same time (so blockdata (auto:1b) and (auto:0b) right after another), it does work at 20 ms!

๐ŸŽ™๏ธ tryashtar ยท 2 points ยท Posted at 05:15:23 on January 29, 2016 ยท (Permalink)

Sweet! It's difficult to read the signs, but this is the multiple condition checking, right?

That's excellent, thank you!