Archived
0

Merge remote-tracking branch 'event' into world-loader-anvil

# Conflicts:
#	core/src/main/java/mc/core/CoreEventListener.java
This commit is contained in:
2019-01-12 22:11:34 +03:00
20 changed files with 293 additions and 141 deletions

View File

@@ -1,3 +1,6 @@
import java.nio.file.Files
import java.nio.file.Paths
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
@@ -85,6 +88,43 @@ subprojects {
task cleanDep(type: Delete) {
delete 'libs'
}
/**
* Сборка
*/
task deploy() {
dependsOn { jar }
doLast {
def deployDir = System.getProperty("deploy")
if (deployDir == null) {
println "Need param -Ddeploy=path/to/deploy"
throw new Exception("Need param -Ddir=path/to/deploy")
}
def target = Paths.get(deployDir, jar.archivePath.getName())
if (Files.notExists(target)) {
println jar.archivePath
Files.copy(jar.archivePath.toPath(), target)
}
def libsDir = System.getProperty("libs", deployDir+File.separator+"libs")
if (Files.notExists(Paths.get(libsDir))) {
(new File(libsDir)).mkdirs()
}
def libsCollection = configurations.compile + configurations.runtime - configurations.compile_excludeCopy
libsCollection.each{ libFile ->
target = Paths.get(libsDir, libFile.getName())
if (Files.notExists(target)) {
println libFile
Files.copy(libFile.toPath(), target)
}
}
}
}
}
/**

View File

@@ -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
if (chunk == null) return;
@@ -54,7 +52,7 @@ public class CoreEventListener {
}
if (!eventChunkLoad.getNeedLoadChunks().isEmpty()) {
EventBusGetter.getInstance().post(eventChunkLoad);
EventBus.getInstance().post(eventChunkLoad);
}
SC_ChunkUnloadEvent eventChunkUnload = new SC_ChunkUnloadEvent(event.getPlayer());
@@ -69,7 +67,7 @@ public class CoreEventListener {
}
if (!eventChunkUnload.getNeedUnloadChunks().isEmpty()) {
EventBusGetter.getInstance().post(eventChunkUnload);
EventBus.getInstance().post(eventChunkUnload);
}
}

View File

@@ -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(),

View File

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

View File

@@ -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;
}

View 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
);
}
}
}
}
}
}

View File

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

View 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 {
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

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

View File

@@ -11,7 +11,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.AttributeKey;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import mc.core.eventbus.EventBusGetter;
import mc.core.eventbus.EventBus;
import mc.core.network.Server;
import mc.core.network.StartServerException;
import mc.core.network.proto_1_12_2.State;
@@ -65,7 +65,7 @@ public class NettyServer implements Server {
public void start() throws StartServerException {
log.info("Use protocol {}", StatusResponsePacket.NAME);
EventBusGetter.getInstance().register(new PlayerEventListener());
EventBus.getInstance().registerSubscribes(new PlayerEventListener());
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup(workerGroupCount);

View File

@@ -1,7 +1,7 @@
package mc.core.network.proto_1_12_2.netty;
import com.google.common.eventbus.Subscribe;
import lombok.extern.slf4j.Slf4j;
import mc.core.eventbus.Subscriber;
import mc.core.eventbus.events.SC_ChunkLoadEvent;
import mc.core.eventbus.events.SC_ChunkUnloadEvent;
import mc.core.eventbus.events.SC_PlayerMoveEvent;
@@ -13,8 +13,8 @@ import mc.core.utils.CompactedCoords;
import mc.core.world.chunk.Chunk;
@Slf4j
class PlayerEventListener {
@Subscribe
public class PlayerEventListener {
@Subscriber
public void playerMoveEventHandler(SC_PlayerMoveEvent event) {
log.debug("(SC) playerMoveEventHandler()");
PlayerPositionAndLookPacket packet = new PlayerPositionAndLookPacket();
@@ -25,7 +25,7 @@ class PlayerEventListener {
event.getPlayer().getChannel().writeAndFlush(packet);
}
@Subscribe
@Subscriber
public void playerChunkLoadHandler(SC_ChunkLoadEvent event) {
for(Integer compressXZ : event.getNeedLoadChunks()) {
int[] xz = CompactedCoords.uncompressXZ(compressXZ);
@@ -42,7 +42,7 @@ class PlayerEventListener {
}
}
@Subscribe
@Subscriber
public void playerChunkUnloadHandler(SC_ChunkUnloadEvent event) {
for(Integer compressXZ : event.getNeedUnloadChunks()) {
int[] xz = CompactedCoords.uncompressXZ(compressXZ);

View File

@@ -2,7 +2,7 @@ package mc.core.network.proto_1_12_2.netty.handlers;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import mc.core.eventbus.EventBusGetter;
import mc.core.eventbus.EventBus;
import mc.core.eventbus.events.CS_PlayerMoveEvent;
import mc.core.network.proto_1_12_2.State;
import mc.core.network.proto_1_12_2.TeleportManager;
@@ -15,9 +15,7 @@ import mc.core.player.PlayerMode;
import mc.core.text.Text;
import mc.core.text.TextColor;
import mc.core.text.TextStyle;
import mc.core.utils.CompactedCoords;
import mc.core.world.World;
import mc.core.world.chunk.Chunk;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -123,7 +121,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
CS_PlayerMoveEvent event = new CS_PlayerMoveEvent(player, player.getLocation());
event.setNewLocation(player.getLocation());
event.setRecalcChunk(true);
EventBusGetter.getInstance().post(event);
EventBus.getInstance().post(event);
}
}
}

View File

@@ -1,14 +1,10 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-06-23
*/
package mc.core.network.proto_1_12_2.netty.handlers;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import mc.core.EntityLocation;
import mc.core.chat.ChatProcessor;
import mc.core.eventbus.EventBusGetter;
import mc.core.eventbus.EventBus;
import mc.core.eventbus.events.CS_PlayerMoveEvent;
import mc.core.network.proto_1_12_2.TeleportManager;
import mc.core.network.proto_1_12_2.packets.*;
@@ -83,7 +79,7 @@ public class PlayHandler extends AbstractStateHandler implements PlayStateHandle
player.getLocation().getYaw(),
player.getLocation().getPitch()
));
EventBusGetter.getInstance().post(event);
EventBus.getInstance().post(event);
}
@Handler