mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-22 14:34:59 +01:00
Cancel Erosion futures when disconnecting/switching servers (#5026)
This commit is contained in:
parent
34f5d71e58
commit
e194880f7e
8 changed files with 119 additions and 11 deletions
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.erosion;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
public class ErosionCancellationException extends CancellationException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -42,7 +42,6 @@ public final class GeyserboundHandshakePacketHandler extends AbstractGeyserbound
|
|||
public void handleHandshake(GeyserboundHandshakePacket packet) {
|
||||
boolean useTcp = packet.getTransportType().getSocketAddress() == null;
|
||||
GeyserboundPacketHandlerImpl handler = new GeyserboundPacketHandlerImpl(session, useTcp ? new GeyserErosionPacketSender(session) : new NettyPacketSender<>());
|
||||
session.setErosionHandler(handler);
|
||||
if (!useTcp) {
|
||||
if (session.getGeyser().getErosionUnixListener() == null) {
|
||||
session.disconnect("Erosion configurations using Unix socket handling are not supported on this hardware!");
|
||||
|
@ -52,6 +51,7 @@ public final class GeyserboundHandshakePacketHandler extends AbstractGeyserbound
|
|||
} else {
|
||||
handler.onConnect();
|
||||
}
|
||||
session.setErosionHandler(handler);
|
||||
session.ensureInEventLoop(() -> session.getChunkCache().clear());
|
||||
}
|
||||
|
||||
|
|
|
@ -171,10 +171,10 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
|||
|
||||
@Override
|
||||
public void handleHandshake(GeyserboundHandshakePacket packet) {
|
||||
this.close();
|
||||
var handler = new GeyserboundHandshakePacketHandler(this.session);
|
||||
session.setErosionHandler(handler);
|
||||
handler.handleHandshake(packet);
|
||||
this.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -198,6 +198,17 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
|||
|
||||
public void close() {
|
||||
this.packetSender.close();
|
||||
|
||||
if (pendingLookup != null) {
|
||||
pendingLookup.completeExceptionally(new ErosionCancellationException());
|
||||
}
|
||||
if (pendingBatchLookup != null) {
|
||||
pendingBatchLookup.completeExceptionally(new ErosionCancellationException());
|
||||
}
|
||||
if (pickBlockLookup != null) {
|
||||
pickBlockLookup.completeExceptionally(new ErosionCancellationException());
|
||||
}
|
||||
asyncPendingLookups.forEach(($, future) -> future.completeExceptionally(new ErosionCancellationException()));
|
||||
}
|
||||
|
||||
public int getNextTransactionId() {
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPac
|
|||
import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket;
|
||||
import org.geysermc.erosion.util.BlockPositionIterator;
|
||||
import org.geysermc.geyser.erosion.ErosionCancellationException;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
|
@ -49,6 +50,8 @@ public class GeyserWorldManager extends WorldManager {
|
|||
var erosionHandler = session.getErosionHandler().getAsActive();
|
||||
if (erosionHandler == null) {
|
||||
return session.getChunkCache().getBlockAt(x, y, z);
|
||||
} else if (session.isClosed()) {
|
||||
throw new ErosionCancellationException();
|
||||
}
|
||||
CompletableFuture<Integer> future = new CompletableFuture<>(); // Boxes
|
||||
erosionHandler.setPendingLookup(future);
|
||||
|
@ -61,6 +64,8 @@ public class GeyserWorldManager extends WorldManager {
|
|||
var erosionHandler = session.getErosionHandler().getAsActive();
|
||||
if (erosionHandler == null) {
|
||||
return super.getBlockAtAsync(session, x, y, z);
|
||||
} else if (session.isClosed()) {
|
||||
return CompletableFuture.failedFuture(new ErosionCancellationException());
|
||||
}
|
||||
CompletableFuture<Integer> future = new CompletableFuture<>(); // Boxes
|
||||
int transactionId = erosionHandler.getNextTransactionId();
|
||||
|
@ -74,6 +79,8 @@ public class GeyserWorldManager extends WorldManager {
|
|||
var erosionHandler = session.getErosionHandler().getAsActive();
|
||||
if (erosionHandler == null) {
|
||||
return super.getBlocksAt(session, iter);
|
||||
} else if (session.isClosed()) {
|
||||
throw new ErosionCancellationException();
|
||||
}
|
||||
CompletableFuture<int[]> future = new CompletableFuture<>();
|
||||
erosionHandler.setPendingBatchLookup(future);
|
||||
|
@ -124,6 +131,8 @@ public class GeyserWorldManager extends WorldManager {
|
|||
var erosionHandler = session.getErosionHandler().getAsActive();
|
||||
if (erosionHandler == null) {
|
||||
return super.getPickItemComponents(session, x, y, z, addNbtData);
|
||||
} else if (session.isClosed()) {
|
||||
return CompletableFuture.failedFuture(new ErosionCancellationException());
|
||||
}
|
||||
CompletableFuture<Int2ObjectMap<byte[]>> future = new CompletableFuture<>();
|
||||
erosionHandler.setPickBlockLookup(future);
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.Clien
|
|||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket;
|
||||
import io.netty.channel.EventLoop;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.erosion.ErosionCancellationException;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoaders;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
@ -87,6 +88,8 @@ public class PacketTranslatorRegistry<T> extends AbstractMappedRegistry<Class<?
|
|||
|
||||
try {
|
||||
translator.translate(session, packet);
|
||||
} catch (ErosionCancellationException ex) {
|
||||
GeyserImpl.getInstance().getLogger().debug("Caught ErosionCancellationException");
|
||||
} catch (Throwable ex) {
|
||||
GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.network.translator.packet.failed", packet.getClass().getSimpleName()), ex);
|
||||
ex.printStackTrace();
|
||||
|
|
|
@ -130,6 +130,7 @@ import org.geysermc.geyser.entity.type.Tickable;
|
|||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
|
||||
import org.geysermc.geyser.erosion.AbstractGeyserboundPacketHandler;
|
||||
import org.geysermc.geyser.erosion.ErosionCancellationException;
|
||||
import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler;
|
||||
import org.geysermc.geyser.impl.camera.CameraDefinitions;
|
||||
import org.geysermc.geyser.impl.camera.GeyserCameraData;
|
||||
|
@ -258,7 +259,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
|
||||
@NonNull
|
||||
@Setter
|
||||
private AbstractGeyserboundPacketHandler erosionHandler;
|
||||
private volatile AbstractGeyserboundPacketHandler erosionHandler;
|
||||
|
||||
@Accessors(fluent = true)
|
||||
@Setter
|
||||
|
@ -1190,9 +1191,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
tickThread.cancel(false);
|
||||
}
|
||||
|
||||
erosionHandler.close();
|
||||
|
||||
// Mark session as closed before cancelling erosion futures
|
||||
closed = true;
|
||||
erosionHandler.close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1213,6 +1214,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
eventLoop.execute(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (ErosionCancellationException e) {
|
||||
geyser.getLogger().debug("Caught ErosionCancellationException");
|
||||
} catch (Throwable e) {
|
||||
geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e);
|
||||
}
|
||||
|
@ -1230,6 +1233,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
if (!closed) {
|
||||
runnable.run();
|
||||
}
|
||||
} catch (ErosionCancellationException e) {
|
||||
geyser.getLogger().debug("Caught ErosionCancellationException");
|
||||
} catch (Throwable e) {
|
||||
geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.geysermc.erosion.Constants;
|
|||
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
|
||||
import org.geysermc.geyser.api.network.AuthType;
|
||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler;
|
||||
import org.geysermc.geyser.level.JavaDimension;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
|
@ -57,11 +56,6 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||
SessionPlayerEntity entity = session.getPlayerEntity();
|
||||
entity.setEntityId(packet.getEntityId());
|
||||
|
||||
if (session.getErosionHandler().isActive()) {
|
||||
session.getErosionHandler().close();
|
||||
session.setErosionHandler(new GeyserboundHandshakePacketHandler(session));
|
||||
}
|
||||
|
||||
PlayerSpawnInfo spawnInfo = packet.getCommonPlayerSpawnInfo();
|
||||
JavaDimension newDimension = session.getRegistryCache().dimensions().byId(spawnInfo.getDimension());
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java;
|
||||
|
||||
import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundStartConfigurationPacket;
|
||||
|
||||
@Translator(packet = ClientboundStartConfigurationPacket.class)
|
||||
public class JavaStartConfigurationTranslator extends PacketTranslator<ClientboundStartConfigurationPacket> {
|
||||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundStartConfigurationPacket packet) {
|
||||
var erosionHandler = session.getErosionHandler();
|
||||
if (erosionHandler.isActive()) {
|
||||
// Set new handler before closing
|
||||
session.setErosionHandler(new GeyserboundHandshakePacketHandler(session));
|
||||
erosionHandler.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldExecuteInEventLoop() {
|
||||
// Execute outside of event loop to cancel any pending erosion futures
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue