
[Crash 1.21.1] NullPointerException: null
pietro-lopes opened this issue · 3 comments
A player reported this:
https://gnomebot.dev/paste/mclogs/ymX684C#L2175
No reports on how to reproduce or why it is happening
That's... uh, weird, at best.
The faulting line is
A crash can only occur here if the visible
field is null, but this field is defined (by vanilla) as
private final List<ToastComponent.ToastInstance<?>> visible = new ArrayList<>();
I suspect you have some overzealous optimization
™ mod present that is trying to null it out for some kind of memory saving or cause it to be lazily initialized.
I don't think there's any change I can make from my end here though; as far as TC is concerned that is a final
field which may never have a null value.
What on hell, now I'm curious 🧐
I will mixin debug and see who is touching that.
Thanks for the guidance
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package net.minecraft.client.gui.components.toasts;
import com.aizistral.nochatreports.common.config.NCRConfig;
import com.google.common.collect.Queues;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Deque;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.toasts.SystemToast.SystemToastId;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.ClientHooks;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.transformer.meta.MixinMerged;
import ovh.corail.tombstone.event.ClientEventHandler;
@OnlyIn(Dist.CLIENT)
public class ToastComponent {
public static final int SLOT_COUNT = 5;
public static final int NO_SPACE = -1;
public final Minecraft minecraft;
public final List<ToastInstance<?>> visible = new ArrayList();
public BitSet occupiedSlots = new BitSet(5);
public Deque<Toast> queued = Queues.newArrayDeque();
public ToastComponent(Minecraft p_94918_) {
this.minecraft = p_94918_;
}
public void render(GuiGraphics p_283249_) {
if (!this.minecraft.options.hideGui) {
int i = p_283249_.guiWidth();
this.visible.removeIf((p_280780_) -> {
if (p_280780_ != null && p_280780_.render(i, p_283249_)) {
this.occupiedSlots.clear(p_280780_.index, p_280780_.index + p_280780_.slotCount);
return true;
} else {
return false;
}
});
if (!this.queued.isEmpty() && this.freeSlots() > 0) {
this.queued.removeIf((p_243239_) -> {
int j = p_243239_.slotCount();
int k = this.findFreeIndex(j);
if (k != -1) {
this.visible.add(new ToastInstance(this, p_243239_, k, j));
this.occupiedSlots.set(k, k + j);
return true;
} else {
return false;
}
});
}
}
this.handler$bln000$tombstone$render(p_283249_, (CallbackInfo)null);
}
public int findFreeIndex(int p_243272_) {
if (this.freeSlots() >= p_243272_) {
int i = 0;
for(int j = 0; j < 5; ++j) {
if (this.occupiedSlots.get(j)) {
i = 0;
} else {
++i;
if (i == p_243272_) {
return j + 1 - i;
}
}
}
}
return -1;
}
public int freeSlots() {
return 5 - this.occupiedSlots.cardinality();
}
@Nullable
public <T extends Toast> T getToast(Class<? extends T> p_94927_, Object p_94928_) {
for(ToastInstance<?> toastinstance : this.visible) {
if (toastinstance != null && p_94927_.isAssignableFrom(toastinstance.getToast().getClass()) && toastinstance.getToast().getToken().equals(p_94928_)) {
return (T)toastinstance.getToast();
}
}
for(Toast toast : this.queued) {
if (p_94927_.isAssignableFrom(toast.getClass()) && toast.getToken().equals(p_94928_)) {
return (T)toast;
}
}
return null;
}
public void clear() {
this.occupiedSlots.clear();
this.visible.clear();
this.queued.clear();
}
public void addToast(Toast p_94923_) {
CallbackInfo callbackInfo2 = new CallbackInfo("addToast", true);
this.handler$doh000$nochatreports$onAddToast(p_94923_, callbackInfo2);
if (!callbackInfo2.isCancelled()) {
if (!ClientHooks.onToastAdd(p_94923_)) {
this.queued.add(p_94923_);
}
}
}
public Minecraft getMinecraft() {
return this.minecraft;
}
public double getNotificationDisplayTimeMultiplier() {
return (Double)this.minecraft.options.notificationDisplayTime().get();
}
@MixinMerged(
mixin = "ovh.corail.tombstone.mixin.ToastComponentMixin",
priority = 1000,
sessionId = "70b74f7b-ec65-4454-9795-481bc621e288"
)
private void handler$bln000$tombstone$render(GuiGraphics guiGraphics, CallbackInfo callbackInfo) {
ClientEventHandler.renderScreenMessage();
}
@MixinMerged(
mixin = "com.aizistral.nochatreports.common.mixins.client.MixinToastComponent",
priority = 1000,
sessionId = "70b74f7b-ec65-4454-9795-481bc621e288"
)
private void handler$doh000$nochatreports$onAddToast(Toast toast, CallbackInfo info) {
if (NCRConfig.getClient().hideWarningToast() && toast instanceof SystemToast sys) {
if (sys.getToken() == SystemToastId.UNSECURE_SERVER_WARNING) {
info.cancel();
}
}
}
}
This is what we have 🤔