Archived
0
This commit is contained in:
2018-03-28 03:52:27 +03:00
parent d65b59d859
commit 723da8480f
5 changed files with 128 additions and 9 deletions

View File

@@ -0,0 +1,89 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-03-28
*/
package mc.core.netty;
import io.netty.channel.Channel;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mc.core.Packet;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
@Slf4j
public class EventBus {
private static EventBus instance = new EventBus();
@RequiredArgsConstructor
@EqualsAndHashCode
private static class PairKey {
private final int stateId;
private final int packetId;
}
@RequiredArgsConstructor
private static class PairValue {
private final Object object;
private final Method method;
}
public interface Listener {}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventHandler {
State value();
}
public static EventBus getInstance() {
return instance;
}
private Map<PairKey, List<PairValue>> listenersMap = new HashMap<>();
public void listenIncomingPacket(final Listener listener) {
Arrays.stream(listener.getClass().getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(EventHandler.class)
&& method.getParameterCount() == 2
&& Packet.class.isAssignableFrom(method.getParameterTypes()[0])
&& Channel.class.isAssignableFrom(method.getParameterTypes()[1]))
.forEach(method -> {
State state = method.getAnnotation(EventHandler.class).value();
Class<?> pktClass = method.getParameterTypes()[0];
Optional<Integer> optPacketId = state.getPacketId(pktClass.asSubclass(Packet.class));
if (optPacketId.isPresent()) {
PairKey key = new PairKey(
state.getId(),
optPacketId.get()
);
PairValue value = new PairValue(listener, method);
List<PairValue> listValues = listenersMap.computeIfAbsent(key, f -> new ArrayList<>());
listValues.add(value);
}
});
}
public void eventIncomingPacket(final int stateId, final Packet packet, final Channel channel) {
List<PairValue> listValues = listenersMap.get(new PairKey(stateId, packet.getId()));
if (listValues != null) {
listValues.forEach(pairValue -> {
try {
pairValue.method.invoke(pairValue.object, packet, channel);
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("Method invoke", e);
}
});
}
}
}

View File

@@ -13,6 +13,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler; import io.netty.handler.logging.LoggingHandler;
import mc.core.Server; import mc.core.Server;
import mc.core.StartServerException; import mc.core.StartServerException;
import mc.core.netty.handlers.HandshakeHandler;
public class NettyServer implements Server { public class NettyServer implements Server {
private EventLoopGroup bossGroup, workerGroup; private EventLoopGroup bossGroup, workerGroup;
@@ -48,6 +49,8 @@ public class NettyServer implements Server {
ServerBootstrap serverBootstrap = buildServerBootstrap(); ServerBootstrap serverBootstrap = buildServerBootstrap();
EventBus.getInstance().listenIncomingPacket(new HandshakeHandler());
try { try {
serverBootstrap.bind(host, port).sync().channel().closeFuture().sync(); serverBootstrap.bind(host, port).sync().channel().closeFuture().sync();
} catch (InterruptedException e) { } catch (InterruptedException e) {

View File

@@ -26,10 +26,10 @@ public class PacketHandler extends SimpleChannelInboundHandler<Packet> {
packet.getClass().getSimpleName(), packet.getClass().getSimpleName(),
packet.toString()); packet.toString());
if (equalsPacket(packet, "HandshakeRequestPacket")) { EventBus.getInstance().eventIncomingPacket(
HandshakeRequestPacket pkt = (HandshakeRequestPacket) packet; context.channel().attr(State.ATTR_STATE).get().getId(),
context.channel().attr(State.ATTR_STATE).set(pkt.getNextState()); packet,
context.channel().writeAndFlush(new HandshakeResponsePacket()); context.channel()
} );
} }
} }

View File

@@ -4,6 +4,8 @@
*/ */
package mc.core.netty; package mc.core.netty;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import lombok.Getter; import lombok.Getter;
@@ -16,11 +18,11 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
public enum State { public enum State {
Handshaking(1, ImmutableMap.of( Handshaking(1, ImmutableBiMap.of(
0, HandshakeRequestPacket.class, 0, HandshakeRequestPacket.class,
1, PingPacket.class 1, PingPacket.class
)), )),
Status(0, ImmutableMap.of(1, PingPacket.class)); Status(0, ImmutableBiMap.of(1, PingPacket.class));
public static final AttributeKey<State> ATTR_STATE = AttributeKey.newInstance("ATTR_STATE"); public static final AttributeKey<State> ATTR_STATE = AttributeKey.newInstance("ATTR_STATE");
@@ -30,9 +32,9 @@ public enum State {
@Getter @Getter
private final int id; private final int id;
private final Map<Integer, Class<? extends Packet>> requestMap; private final BiMap<Integer, Class<? extends Packet>> requestMap;
State(int id, Map<Integer, Class<? extends Packet>> requestMap) { State(int id, BiMap<Integer, Class<? extends Packet>> requestMap) {
this.id = id; this.id = id;
this.requestMap = requestMap; this.requestMap = requestMap;
} }
@@ -40,4 +42,8 @@ public enum State {
public Optional<Class<? extends Packet>> getPacketClass(int id) { public Optional<Class<? extends Packet>> getPacketClass(int id) {
return Optional.ofNullable(requestMap.get(id)); return Optional.ofNullable(requestMap.get(id));
} }
public Optional<Integer> getPacketId(Class<? extends Packet> clazz) {
return Optional.ofNullable(requestMap.inverse().get(clazz));
}
} }

View File

@@ -0,0 +1,21 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-03-28
*/
package mc.core.netty.handlers;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import mc.core.netty.EventBus;
import mc.core.netty.State;
import mc.core.netty.packets.HandshakeRequestPacket;
import mc.core.netty.packets.HandshakeResponsePacket;
@Slf4j
public class HandshakeHandler implements EventBus.Listener {
@EventBus.EventHandler(State.Handshaking)
public void onRequestHandshake(HandshakeRequestPacket packet, Channel channel) {
channel.attr(State.ATTR_STATE).set(packet.getNextState());
channel.writeAndFlush(new HandshakeResponsePacket());
}
}