Merge branch 'event' into proto_1.12.2
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
package mc.core;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.eventbus.EventBusGetter;
|
||||
import mc.core.eventbus.EventBus;
|
||||
import mc.core.eventbus.Subscriber;
|
||||
import mc.core.eventbus.events.CS_PlayerMoveEvent;
|
||||
import mc.core.eventbus.events.SC_ChunkLoadEvent;
|
||||
import mc.core.eventbus.events.SC_ChunkUnloadEvent;
|
||||
@@ -16,13 +16,11 @@ import java.util.Iterator;
|
||||
public class CoreEventListener {
|
||||
@PostConstruct
|
||||
public void registerEventHandlers() {
|
||||
EventBusGetter.getInstance().register(this);
|
||||
EventBus.getInstance().registerSubscribes(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Subscriber
|
||||
public void handlerPlayerMoveEvent(CS_PlayerMoveEvent event) {
|
||||
log.trace("(GameLoop) playerMoveEventHandler()");
|
||||
|
||||
Chunk chunk;
|
||||
chunk = event.getPlayer().getWorld().getChunk(event.getOldLocation().toBlockLocation()); // Old chunk
|
||||
int ccX = chunk.getX();
|
||||
@@ -50,7 +48,7 @@ public class CoreEventListener {
|
||||
}
|
||||
|
||||
if (!eventChunkUnload.getNeedUnloadChunks().isEmpty()) {
|
||||
EventBusGetter.getInstance().post(eventChunkUnload);
|
||||
EventBus.getInstance().post(eventChunkUnload);
|
||||
}
|
||||
|
||||
SC_ChunkLoadEvent eventChunkLoad = new SC_ChunkLoadEvent(event.getPlayer());
|
||||
@@ -67,7 +65,7 @@ public class CoreEventListener {
|
||||
}
|
||||
|
||||
if (!eventChunkLoad.getNeedLoadChunks().isEmpty()) {
|
||||
EventBusGetter.getInstance().post(eventChunkLoad);
|
||||
EventBus.getInstance().post(eventChunkLoad);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package mc.core;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.eventbus.EventBus;
|
||||
import mc.core.player.PlayerManager;
|
||||
import mc.core.time.TimeProcessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -47,6 +48,8 @@ public class GameLoop extends Thread {
|
||||
|
||||
/* --- --- --- */
|
||||
|
||||
EventBus.getInstance().process();
|
||||
|
||||
/* TODO нужно перенести этот функционал на Network */
|
||||
playerManager.getBroadcastChannel().sendTimeUpdate(
|
||||
gameTimer.getGameTime(),
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.eventbus;
|
||||
|
||||
public interface Event {
|
||||
void setCanceled(boolean value);
|
||||
boolean isCanceled();
|
||||
|
||||
void setLastProcess(boolean value);
|
||||
boolean isLastProcess();
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.eventbus;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class EventBase implements Event {
|
||||
private boolean canceled;
|
||||
private boolean lastProcess;
|
||||
}
|
||||
89
core/src/main/java/mc/core/eventbus/EventBus.java
Normal file
89
core/src/main/java/mc/core/eventbus/EventBus.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package mc.core.eventbus;
|
||||
|
||||
import javafx.util.Pair;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Slf4j
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class EventBus {
|
||||
@Getter
|
||||
private static final EventBus instance = new EventBus();
|
||||
|
||||
private Queue<Event> eventQueue = new ConcurrentLinkedQueue<>();
|
||||
private Map<Class<? extends Event>, List<Pair<Object, Method>>> subscribes = new HashMap<>();
|
||||
|
||||
private Stream<Method> getMethods(Object subscriberObject) {
|
||||
return Stream.of(subscriberObject.getClass().getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(Subscriber.class))
|
||||
.filter(method -> method.getReturnType().equals(Void.TYPE))
|
||||
.filter(method -> method.getParameterCount() == 1)
|
||||
.filter(method -> Event.class.isAssignableFrom(method.getParameterTypes()[0]));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerSubscribes(Object subscriberObject) {
|
||||
getMethods(subscriberObject)
|
||||
.forEach(method -> {
|
||||
final Class<? extends Event> type = (Class<? extends Event>) method.getParameterTypes()[0];
|
||||
final List<Pair<Object, Method>> pairs;
|
||||
if (subscribes.containsKey(type)) {
|
||||
pairs = subscribes.get(type);
|
||||
} else {
|
||||
pairs = new ArrayList<>();
|
||||
subscribes.put(type, pairs);
|
||||
}
|
||||
pairs.add(new Pair<>(subscriberObject, method));
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void unregisterSubscribes(Object subscriberObject) {
|
||||
getMethods(subscriberObject)
|
||||
.forEach(method -> {
|
||||
final Class<? extends Event> type = (Class<? extends Event>) method.getParameterTypes()[0];
|
||||
if (subscribes.containsKey(type)) {
|
||||
final List<Pair<Object, Method>> pairs = subscribes.get(type);
|
||||
pairs.removeIf(pair -> pair.getKey() == subscriberObject);
|
||||
|
||||
if (pairs.isEmpty()) {
|
||||
subscribes.remove(type);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void post(Event event) {
|
||||
eventQueue.add(event);
|
||||
}
|
||||
|
||||
public void process() {
|
||||
Event event;
|
||||
while ((event = eventQueue.poll()) != null) {
|
||||
final Class<? extends Event> type = event.getClass();
|
||||
if (subscribes.containsKey(type)) {
|
||||
final List<Pair<Object, Method>> pairs = subscribes.get(type);
|
||||
for (Pair<Object, Method> pair : pairs) {
|
||||
try {
|
||||
pair.getValue().invoke(pair.getKey(), event);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.error(MessageFormatter.format("Invoke method '{}#{}'",
|
||||
pair.getKey().getClass().getSimpleName(),
|
||||
pair.getValue().getName()).getMessage(),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.eventbus;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import lombok.Getter;
|
||||
|
||||
public final class EventBusGetter {
|
||||
@Getter
|
||||
private static final EventBus instance = new EventBus();
|
||||
|
||||
private EventBusGetter() {
|
||||
}
|
||||
}
|
||||
11
core/src/main/java/mc/core/eventbus/Subscriber.java
Normal file
11
core/src/main/java/mc/core/eventbus/Subscriber.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package mc.core.eventbus;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(value= ElementType.METHOD)
|
||||
@Retention(value= RetentionPolicy.RUNTIME)
|
||||
public @interface Subscriber {
|
||||
}
|
||||
@@ -1,18 +1,14 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.ImmutableEntityLocation;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.eventbus.Event;
|
||||
import mc.core.player.Player;
|
||||
|
||||
@Getter
|
||||
public class CS_PlayerMoveEvent extends EventBase {
|
||||
public class CS_PlayerMoveEvent implements Event {
|
||||
private final Player player;
|
||||
private final ImmutableEntityLocation oldLocation;
|
||||
@Setter
|
||||
|
||||
@@ -2,14 +2,14 @@ package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.eventbus.Event;
|
||||
import mc.core.player.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SC_ChunkLoadEvent extends EventBase {
|
||||
public class SC_ChunkLoadEvent implements Event {
|
||||
@Getter
|
||||
private final Player player;
|
||||
@Getter
|
||||
|
||||
@@ -2,14 +2,14 @@ package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.eventbus.Event;
|
||||
import mc.core.player.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SC_ChunkUnloadEvent extends EventBase {
|
||||
public class SC_ChunkUnloadEvent implements Event {
|
||||
@Getter
|
||||
private final Player player;
|
||||
@Getter
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.eventbus.EventBase;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class SC_LoginEvent extends EventBase {
|
||||
private String playerName;
|
||||
private final SocketAddress remoteAddress;
|
||||
private boolean deny;
|
||||
private String denyReason;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.player.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class SC_PlayerLookEvent extends EventBase {
|
||||
private final Player player;
|
||||
private EntityLocation newLook;
|
||||
}
|
||||
@@ -4,12 +4,12 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.eventbus.Event;
|
||||
import mc.core.player.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class SC_PlayerMoveEvent extends EventBase {
|
||||
public class SC_PlayerMoveEvent implements Event {
|
||||
private final Player player;
|
||||
@Setter
|
||||
private EntityLocation newLocation;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.eventbus.EventBase;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class SC_ServerPingEvent extends EventBase {
|
||||
private final SocketAddress remoteAddress;
|
||||
private String description;
|
||||
private int online;
|
||||
private int maxOnline;
|
||||
}
|
||||
125
core/src/test/java/mc/core/TestEventBus.java
Normal file
125
core/src/test/java/mc/core/TestEventBus.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package mc.core;
|
||||
|
||||
import javafx.util.Pair;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
import mc.core.eventbus.Event;
|
||||
import mc.core.eventbus.EventBus;
|
||||
import mc.core.eventbus.Subscriber;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
class TestEventBus {
|
||||
private List<String> resultList = new ArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<Class<? extends Event>, List<Pair<Object, Method>>> getEventBusFieldSubscribes() {
|
||||
return (Map<Class<? extends Event>, List<Pair<Object, Method>>>)
|
||||
Whitebox.getInternalState(EventBus.getInstance(), "subscribes");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@SuppressWarnings("unchecked")
|
||||
void before() {
|
||||
getEventBusFieldSubscribes().clear();
|
||||
((Queue<Event>) Whitebox.getInternalState(EventBus.getInstance(), "eventQueue")).clear();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testRegisterSubscribes() {
|
||||
DumbEventHandler handler = new DumbEventHandler();
|
||||
EventBus.getInstance().registerSubscribes(handler);
|
||||
|
||||
Map<Class<? extends Event>, List<Pair<Object, Method>>> subscribes = getEventBusFieldSubscribes();
|
||||
assertEquals(1, subscribes.size());
|
||||
|
||||
List<Pair<Object, Method>> pairs = subscribes.values().iterator().next();
|
||||
assertEquals(1, pairs.size());
|
||||
|
||||
Pair<Object, Method> pair = pairs.get(0);
|
||||
assertSame(handler, pair.getKey());
|
||||
assertEquals("corectSubscribe", pair.getValue().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnregisterSubscribes() {
|
||||
DumbEventHandler handler = new DumbEventHandler();
|
||||
EventBus.getInstance().registerSubscribes(handler);
|
||||
|
||||
EventBus.getInstance().unregisterSubscribes(handler);
|
||||
|
||||
Map<Class<? extends Event>, List<Pair<Object, Method>>> subscribes = getEventBusFieldSubscribes();
|
||||
assertEquals(0, subscribes.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void testPost() {
|
||||
EventBus.getInstance().post(new DumbEvent());
|
||||
|
||||
Queue<Event> eventQueue = (Queue<Event>) Whitebox.getInternalState(EventBus.getInstance(), "eventQueue");
|
||||
assertEquals(1, eventQueue.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProcess() {
|
||||
Stream.of(new DumbEventHandler("D1 "), new DumbEventHandler("D2 "))
|
||||
.forEach(handler -> EventBus.getInstance().registerSubscribes(handler));
|
||||
|
||||
Stream.of(new DumbEvent("message 1"), new DumbEvent("message 2"))
|
||||
.forEach(event -> EventBus.getInstance().post(event));
|
||||
|
||||
EventBus.getInstance().process();
|
||||
|
||||
assertEquals(4, resultList.size());
|
||||
assertEquals("D1 message 1", resultList.get(0));
|
||||
assertEquals("D2 message 1", resultList.get(1));
|
||||
assertEquals("D1 message 2", resultList.get(2));
|
||||
assertEquals("D2 message 2", resultList.get(3));
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
private class DumbEvent implements Event {
|
||||
String message;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DumbEventHandler {
|
||||
private String prefix = "";
|
||||
|
||||
@Subscriber
|
||||
public void corectSubscribe(DumbEvent event) {
|
||||
resultList.add(prefix + event.message);
|
||||
}
|
||||
|
||||
@Subscriber
|
||||
public Object incorectSubscribeReturnType(DumbEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Subscriber
|
||||
public void incorrectSubscriberTypeParameter(Object object) {
|
||||
}
|
||||
|
||||
@Subscriber
|
||||
public void incorrectSubscriberManyParameters(DumbEvent event, Object object) {
|
||||
}
|
||||
|
||||
public void someMethod() {
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user