Merge branch 'serverside-experimental/prevent-disconnects' into serverside

This commit is contained in:
s809
2024-08-07 22:20:29 +05:00
9 changed files with 65 additions and 29 deletions
@@ -52,7 +52,7 @@ public class ClientPluginChannelApi
Objects.requireNonNull(session);
this.session = session;
session.registerHandler(CurrentLevelKeyMessage.class, this::onCurrentLevelKeyMessage);
session.registerHandler(CloseEvent.class, this::onClose);
session.registerHandler(CloseEvent.class, false, this::onClose);
}
private void onCurrentLevelKeyMessage(CurrentLevelKeyMessage msg)
@@ -64,7 +64,7 @@ public class ClientNetworkState implements Closeable
this.configReceived = true;
});
this.session.registerHandler(CloseEvent.class, msg ->
this.session.registerHandler(CloseEvent.class, false, msg ->
{
this.configReceived = false;
});
@@ -53,7 +53,7 @@ public class ServerPlayerState
this.session.sendMessage(new RemotePlayerConfigMessage(this.config));
});
this.session.registerHandler(CloseEvent.class, event -> {
this.session.registerHandler(CloseEvent.class, false, event -> {
// Noop
});
}
@@ -1,16 +1,9 @@
package com.seibel.distanthorizons.core.network.event;
import com.seibel.distanthorizons.core.network.messages.NetworkMessage;
import io.netty.buffer.ByteBuf;
/**
* This is not a "real" message, and only used to indicate a disconnection.
* This event is used to indicate a disconnect.
*/
public class CloseEvent extends NetworkMessage
public class CloseEvent extends InternalEvent
{
@Override
public void encode(ByteBuf out) { throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is not a real message, and cannot be sent."); }
@Override
public void decode(ByteBuf in) { throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is not a real message, and cannot be received."); }
}
@@ -0,0 +1,20 @@
package com.seibel.distanthorizons.core.network.event;
import com.seibel.distanthorizons.core.network.messages.NetworkMessage;
import io.netty.buffer.ByteBuf;
public abstract class InternalEvent extends NetworkMessage
{
@Override
public void encode(ByteBuf out)
{
throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is an internal event, and cannot be sent.");
}
@Override
public void decode(ByteBuf in)
{
throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is an internal event, and cannot be received.");
}
}
@@ -108,20 +108,22 @@ public abstract class NetworkEventSource
}
}
public abstract <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation);
protected <T extends NetworkMessage> void registerHandler(NetworkEventSource instance, Class<T> handlerClass, Consumer<T> handlerImplementation)
public abstract <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation);
public final <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation)
{
this.registerHandler(handlerClass, true, handlerImplementation);
}
protected final <T extends NetworkMessage> void registerHandler(NetworkEventSource instance, Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation)
{
if (throwIfMessageNotRegistered)
{
MessageRegistry.INSTANCE.getMessageId(handlerClass);
}
//noinspection unchecked
this.handlers.computeIfAbsent(handlerClass, missingHandlerClass ->
{
// Will throw if the handler class is not found
if (missingHandlerClass != CloseEvent.class)
{
MessageRegistry.INSTANCE.getMessageId(missingHandlerClass);
}
return new ConcurrentHashMap<>();
})
this.handlers.computeIfAbsent(handlerClass, missingHandlerClass -> new ConcurrentHashMap<>())
.computeIfAbsent(instance, _instance -> ConcurrentHashMap.newKeySet())
.add((Consumer<NetworkMessage>) handlerImplementation);
}
@@ -0,0 +1,21 @@
package com.seibel.distanthorizons.core.network.event;
import com.seibel.distanthorizons.core.network.messages.NetworkMessage;
import org.jetbrains.annotations.Nullable;
/**
* This event is used to indicate that encoding or decoding of a message threw an exception.
*/
public class ProtocolErrorEvent extends InternalEvent
{
public final Throwable throwable;
@Nullable
public final NetworkMessage message;
public ProtocolErrorEvent(Throwable throwable, @Nullable NetworkMessage message)
{
this.throwable = throwable;
this.message = message;
}
}
@@ -39,7 +39,7 @@ public final class ScopedNetworkEventSource extends NetworkEventSource
@Override
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation)
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation)
{
if (this.isClosed)
{
@@ -47,9 +47,9 @@ public final class ScopedNetworkEventSource extends NetworkEventSource
}
//noinspection unchecked
this.parent.registerHandler(this, handlerClass, (Consumer<T>) this.actualHandleMessageStable);
this.parent.registerHandler(this, handlerClass, throwIfMessageNotRegistered, (Consumer<T>) this.actualHandleMessageStable);
super.registerHandler(this, handlerClass, handlerImplementation);
super.registerHandler(this, handlerClass, throwIfMessageNotRegistered, handlerImplementation);
}
@@ -66,14 +66,14 @@ public class Session extends NetworkEventSource
}
@Override
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation)
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation)
{
if (this.closeReason.get() != null)
{
return;
}
this.registerHandler(this, handlerClass, handlerImplementation);
this.registerHandler(this, handlerClass, throwIfMessageNotRegistered, handlerImplementation);
}
public <TResponse extends TrackableMessage> CompletableFuture<TResponse> sendRequest(TrackableMessage msg, Class<TResponse> responseClass)