Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-195351

Comparator in compare mode can schedule unneeded tileticks

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Resolution: Fixed
    • Affects Version/s: 1.16.1, 20w29a, 20w30a, 1.16.2 Pre-release 1, 1.16.2 Pre-release 2, 1.16.2 Release Candidate 1, 1.16.2 Release Candidate 2, 1.16.2
    • Fix Version/s: 20w45a
    • Labels:
      None
    • Confirmation Status:
      Confirmed
    • Category:
      Performance, Redstone
    • Mojang Priority:
      Normal

      Description

      The bug

      Comparators in compare mode can schedule tileticks when they shouldn't, creating unneeded lag from block updates and in some situations the comparator can be instant making for very confusing timings.

      To reproduce

      1. Place a comparator down in compare mode
      2. Power the side of the comparator
      3. Power the back of the comparator with a signal strength less than the side
        Comparator should do nothing
        Comparator schedules a tiletick on itself and causes block updates afer 2gt
        This can be most easily seen when placing a Block Update Detector after the comparator
        It will detect the block updates that the scheduled tiletick produces

      Instant Comparator

      Due to this bug allowing comparators to schedule a tiletick seemly randomly, if in the right circumstances the comparator can appear instant, creating a very confusing time for the player as they try to find the timing issue
      In the below picture both comparators turn on at the same time even tho the top line has an extra 1tick  of delay
      This is because when the first repeaters turn on, the comparator thinks it can turn on too (even tho it can't), so it schedules a tiletick on itself for the next tick
      In the next tick, the side of the comparator turns off and the comparator instantly turns on afterwards in the same tick

      Code analysis

      Vanilla code:

      private int calculateOutputSignal(Level level, BlockPos blockPos, BlockState blockState) {
          if (blockState.getValue(MODE) == ComparatorMode.SUBTRACT) {
              return Math.max(this.getInputSignal(level, blockPos, blockState) - this.getAlternateSignal(level, blockPos, blockState), 0);
          }
          return this.getInputSignal(level, blockPos, blockState);
      }
      

      The first if statement for subtract mode works perfectly fine
      But the compare mode doesn't take the side input into account, leading to the comparator thinking it can turn on even tho the side input is overpowering the back

      Fixed code:

      private int calculateOutputSignal(Level level, BlockPos blockPos, BlockState blockState) {
          if (blockState.getValue(MODE) == ComparatorMode.SUBTRACT) {
              return Math.max(this.getInputSignal(level, blockPos, blockState) - this.getAlternateSignal(level, blockPos, blockState), 0);
          }
          return this.getInputSignal(level, blockPos, blockState) >= this.getAlternateSignal(level, blockPos, blockState) ? this.getInputSignal(level, blockPos, blockState) : 0;
      }
      

      Check if the side input is greater than the back and return 0

      Optimized code:

      private int calculateOutputSignal(Level level, BlockPos blockPos, BlockState blockState) {
          int i = this.getInputSignal(level, blockPos, blockState);
          if (i == 0)
              return 0;
          j = this.getAlternateSignal(level, blockPos, blockState);
          if (j > i)
              return 0;
          if (blockState.getValue(MODE) == ComparatorMode.SUBTRACT) {
              return i - j;
          }
          return j;
      }
      

      If the back input is 0, no need to check the side or mode state and return 0
      If the side input is greater than the back, no need to check the mode state and return 0

      Note for technical players 

      This bug is not the cause nor affects scheduling a tiletick on a comparator by simply powering the back (without the side) with a 1tick pulse
      As that is not a exception, but a rule on how comparators fundamentally work

      Nor will this remove instant comparators
      There are multiple ways of getting a comparator to schedule a tiletick
      And you do not use this partiular technique

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              xilefian [Mojang] Felix Jones
              Reporter:
              RedCMD RedCMD
              Votes:
              15 Vote for this issue
              Watchers:
              13 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                CHK: