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 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) {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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