EventBus
This commit is contained in:
89
src/main/java/mc/core/netty/EventBus.java
Normal file
89
src/main/java/mc/core/netty/EventBus.java
Normal 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import mc.core.Server;
|
||||
import mc.core.StartServerException;
|
||||
import mc.core.netty.handlers.HandshakeHandler;
|
||||
|
||||
public class NettyServer implements Server {
|
||||
private EventLoopGroup bossGroup, workerGroup;
|
||||
@@ -48,6 +49,8 @@ public class NettyServer implements Server {
|
||||
|
||||
ServerBootstrap serverBootstrap = buildServerBootstrap();
|
||||
|
||||
EventBus.getInstance().listenIncomingPacket(new HandshakeHandler());
|
||||
|
||||
try {
|
||||
serverBootstrap.bind(host, port).sync().channel().closeFuture().sync();
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
@@ -26,10 +26,10 @@ public class PacketHandler extends SimpleChannelInboundHandler<Packet> {
|
||||
packet.getClass().getSimpleName(),
|
||||
packet.toString());
|
||||
|
||||
if (equalsPacket(packet, "HandshakeRequestPacket")) {
|
||||
HandshakeRequestPacket pkt = (HandshakeRequestPacket) packet;
|
||||
context.channel().attr(State.ATTR_STATE).set(pkt.getNextState());
|
||||
context.channel().writeAndFlush(new HandshakeResponsePacket());
|
||||
}
|
||||
EventBus.getInstance().eventIncomingPacket(
|
||||
context.channel().attr(State.ATTR_STATE).get().getId(),
|
||||
packet,
|
||||
context.channel()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
package mc.core.netty;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.netty.util.AttributeKey;
|
||||
import lombok.Getter;
|
||||
@@ -16,11 +18,11 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum State {
|
||||
Handshaking(1, ImmutableMap.of(
|
||||
Handshaking(1, ImmutableBiMap.of(
|
||||
0, HandshakeRequestPacket.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");
|
||||
|
||||
@@ -30,9 +32,9 @@ public enum State {
|
||||
|
||||
@Getter
|
||||
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.requestMap = requestMap;
|
||||
}
|
||||
@@ -40,4 +42,8 @@ public enum State {
|
||||
public Optional<Class<? extends Packet>> getPacketClass(int id) {
|
||||
return Optional.ofNullable(requestMap.get(id));
|
||||
}
|
||||
|
||||
public Optional<Integer> getPacketId(Class<? extends Packet> clazz) {
|
||||
return Optional.ofNullable(requestMap.inverse().get(clazz));
|
||||
}
|
||||
}
|
||||
|
||||
21
src/main/java/mc/core/netty/handlers/HandshakeHandler.java
Normal file
21
src/main/java/mc/core/netty/handlers/HandshakeHandler.java
Normal 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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user