mojira.dev

BugTracker_

Assigned

No issues.

Reported

View all
MC-306706 The game hangs/freezes upon losing focus Fixed MC-306463 Game crashes when mobs go below the world Duplicate MC-306327 The chat restriction warning ignores the Chat Width option Fixed MC-271348 Shulker bullets can go through the world border. Duplicate MC-271329 Block outline disappears after pushing block next/outside world border using piston Duplicate MC-271132 Can glitch through any block using lava and water. Invalid MC-271059 Items can be thrown outside world border through the invisible world border but cannot be thrown through the world border Works As Intended MC-271052 Mobs can go through invisible/world border when summoned. Works As Intended MC-271051 Cannot take damage outside world border in survival mode. Works As Intended MC-271050 Trident can go through the invisible border outside world border Duplicate

Comments

Can confirm in 1.21.11 as well.

I can confirm this in 1.21.11 as well. However, it seems like you’ve created the same bug report twice. Therefore, this ticket should be closed as a duplicate of MC-186068 . MC-186068 can then be reopened.

Can confirm:

[media: Minecraft Screenshot 2026.03.15 - 18.44.44.17.png]

How to Reproduce:

  • Make sure you have Python installed

  • Save this following script as a .py file:

    import socket
    import json
    
    def encode_varint(value):
        result = bytearray()
        while True:
            byte = value & 0x7F
            value >>= 7
            if value != 0:
                byte |= 0x80
            result.append(byte)
            if value == 0:
                break
        return bytes(result)
    
    def decode_varint(data, pos=0):
        result = 0
        shift = 0
        while pos < len(data):
            byte = data[pos]
            pos += 1
            result |= (byte & 0x7F) << shift
            shift += 7
            if not (byte & 0x80):
                return result, pos
        raise ValueError("Ran out of data reading VarInt")
    
    def encode_string(text):
        encoded = text.encode('utf-8')
        return encode_varint(len(encoded)) + encoded
    
    def build_packet(packet_id, data=b''):
        id_bytes = encode_varint(packet_id)
        content = id_bytes + data
        return encode_varint(len(content)) + content
    
    def recv_exact(sock, n):
        data = b''
        while len(data) < n:
            chunk = sock.recv(n - len(data))
            if not chunk:
                raise ConnectionError("Client disconnected early")
            data += chunk
        return data
    
    def recv_packet(sock):
        length_bytes = bytearray()
        while True:
            byte = recv_exact(sock, 1)[0]
            length_bytes.append(byte)
            if not (byte & 0x80):
                break
            if len(length_bytes) >= 5:
                raise ValueError("VarInt too long")
        length, _ = decode_varint(bytes(length_bytes))
        content = recv_exact(sock, length)
        packet_id, offset = decode_varint(content)
        payload = content[offset:]
        return packet_id, payload
    
    STATUS_JSON = {
        "description": [
            {"player": {"name": "alex"}},
            {"sprite": "block/stone"}
        ],
        "players": {"max": 20, "online": 0},
        "version": {"name": "26.1 Pre-Release 2", "protocol": 1073742123},
        "enforcesSecureChat": True
    }
    
    def handle_client(conn, addr):
        print(f"\n[+] Client connected from {addr}")
        try:
            packet_id, payload = recv_packet(conn)
            if packet_id != 0x00:
                return
            pos = 0
            protocol_ver, pos = decode_varint(payload, pos)
            addr_len, pos = decode_varint(payload, pos)
            server_addr = payload[pos:pos + addr_len].decode('utf-8')
            pos += addr_len
            server_port = int.from_bytes(payload[pos:pos+2], 'big')
            pos += 2
            next_state, pos = decode_varint(payload, pos)
            if next_state != 1:
                return
            packet_id, _ = recv_packet(conn)
            json_str = json.dumps(STATUS_JSON)
            response_packet = build_packet(0x00, encode_string(json_str))
            conn.sendall(response_packet)
            print(f"    Payload sent: {json_str}")
            try:
                packet_id, ping_payload = recv_packet(conn)
                if packet_id == 0x01:
                    conn.sendall(build_packet(0x01, ping_payload))
            except Exception:
                pass
        except Exception as e:
            print(f"    Error: {e}")
        finally:
            conn.close()
            print(f"[-] Client disconnected.")
    
    def main():
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server.bind(('0.0.0.0', 25565))
        server.listen(5)
        print("Mock server running on port 25565. Add 127.0.0.1 in Minecraft.")
        print("Press Ctrl+C to stop.")
        try:
            while True:
                conn, addr = server.accept()
                handle_client(conn, addr)
        except KeyboardInterrupt:
            print("\nStopped.")
        finally:
            server.close()
    
    if __name__ == '__main__':
        main()
  • Open Command Prompt or Powershell and run the .py file: python _.py

  • Launch Minecraft Java Edition 26.1 Pre Release 2

  • Go to Multiplayer and add the following server address: 127.0.0.1

  • Click done and observe the MOTD displayed under the server name in the list.


Expected Result:

  • {"player": {"name": "alex"}} should render as fallback text ([alex]), as player objects are no longer permitted in Motd’s

  • {"sprite": "block/stone"} should render as a visible block sprite icon.

Observed Result:

  • {"player": {"name": "alex"}} renders as a player head sprite, it is not being blocked as the changelog states it should be

  • {"sprite": "block/stone"} renders as the fallback text [block/stone], the sprite is not rendering.

I was unable to confirm this as of 1.21.11:

  • The method downloadAndSelectResourcePack no longer exists. The resource pack system now uses a CompletableFuture based asynchronous architecture.

  • The string "Pack application failed" is gone. The closest equivalent code is:

public CompletableFuture<Void> b(final UUID $$0) {
    final CompletableFuture<Void> $$1 = new CompletableFuture<Void>();
    @Override
    public void a(UUID $$02, ioo.a $$12) {
        if ($$0.equals($$02)) {
            iom.this.m = $$2;
            if ($$12 == ioo.a.b) {
                $$1.complete(null);
            } else {
                $$1.completeExceptionally(new IllegalStateException(
                    "Failed to apply pack " + String.valueOf($$02) + 
                    ", reason: " + String.valueOf((Object)$$12)));
            }
        }
        $$2.a($$02, $$12);
    }
}

This may’ve been resolved due to the complete architectural rewrite of the resource pack download/apply system.

This is still an issue as of 1.21.11.


Steps to Reproduce:

  • Extract the 1.21.11 client JAR.

  • Open assets/minecraft/shaders/core/position_color.fsh.

  • Observe that vertex color is unconditionally multiplied by ColorModulator on line 14.


Code Analysis:

#version 330

#moj_import <minecraft:dynamictransforms.glsl>

in vec4 vertexColor;

out vec4 fragColor;

void main() {
    vec4 color = vertexColor;
    if (color.a == 0.0) {
        discard;
    }
    fragColor = color * ColorModulator;
}

assets/minecraft/shaders/include/dynamictransforms.glsl:

#version 330

layout(std140) uniform DynamicTransforms {
    mat4 ModelViewMat;
    vec4 ColorModulator;
    vec3 ModelOffset;
    mat4 TextureMat;
};


Observed Results: The shader unconditionally multiplies vertex color by ColorModulator (fragColor = color * ColorModulator). When debug markers are rendered, ColorModulator is set to vec4(0.0, 1.0, 0.0, 0.75), which zeroes out the Red channel (×0.0) and distorts Blue/Alpha (×0.75). Only the Green channel passes through correctly. Though the shader has been upgraded from GLSL 150 to 330 and ColorModulator moved from a standalone uniform into a UBO (DynamicTransforms), the core issue remains unchanged.

Expected Results: Debug markers should render with their intended colors, including Red and Blue values, as they did prior to 1.17.

Cannot reproduce anymore, this seems to have been unintentionally fixed in 23w31a due to the following changes:

All GUI textures that were previously packed into large sprite sheets got split into individual sprite files under textures/gui/sprites

Sprites can now have scaling behavior configured via .mcmeta files (stretch, tile, or nine-slice)

The automated Slicer tool was provided specifically to help split these sheets correctly


The hotbar selector texture was part of one of these old GUI sprite sheets.


23w31a:

[media: 2026-03-14_19.55.13.png]

Prior Versions:

[media: 2026-03-14_19.56.04.png]

This can be confirmed using the attached resource pack:

[media]

The resource pack replaces the hotbar selector texture with a diagnostic version: the bottom three rows are colored yellow, magenta, and cyan respectively, making any clipping immediately visible. Testing on any version before 23w31a shows only the yellow row partially visible, with magenta and cyan completely cut off, confirming the bug is present. Testing on 23w31a shows all three colored rows fully visible.

Your game seems to be modified based on the attached screenshots, please note that modified versions are not supported here. Additionally, this seems to describe the same issue as MC-244683 which has been fixed.

Please note that modified and outdated versions are not supported here. Also,

gamerule doDaylightCycle false

is now:

/gamerule advance_time false

This seems to have indeed been fixed in 1.20 pre-3.


1.20 pre-3:

public void c(acq $$0) {
    ftx $$1 = this.c.remove($$0);
    if ($$1 != null) {
        this.c($$0, $$1);
    }
}

This now calls this.c.remove($$0) instead of getOrDefault, so the map entry is actually removed. It then delegates to the private cleanup helper:

private void c(acq $$0, ftx $$1) {
    if ($$1 != fuc.c()) {
        this.d.remove($$1);
        try {
            $$1.close();
        }
        catch (Exception $$2) {
            b.warn("Failed to close texture {}", (Object)$$0, (Object)$$2);
        }
    }
    $$1.b();
}

This does everything the old code was missing: removes from the tickable set (this.d), calls close() on the texture, and releases the GL texture ID via $$1.b().

For context, this.c is the texture map and this.d is the tickable texture set, both declared identically in both versions:

private final Map<acq, ftv> c = Maps.newHashMap();
private final Set<fum> d = Sets.newHashSet();

Prior Versions:

public void c(acq $$0) {
    ftv $$1 = this.b($$0, (ftv)fua.c());
    if ($$1 != fua.c()) {
        TextureUtil.releaseTextureId((int)$$1.a());
    }
}

This calls b(acq, ftv), which is just a getOrDefault wrapper:

public ftv b(acq $$0, ftv $$1) {
    return this.c.getOrDefault($$0, $$1);
}

So it looks up the texture from the map, releases the GL texture ID if found, but never removes the entry from the map. It also never calls close() on the texture object, and doesn't touch the tickable texture set. This matches the bug as originally reported.

This is still present in 1.21.11, GoalSelector.a(boolean) (goalTick) iterates this.c via for each and calls WrappedGoal.tick() ($$2.a()) on each running goal. SkeletonTrapGoal.tick() calls setTrap(false) (this.a.x(false)) mid iteration. setTrap(false) calls removeGoal() (this.cs.a(this.cv)), which calls removeIf directly on this.c, the set currently being iterated:

for (cqe $$2 : this.c) {
    if (!$$2.h() || !$$0 && !$$2.X_()) continue;
    $$2.a();
}
public void a() {
    axf $$0 = (axf)this.a.ao();
    cda $$1 = $$0.c(this.a.dK());
    this.a.x(false);
    ...
}
public void x(boolean $$0) {
    if ($$0 == this.cB) {
        return;
    }
    this.cB = $$0;
    if ($$0) {
        this.cs.a(1, this.cv);
    } else {
        this.cs.a(this.cv);
    }
}
public void a(cop $$0) {
    for (cqe $$12 : this.c) {
        if ($$12.k() != $$0 || !$$12.h()) continue;
        $$12.e();
    }
    this.c.removeIf($$1 -> $$1.k() == $$0);
}
private final Set<cqe> c = new ObjectLinkedOpenHashSet();

However, based on my analysis, it is worth noting that the structural difference from the original report: this.c is now ObjectLinkedOpenHashSet (fastutil) rather than java.util.LinkedHashSet. The original safe in vanilla assumption relied on LinkedHashSet's iterator only checking modCount in next(), not hasNext(). With ObjectLinkedOpenHashSet, modification during for each iteration produces undefined behavior rather than a guaranteed CME.

Affects 1.21.11, updated datapack:

[media]

Can anyone still confirm this as of the latest versions? I cannot reproduce, it correctly appears as red stone wires now:

[media: image-20260311-050122.png]

This is most likely due to format changes across versions, 1.21.11 datapack:

[media]


Can confirm in 1.21.11, datapack:

[media]

This seems to have been fixed in 25w44a:

[media: Fixed.mp4]

Prior versions:

[media: Bug.mp4]

I cannot reproduce this anymore, it seems to have been fixed in 22w12a:

[media: 2026-03-10_23.12.06.png]

Prior versions:

[media: 2026-03-10_23.09.48.png]

Can confirm in 1.21.11:

protected void fv() {
    int $$0 = this.F();
    if (this.bp) {
        ++this.br;
        if (this.br >= $$0) {
            this.br = 0;
            this.bp = false;
        }
    } else {
        this.br = 0;
    }
    this.by = (float)this.br / (float)$$0;
}

The ClientMannequin class (gij.class) overrides tick() (g()). However, its implementation only checks asynchronous skin profile lookups and delegates to super.tick(), completely omitting the call to updateSwingTime() (fv()):

@Override
public void g() {
    super.g();
    this.g.a(this.dI(), this.dN());
    
    if (this.h != null && this.h.isDone()) {
        try {
            this.h.get().ifPresent(this::a);
            this.h = null;
        }
        catch (Exception $$0) {
            f.error("Error when trying to look up skin", (Throwable)$$0);
        }
    }
}

Furthermore, an analysis of the inheritance chain confirms that super.g() (Mannequin.class <Mob.class < LivingEntity.class) does not call updateSwingTime() either.

Load more comments