From 2459bc183e3d818fd201b6e1640e225f379a427e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Primo=C5=BE=20Bo=C5=BEi=C4=8D?= Date: Thu, 23 Jul 2026 14:07:56 +0200 Subject: [PATCH] Fix NPE crash when wireless connector ticks before AE2 grid nodes exist GridHelper.createGridConnection was called with the result of getNode() without checking for null. AE2 creates grid nodes lazily, so a wireless connector ticking during world/chunk load could pass a null node and crash the server with "Ticking block entity" (NullPointerException at GridHelper.createGridConnection). - Null-check both grid nodes before creating the connection; treat a missing node as temporarily disconnected instead of crashing. - Let updateStatus() report whether it completed, and keep retrying every tick until both AE2 nodes exist, so affected connectors self-heal once the grid finishes initializing. - Harden isConnected() to require an actual established connection, and mark the connector shut down on FailedConnectionException. --- .../github/epp/common/me/WirelessConnect.java | 55 ++++++++++++------- .../common/tiles/TileWirelessConnector.java | 8 ++- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/glodblock/github/epp/common/me/WirelessConnect.java b/src/main/java/com/glodblock/github/epp/common/me/WirelessConnect.java index e5a7eb88..74acd08a 100644 --- a/src/main/java/com/glodblock/github/epp/common/me/WirelessConnect.java +++ b/src/main/java/com/glodblock/github/epp/common/me/WirelessConnect.java @@ -49,7 +49,11 @@ private void onUnload(ServerWorld world) { } } - public void updateStatus() { + /** + * @return false if the update could not complete because an AE2 grid node + * is not available yet and should be retried next tick. + */ + public boolean updateStatus() { final long f = this.host.getFrequency(); if (this.thisSide != f && this.thisSide != -f) { if (f != 0) { @@ -75,6 +79,7 @@ public void updateStatus() { this.shutdown = false; this.dis = 0; + boolean completed = true; if (myOtherSide instanceof WirelessConnect sideB) { var sideA = this; @@ -82,28 +87,35 @@ public void updateStatus() { if (sideA.isActive() && sideB.isActive() && this.dis <= EPPConfig.INSTANCE.wirelessConnectorMaxRange && (sideA.host.getWorld() == sideB.host.getWorld())) { - if (this.connection != null && this.connection.getConnection() != null) { - final IGridNode a = this.connection.getConnection().a(); - final IGridNode b = this.connection.getConnection().b(); - final IGridNode sa = sideA.getNode(); - final IGridNode sb = sideB.getNode(); - if ((a == sa || b == sa) && (a == sb || b == sb)) { - return; + final IGridNode nodeA = sideA.getNode(); + final IGridNode nodeB = sideB.getNode(); + if (nodeA == null || nodeB == null) { + // AE2 creates grid nodes lazily, so they may not exist yet during startup + this.shutdown = true; + completed = false; + } else { + if (this.connection != null && this.connection.getConnection() != null) { + final IGridNode a = this.connection.getConnection().a(); + final IGridNode b = this.connection.getConnection().b(); + if ((a == nodeA || b == nodeA) && (a == nodeB || b == nodeB)) { + return true; + } } - } - try { - if (sideA.connection != null && sideA.connection.getConnection() != null) { - sideA.connection.getConnection().destroy(); - sideA.connection = new ConnectionWrapper(null); - } - if (sideB.connection != null && sideB.connection.getConnection() != null) { - sideB.connection.getConnection().destroy(); - sideB.connection = new ConnectionWrapper(null); + try { + if (sideA.connection != null && sideA.connection.getConnection() != null) { + sideA.connection.getConnection().destroy(); + sideA.connection = new ConnectionWrapper(null); + } + if (sideB.connection != null && sideB.connection.getConnection() != null) { + sideB.connection.getConnection().destroy(); + sideB.connection = new ConnectionWrapper(null); + } + sideA.connection = sideB.connection = new ConnectionWrapper(GridHelper.createGridConnection(nodeA, nodeB)); + } catch (FailedConnectionException e) { + this.shutdown = true; + EPP.LOGGER.debug("Failed to connect wireless connectors", e); } - sideA.connection = sideB.connection = new ConnectionWrapper(GridHelper.createGridConnection(sideA.getNode(), sideB.getNode())); - } catch (FailedConnectionException e) { - EPP.LOGGER.debug(e.getMessage()); } } else { this.shutdown = true; @@ -117,6 +129,7 @@ public void updateStatus() { this.connection.setConnection(null); this.connection = new ConnectionWrapper(null); } + return completed; } public double getDistance() { @@ -124,7 +137,7 @@ public double getDistance() { } public boolean isConnected() { - return !this.shutdown; + return !this.shutdown && this.connection != null && this.connection.getConnection() != null; } @SuppressWarnings("deprecation") diff --git a/src/main/java/com/glodblock/github/epp/common/tiles/TileWirelessConnector.java b/src/main/java/com/glodblock/github/epp/common/tiles/TileWirelessConnector.java index 5eff6251..b4c3175d 100644 --- a/src/main/java/com/glodblock/github/epp/common/tiles/TileWirelessConnector.java +++ b/src/main/java/com/glodblock/github/epp/common/tiles/TileWirelessConnector.java @@ -37,10 +37,12 @@ public TileWirelessConnector(BlockPos pos, BlockState blockState) { @Override public void serverTick() { if (this.updateStatus) { - this.updateStatus = false; - this.connect.updateStatus(); + // retry every tick until the AE2 grid nodes of both sides exist + if (this.connect.updateStatus()) { + this.updateStatus = false; + this.markForUpdate(); + } this.updatePowerUsage(); - this.markForUpdate(); } }