Skip to content

Translation notice

This page was translated with machine translation and may contain inaccuracies. If you can help improve it, please open an issue or submit a pull request.

Better right-click detection: Halving method

Esan Sang Sang Sang

Esan Sang Sang Sang

Let’s look at a performance improvement solution for right-click detection:

Right-click detection (halving method) ​

Before we start, let’s do an experiment: If a scoreboard value initially is0\color{blue}0, add it first every time4\color{blue}4, then divided by2\color{blue}2, and see what happens:

  • initial:0\color{blue}0
  • 0+4=40+4=4,4÷2=24 \div 2=\color{blue}2
  • 2+4=62+4=6,6÷2=36 \div 2=\color{blue}3
  • 3+4=73+4=7,7÷2=37 \div 2=\color{blue}3
  • 3+4=73+4=7,7÷2=37 \div 2=\color{blue}3
  • ...

You'll notice that the last value always seems to be3\color{blue}3。
If we don't continue to add44, what will happen?

  • initial:0\color{blue}0
  • 0+4=40+4=4,4÷2=24 \div 2=\color{blue}2
  • 2+4=62+4=6,6÷2=36 \div 2=\color{blue}3
  • 3+4=73+4=7,7÷2=37 \div 2=\color{blue}3
  • 3+4=73+4=7,7÷2=37 \div 2=\color{blue}3
  • 3÷2=13 \div 2=\color{blue}1
  • 1÷2=01 \div 2=\color{blue}0
  • 0÷2=00 \div 2=\color{blue}0
  • ...

If we don't continue to add44, this value will change from33become11, and then return to the initial00 Did you notice anything strange?
Let’s look directly at the resulting numbers:

0\color{blue}0
2\color{blue}2
3\color{blue}3
3\color{blue}3
3\color{blue}3
1\color{blue}1
0\color{blue}0
0\color{blue}0

You will find that when the value is added44During this period of time, the value will look like2333123331, that is, starting with22, the middle is33, ending with11。 In other words, we only need to add44, and then continue to divide by22, you can get the right-click status. This is where the name "halving method" comes from.

However, players who are familiar with command will say that right-click advancement detection is very unstable and often disconnects. In this way, during a long press, the detection will start immediately after the end due to disconnection. So this method cannot be used? No, we can add it to the process44Change to plus66:

0\color{blue}0
3\color{blue}3
4\color{blue}4
5\color{blue}5
5\color{blue}5
2\color{blue}2
1\color{blue}1
0\color{blue}0

If the value is33, it means starting to press and hold the right button If the value is11, it means release the right button Otherwise as long as it is not00, indicating that you are pressing and holding the right button But some people will say, what will happen if I press and release it immediately?

0\color{blue}0
0\color{blue}0
3\color{blue}3 🕹️
1\color{blue}1
0\color{blue}0
0\color{blue}0

What if you press it longer?

0\color{blue}0
0\color{blue}0
3\color{blue}3 🕹️
4\color{blue}4 🕹️
2\color{blue}2
1\color{blue}1
0\color{blue}0
0\color{blue}0

What if contact is discontinued?

0\color{blue}0
0\color{blue}0
3\color{blue}3 🕹️
4\color{blue}4 🕹️
5\color{blue}5 🕹️
2\color{blue}2
5\color{blue}5 🕹️
2\color{blue}2
1\color{blue}1
0\color{blue}0

You will find that as long as+4+4or+6+6back÷2\div 2, no matter how you do it, this value is based on22or33Start with11ended. This property can only be satisfied by dividing by 2, which is why it is called the "halving method".
Why is this? In this process, only33and22Divide by22will get11, other numbers will not. And other numbers are divided multiple times by22After that, you will eventually come back to22。
Due to space limitations, this video does not carry out strict mathematical proofs. If you are interested you can prove it yourself.

Next, I will post the complete code without further explanation.

bash
# example:rmb/using_item
# ...右键运行example:rmb/run的进度

# example:load
scoreboard objectives add rmb_flag dummy
scoreboard objectives add example dummy
scoreboard players set 2 example 2

# example:rmb/run
scoreboard players add @s rmb_flag 4
advancement revoke @s only example:rmb/using_item

# example:tick
execute as @a at @s run function example:rmb/player_tick

# example:rmb/player_tick
scoreboard players operation @s rmb_flag /= 2 example
execute if score @s rmb_flag matches 2 run say 开始长按右键
execute if score @s rmb_flag matches 3 run say 正在长按右键
execute if score @s rmb_flag matches 1 run say 松开右键

summary ​

In this tutorial, we learned a high-performance right-click detection scheme-the halving method. The knowledge points involved are:

  • Halving method:

    • Taking advantage of the properties of integer division, by(currentvalue+inputvalue)÷2(current value + input value) \div 2The formula of , completes the state flow within a variable
    • If you need touch-off protection, you only need to modify the numbers and do not need to add new logic.
  • State mapping table

| Scheme | Value | Meaning | |----------|----|----------------| | +4+4Halving |22|Start by right-clicking | | | 33| Long pressing the right button | | | 11| Release the right button | | | 00| No operation | | +6+6Halving |33|Start by right-clicking | | | 11| Release the right button | | | 00| No operation | | |Other values| Long pressing the right button |

  • scoreboard operations
    • Constant setting: The scoreboard operation does not support direct division by numbers. A "constant score" must be set first (such as settingexampleThe score is2) as the divisor.
    • Operation instructions:
      • Input signal:scoreboard players add @s rmb_flag 4(Executed in the function triggered by advancement)
      • Status decay:scoreboard players operation @s rmb_flag /= 2 example(Executed in Tickfunction)

Powered by VitePress and GitHub Pages