Giter Club home page Giter Club logo

Comments (2)

Pokechu22 avatar Pokechu22 commented on June 10, 2024

The affected method is BufferBuilder.normal (func_181663_c).

As decompiled by FF, it looks like this:
   public BufferBuilder func_181663_c(float p_181663_1_, float p_181663_2_, float p_181663_3_) {
      int i = this.field_178997_d * this.field_179011_q.func_177338_f() + this.field_179011_q.func_181720_d(this.field_181678_g);
      switch(this.field_181677_f.func_177367_b()) {
      case FLOAT:
         this.field_179001_a.putFloat(i, p_181663_1_);
         this.field_179001_a.putFloat(i + 4, p_181663_2_);
         this.field_179001_a.putFloat(i + 8, p_181663_3_);
         break;
      case UINT:
      case INT:
         this.field_179001_a.putInt(i, (int)p_181663_1_);
         this.field_179001_a.putInt(i + 4, (int)p_181663_2_);
         this.field_179001_a.putInt(i + 8, (int)p_181663_3_);
         break;
      case USHORT:
      case SHORT:
         this.field_179001_a.putShort(i, (short)((int)p_181663_1_ * 32767 & '\uffff'));
         this.field_179001_a.putShort(i + 2, (short)((int)p_181663_2_ * 32767 & '\uffff'));
         this.field_179001_a.putShort(i + 4, (short)((int)p_181663_3_ * 32767 & '\uffff'));
         break;
      case UBYTE:
      case BYTE:
         this.field_179001_a.put(i, (byte)((int)p_181663_1_ * 127 & 255));
         this.field_179001_a.put(i + 1, (byte)((int)p_181663_2_ * 127 & 255));
         this.field_179001_a.put(i + 2, (byte)((int)p_181663_3_ * 127 & 255));
      }
  this.func_181667_k();
  return this;

}

As disassembled by javap, it looks like this:
  public net.minecraft.client.renderer.BufferBuilder func_181663_c(float, float, float);
    descriptor: (FFF)Lnet/minecraft/client/renderer/BufferBuilder;
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=5, args_size=4
         0: aload_0
         1: getfield      #99                 // Field field_178997_d:I
         4: aload_0
         5: getfield      #101                // Field field_179011_q:Lnet/minecraft/client/renderer/vertex/VertexFormat;
         8: invokevirtual #106                // Method net/minecraft/client/renderer/vertex/VertexFormat.func_177338_f:()I
        11: imul
        12: aload_0
        13: getfield      #101                // Field field_179011_q:Lnet/minecraft/client/renderer/vertex/VertexFormat;
        16: aload_0
        17: getfield      #300                // Field field_181678_g:I
        20: invokevirtual #329                // Method net/minecraft/client/renderer/vertex/VertexFormat.func_181720_d:(I)I
        23: iadd
        24: istore        4
        26: getstatic     #332                // Field net/minecraft/client/renderer/BufferBuilder$1.field_210254_a:[I
        29: aload_0
        30: getfield      #298                // Field field_181677_f:Lnet/minecraft/client/renderer/vertex/VertexFormatElement;
        33: invokevirtual #336                // Method net/minecraft/client/renderer/vertex/VertexFormatElement.func_177367_b:()Lnet/minecraft/client/renderer/vertex/VertexFormatElement$EnumType;
        36: invokevirtual #339                // Method net/minecraft/client/renderer/vertex/VertexFormatElement$EnumType.ordinal:()I
        39: iaload
        40: tableswitch   { // 1 to 7
                       1: 84
                       2: 125
                       3: 125
                       4: 169
                       5: 169
                       6: 239
                       7: 239
                 default: 303
            }
        84: aload_0
        85: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
        88: iload         4
        90: fload_1
        91: invokevirtual #343                // Method java/nio/ByteBuffer.putFloat:(IF)Ljava/nio/ByteBuffer;
        94: pop
        95: aload_0
        96: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
        99: iload         4
       101: iconst_4
       102: iadd
       103: fload_2
       104: invokevirtual #343                // Method java/nio/ByteBuffer.putFloat:(IF)Ljava/nio/ByteBuffer;
       107: pop
       108: aload_0
       109: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       112: iload         4
       114: bipush        8
       116: iadd
       117: fload_3
       118: invokevirtual #343                // Method java/nio/ByteBuffer.putFloat:(IF)Ljava/nio/ByteBuffer;
       121: pop
       122: goto          303
       125: aload_0
       126: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       129: iload         4
       131: fload_1
       132: f2i
       133: invokevirtual #347                // Method java/nio/ByteBuffer.putInt:(II)Ljava/nio/ByteBuffer;
       136: pop
       137: aload_0
       138: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       141: iload         4
       143: iconst_4
       144: iadd
       145: fload_2
       146: f2i
       147: invokevirtual #347                // Method java/nio/ByteBuffer.putInt:(II)Ljava/nio/ByteBuffer;
       150: pop
       151: aload_0
       152: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       155: iload         4
       157: bipush        8
       159: iadd
       160: fload_3
       161: f2i
       162: invokevirtual #347                // Method java/nio/ByteBuffer.putInt:(II)Ljava/nio/ByteBuffer;
       165: pop
       166: goto          303
       169: aload_0
       170: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       173: iload         4
       175: fload_1
       176: f2i
       177: sipush        32767
       180: imul
       181: ldc_w         #484                // int 65535
       184: iand
       185: i2s
       186: invokevirtual #351                // Method java/nio/ByteBuffer.putShort:(IS)Ljava/nio/ByteBuffer;
       189: pop
       190: aload_0
       191: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       194: iload         4
       196: iconst_2
       197: iadd
       198: fload_2
       199: f2i
       200: sipush        32767
       203: imul
       204: ldc_w         #484                // int 65535
       207: iand
       208: i2s
       209: invokevirtual #351                // Method java/nio/ByteBuffer.putShort:(IS)Ljava/nio/ByteBuffer;
       212: pop
       213: aload_0
       214: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       217: iload         4
       219: iconst_4
       220: iadd
       221: fload_3
       222: f2i
       223: sipush        32767
       226: imul
       227: ldc_w         #484                // int 65535
       230: iand
       231: i2s
       232: invokevirtual #351                // Method java/nio/ByteBuffer.putShort:(IS)Ljava/nio/ByteBuffer;
       235: pop
       236: goto          303
       239: aload_0
       240: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       243: iload         4
       245: fload_1
       246: f2i
       247: bipush        127
       249: imul
       250: sipush        255
       253: iand
       254: i2b
       255: invokevirtual #354                // Method java/nio/ByteBuffer.put:(IB)Ljava/nio/ByteBuffer;
       258: pop
       259: aload_0
       260: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       263: iload         4
       265: iconst_1
       266: iadd
       267: fload_2
       268: f2i
       269: bipush        127
       271: imul
       272: sipush        255
       275: iand
       276: i2b
       277: invokevirtual #354                // Method java/nio/ByteBuffer.put:(IB)Ljava/nio/ByteBuffer;
       280: pop
       281: aload_0
       282: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       285: iload         4
       287: iconst_2
       288: iadd
       289: fload_3
       290: f2i
       291: bipush        127
       293: imul
       294: sipush        255
       297: iand
       298: i2b
       299: invokevirtual #354                // Method java/nio/ByteBuffer.put:(IB)Ljava/nio/ByteBuffer;
       302: pop
       303: aload_0
       304: invokespecial #357                // Method func_181667_k:()V
       307: aload_0
       308: areturn
      StackMapTable: number_of_entries = 5
        frame_type = 252 /* append */
          offset_delta = 84
          locals = [ int ]
        frame_type = 40 /* same */
        frame_type = 43 /* same */
        frame_type = 251 /* same_frame_extended */
          offset_delta = 69
        frame_type = 255 /* full_frame */
          offset_delta = 63
          locals = [ class net/minecraft/client/renderer/BufferBuilder ]
          stack = []
      LineNumberTable:
        line 464: 0
        line 465: 26
        line 467: 84
        line 468: 95
        line 469: 108
        line 470: 122
        line 473: 125
        line 474: 137
        line 475: 151
        line 476: 166
        line 479: 169
        line 480: 190
        line 481: 213
        line 482: 236
        line 485: 239
        line 486: 259
        line 487: 281
        line 490: 303
        line 491: 307
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0     309     0  this   Lnet/minecraft/client/renderer/BufferBuilder;
            0     309     1 p_181663_1_   F
            0     309     2 p_181663_2_   F
            0     309     3 p_181663_3_   F
           26     283     4 lvt_4_1_   I

Since this is a lot of text, I'll focus just on just the BYTE and UBYTE path.

Here's the same disassembly, trimmed:
  public net.minecraft.client.renderer.BufferBuilder func_181663_c(float, float, float);
    Code:
// Computing i - snip
// switch
        40: tableswitch   { // 1 to 7
                       // snip cases we don't care about
                       6: 239 // for UBYTE jump to 239
                       7: 239 // for BYTE jump to 239
                 default: 303
            }
// snip code for cases we don't care about
       239: aload_0
       240: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       243: iload         4
       245: fload_1
       246: f2i
       247: bipush        127
       249: imul
       250: sipush        255
       253: iand
       254: i2b
       255: invokevirtual #354                // Method java/nio/ByteBuffer.put:(IB)Ljava/nio/ByteBuffer;
       258: pop
       259: aload_0
       260: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       263: iload         4
       265: iconst_1
       266: iadd
       267: fload_2
       268: f2i
       269: bipush        127
       271: imul
       272: sipush        255
       275: iand
       276: i2b
       277: invokevirtual #354                // Method java/nio/ByteBuffer.put:(IB)Ljava/nio/ByteBuffer;
       280: pop
       281: aload_0
       282: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
       285: iload         4
       287: iconst_2
       288: iadd
       289: fload_3
       290: f2i
       291: bipush        127
       293: imul
       294: sipush        255
       297: iand
       298: i2b
       299: invokevirtual #354                // Method java/nio/ByteBuffer.put:(IB)Ljava/nio/ByteBuffer;
       302: pop
// Exiting the method
       303: aload_0
       304: invokespecial #357                // Method func_181667_k:()V
       307: aload_0
       308: areturn

And now to dissect a tiny section of that specifically -- one call to put:

; Put `this` onto the stack
; Stack: [this]
239: aload_0
; Remove `this` from the stack and put `this.byteBuffer` onto it
; Stack: [this.byteBuffer]
240: getfield      #61                 // Field field_179001_a:Ljava/nio/ByteBuffer;
; Load local variable 4 (which is i, or alternatively lvt_4_1_), and put it onto the stack
; Stack: [this.byteBuffer, i]
243: iload         4
; Load local variable 1 (which is x, or alternatively p_181663_1_), and put it onto the stack.
; Stack: [this.byteBuffer, i, x]
245: fload_1
; Convert the top of the stack from a float to an int and put it into the stack
; Stack: [this.byteBuffer, i, ((int)x)]
246: f2i
; Put the number 127 onto the stack
; Stack: [this.byteBuffer, i, ((int)x), 127]
247: bipush        127
; Take the top two values from the stack and perform an integer multiplication
; and then put that onto the stack
; Stack: [this.byteBuffer, i, (((int)x) * 127)]
249: imul
; Take the number 255 and put it onto the stack
; Stack: [this.byteBuffer, i, (((int)x) * 127), 255]
250: sipush        255
; And the two top values together and put the result onto the stack
; Stack: [this.byteBuffer, i, ((((int)x) * 127) & 255)]
253: iand
; Convert the top of the stack from an int into a byte and put it onto the stack
; Stack: [this.byteBuffer, i, ((byte)((((int)x) * 127) & 255))]
254: i2b
; Call `this.byteBuffer.put`.  Two arguments are popped off
; and then the object to call it on.
; The resultant call is `this.byteBuffer.put(i, ((byte)((((int)x) * 127) & 255)))`
; `ByteBuffer.put` puts the result back onto the stack, so:
; Stack: [this.byteBuffer]
255: invokevirtual #354                // Method java/nio/ByteBuffer.put:(IB)Ljava/nio/ByteBuffer;
; Discard the return value of put
; Stack: []
280: pop

This shows that the cast in the bytecode happens before the multiplication, and the original code actually does have it. So it's a mistake on Mojang's end, not a bug with FernFlower.

I'm mostly ignorant on the actual rendering code, so I need to ask: how would this manifest itself ingame? Is there any way that it could empirically be confirmed that this is a vanilla issue?

from forgeflower.

tterrag1098 avatar tterrag1098 commented on June 10, 2024

There's an image here: MinecraftForge/MinecraftForge#2437

from forgeflower.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.