PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/engine/src/main/java/org/terasology/entitySystem/event/internal/EventSystemImpl.java

http://github.com/MovingBlocks/Terasology
Java | 608 lines | 514 code | 66 blank | 28 comment | 106 complexity | 971f3f7363daece3b1dfcfe47342fe0b MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright 2013 MovingBlocks
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.terasology.entitySystem.event.internal;
  17. import com.esotericsoftware.reflectasm.MethodAccess;
  18. import com.google.common.base.Objects;
  19. import com.google.common.base.Predicates;
  20. import com.google.common.collect.BiMap;
  21. import com.google.common.collect.HashBiMap;
  22. import com.google.common.collect.HashMultimap;
  23. import com.google.common.collect.ImmutableList;
  24. import com.google.common.collect.Lists;
  25. import com.google.common.collect.Maps;
  26. import com.google.common.collect.Queues;
  27. import com.google.common.collect.SetMultimap;
  28. import com.google.common.collect.Sets;
  29. import org.reflections.ReflectionUtils;
  30. import org.slf4j.Logger;
  31. import org.slf4j.LoggerFactory;
  32. import org.terasology.engine.SimpleUri;
  33. import org.terasology.entitySystem.Component;
  34. import org.terasology.entitySystem.entity.EntityRef;
  35. import org.terasology.entitySystem.event.AbstractConsumableEvent;
  36. import org.terasology.entitySystem.event.ConsumableEvent;
  37. import org.terasology.entitySystem.event.Event;
  38. import org.terasology.entitySystem.event.EventPriority;
  39. import org.terasology.entitySystem.event.PendingEvent;
  40. import org.terasology.entitySystem.event.ReceiveEvent;
  41. import org.terasology.entitySystem.metadata.EventLibrary;
  42. import org.terasology.entitySystem.metadata.EventMetadata;
  43. import org.terasology.entitySystem.systems.ComponentSystem;
  44. import org.terasology.monitoring.PerformanceMonitor;
  45. import org.terasology.network.BroadcastEvent;
  46. import org.terasology.network.Client;
  47. import org.terasology.network.NetworkComponent;
  48. import org.terasology.network.NetworkEvent;
  49. import org.terasology.network.NetworkMode;
  50. import org.terasology.network.NetworkSystem;
  51. import org.terasology.network.OwnerEvent;
  52. import org.terasology.network.ServerEvent;
  53. import org.terasology.recording.EventCatcher;
  54. import org.terasology.recording.RecordAndReplayCurrentStatus;
  55. import org.terasology.recording.RecordAndReplayStatus;
  56. import org.terasology.world.block.BlockComponent;
  57. import java.lang.reflect.Method;
  58. import java.lang.reflect.Modifier;
  59. import java.util.Arrays;
  60. import java.util.Collection;
  61. import java.util.Comparator;
  62. import java.util.Iterator;
  63. import java.util.List;
  64. import java.util.Map;
  65. import java.util.Set;
  66. import java.util.concurrent.BlockingQueue;
  67. /**
  68. * An implementation of the EventSystem.
  69. *
  70. */
  71. public class EventSystemImpl implements EventSystem {
  72. private static final Logger logger = LoggerFactory.getLogger(EventSystemImpl.class);
  73. private Map<Class<? extends Event>, SetMultimap<Class<? extends Component>, EventHandlerInfo>> componentSpecificHandlers = Maps.newHashMap();
  74. private SetMultimap<Class<? extends Event>, EventHandlerInfo> generalHandlers = HashMultimap.create();
  75. private Comparator<EventHandlerInfo> priorityComparator = new EventHandlerPriorityComparator();
  76. // Event metadata
  77. private BiMap<SimpleUri, Class<? extends Event>> eventIdMap = HashBiMap.create();
  78. private SetMultimap<Class<? extends Event>, Class<? extends Event>> childEvents = HashMultimap.create();
  79. private Thread mainThread;
  80. private BlockingQueue<PendingEvent> pendingEvents = Queues.newLinkedBlockingQueue();
  81. private EventLibrary eventLibrary;
  82. private NetworkSystem networkSystem;
  83. private EventCatcher eventCatcher;
  84. private RecordAndReplayCurrentStatus recordAndReplayCurrentStatus;
  85. public EventSystemImpl(EventLibrary eventLibrary, NetworkSystem networkSystem, EventCatcher eventCatcher, RecordAndReplayCurrentStatus recordAndReplayCurrentStatus) {
  86. this.mainThread = Thread.currentThread();
  87. this.eventLibrary = eventLibrary;
  88. this.networkSystem = networkSystem;
  89. this.eventCatcher = eventCatcher;
  90. this.eventCatcher.startTimer();
  91. this.recordAndReplayCurrentStatus = recordAndReplayCurrentStatus;
  92. }
  93. @Override
  94. public void process() {
  95. for (PendingEvent event = pendingEvents.poll(); event != null; event = pendingEvents.poll()) {
  96. if (event.getComponent() != null) {
  97. send(event.getEntity(), event.getEvent(), event.getComponent());
  98. } else {
  99. send(event.getEntity(), event.getEvent());
  100. }
  101. }
  102. }
  103. @Override
  104. public void registerEvent(SimpleUri uri, Class<? extends Event> eventType) {
  105. eventIdMap.put(uri, eventType);
  106. logger.debug("Registering event {}", eventType.getSimpleName());
  107. for (Class parent : ReflectionUtils.getAllSuperTypes(eventType, Predicates.assignableFrom(Event.class))) {
  108. if (!AbstractConsumableEvent.class.equals(parent) && !Event.class.equals(parent)) {
  109. childEvents.put(parent, eventType);
  110. }
  111. }
  112. if (shouldAddToLibrary(eventType)) {
  113. eventLibrary.register(uri, eventType);
  114. }
  115. }
  116. /**
  117. * Events are added to the event library if they have a network annotation
  118. *
  119. * @param eventType the type of the event to be checked
  120. * @return Whether the event should be added to the event library
  121. */
  122. private boolean shouldAddToLibrary(Class<? extends Event> eventType) {
  123. return eventType.getAnnotation(ServerEvent.class) != null
  124. || eventType.getAnnotation(OwnerEvent.class) != null
  125. || eventType.getAnnotation(BroadcastEvent.class) != null;
  126. }
  127. @Override
  128. public void registerEventHandler(ComponentSystem handler) {
  129. Class handlerClass = handler.getClass();
  130. if (!Modifier.isPublic(handlerClass.getModifiers())) {
  131. logger.error("Cannot register handler {}, must be public", handler.getClass().getName());
  132. return;
  133. }
  134. logger.debug("Registering event handler " + handlerClass.getName());
  135. for (Method method : handlerClass.getMethods()) {
  136. ReceiveEvent receiveEventAnnotation = method.getAnnotation(ReceiveEvent.class);
  137. if (receiveEventAnnotation != null) {
  138. if (!receiveEventAnnotation.netFilter().isValidFor(networkSystem.getMode(), false)) {
  139. continue;
  140. }
  141. Set<Class<? extends Component>> requiredComponents = Sets.newLinkedHashSet();
  142. method.setAccessible(true);
  143. Class<?>[] types = method.getParameterTypes();
  144. logger.debug("Found method: " + method.toString());
  145. if (!Event.class.isAssignableFrom(types[0]) || !EntityRef.class.isAssignableFrom(types[1])) {
  146. logger.error("Invalid event handler method: {}", method.getName());
  147. return;
  148. }
  149. requiredComponents.addAll(Arrays.asList(receiveEventAnnotation.components()));
  150. List<Class<? extends Component>> componentParams = Lists.newArrayList();
  151. for (int i = 2; i < types.length; ++i) {
  152. if (!Component.class.isAssignableFrom(types[i])) {
  153. logger.error("Invalid event handler method: {} - {} is not a component class", method.getName(), types[i]);
  154. return;
  155. }
  156. requiredComponents.add((Class<? extends Component>) types[i]);
  157. componentParams.add((Class<? extends Component>) types[i]);
  158. }
  159. ByteCodeEventHandlerInfo handlerInfo = new ByteCodeEventHandlerInfo(handler, method, receiveEventAnnotation.priority(),
  160. receiveEventAnnotation.activity(), requiredComponents, componentParams);
  161. addEventHandler((Class<? extends Event>) types[0], handlerInfo, requiredComponents);
  162. }
  163. }
  164. }
  165. @Override
  166. public void unregisterEventHandler(ComponentSystem handler) {
  167. for (SetMultimap<Class<? extends Component>, EventHandlerInfo> eventHandlers : componentSpecificHandlers.values()) {
  168. Iterator<EventHandlerInfo> eventHandlerIterator = eventHandlers.values().iterator();
  169. while (eventHandlerIterator.hasNext()) {
  170. EventHandlerInfo eventHandler = eventHandlerIterator.next();
  171. if (eventHandler.getHandler().equals(handler)) {
  172. eventHandlerIterator.remove();
  173. }
  174. }
  175. }
  176. Iterator<EventHandlerInfo> eventHandlerIterator = generalHandlers.values().iterator();
  177. while (eventHandlerIterator.hasNext()) {
  178. EventHandlerInfo eventHandler = eventHandlerIterator.next();
  179. if (eventHandler.getHandler().equals(handler)) {
  180. eventHandlerIterator.remove();
  181. }
  182. }
  183. }
  184. private void addEventHandler(Class<? extends Event> type, EventHandlerInfo handler, Collection<Class<? extends Component>> components) {
  185. if (components.isEmpty()) {
  186. generalHandlers.put(type, handler);
  187. for (Class<? extends Event> childType : childEvents.get(type)) {
  188. generalHandlers.put(childType, handler);
  189. }
  190. } else {
  191. for (Class<? extends Component> c : components) {
  192. addToComponentSpecificHandlers(type, handler, c);
  193. for (Class<? extends Event> childType : childEvents.get(type)) {
  194. addToComponentSpecificHandlers(childType, handler, c);
  195. }
  196. }
  197. }
  198. }
  199. private void addToComponentSpecificHandlers(Class<? extends Event> type, EventHandlerInfo handlerInfo, Class<? extends Component> c) {
  200. SetMultimap<Class<? extends Component>, EventHandlerInfo> componentMap = componentSpecificHandlers.get(type);
  201. if (componentMap == null) {
  202. componentMap = HashMultimap.create();
  203. componentSpecificHandlers.put(type, componentMap);
  204. }
  205. componentMap.put(c, handlerInfo);
  206. }
  207. @Override
  208. public <T extends Event> void registerEventReceiver(EventReceiver<T> eventReceiver, Class<T> eventClass, Class<? extends Component>... componentTypes) {
  209. registerEventReceiver(eventReceiver, eventClass, EventPriority.PRIORITY_NORMAL, componentTypes);
  210. }
  211. @Override
  212. public <T extends Event> void registerEventReceiver(EventReceiver<T> eventReceiver, Class<T> eventClass, int priority, Class<? extends Component>... componentTypes) {
  213. EventHandlerInfo info = new ReceiverEventHandlerInfo<>(eventReceiver, priority, componentTypes);
  214. addEventHandler(eventClass, info, Arrays.asList(componentTypes));
  215. }
  216. @Override
  217. public <T extends Event> void unregisterEventReceiver(EventReceiver<T> eventReceiver, Class<T> eventClass, Class<? extends Component>... componentTypes) {
  218. SetMultimap<Class<? extends Component>, EventHandlerInfo> eventHandlerMap = componentSpecificHandlers.get(eventClass);
  219. if (eventHandlerMap != null) {
  220. ReceiverEventHandlerInfo testReceiver = new ReceiverEventHandlerInfo<>(eventReceiver, 0, componentTypes);
  221. for (Class<? extends Component> c : componentTypes) {
  222. eventHandlerMap.remove(c, testReceiver);
  223. for (Class<? extends Event> childType : childEvents.get(eventClass)) {
  224. eventHandlerMap.remove(childType, testReceiver);
  225. }
  226. }
  227. }
  228. if (0 == componentTypes.length) {
  229. Iterator<EventHandlerInfo> eventHandlerIterator = generalHandlers.values().iterator();
  230. while (eventHandlerIterator.hasNext()) {
  231. EventHandlerInfo eventHandler = eventHandlerIterator.next();
  232. if (eventHandler.getHandler().equals(eventReceiver)) {
  233. eventHandlerIterator.remove();
  234. }
  235. }
  236. }
  237. }
  238. @Override
  239. public void send(EntityRef entity, Event event) {
  240. if (Thread.currentThread() != mainThread) {
  241. pendingEvents.offer(new PendingEvent(entity, event));
  242. } else {
  243. if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.RECORDING) {
  244. eventCatcher.addEvent(new PendingEvent(entity, event));
  245. }
  246. networkReplicate(entity, event);
  247. Set<EventHandlerInfo> selectedHandlersSet = selectEventHandlers(event.getClass(), entity);
  248. List<EventHandlerInfo> selectedHandlers = Lists.newArrayList(selectedHandlersSet);
  249. selectedHandlers.sort(priorityComparator);
  250. if (event instanceof ConsumableEvent) {
  251. sendConsumableEvent(entity, event, selectedHandlers);
  252. } else {
  253. sendStandardEvent(entity, event, selectedHandlers);
  254. }
  255. }
  256. }
  257. private void sendStandardEvent(EntityRef entity, Event event, List<EventHandlerInfo> selectedHandlers) {
  258. for (EventHandlerInfo handler : selectedHandlers) {
  259. // Check isValid at each stage in case components were removed.
  260. if (handler.isValidFor(entity)) {
  261. handler.invoke(entity, event);
  262. }
  263. }
  264. }
  265. private void sendConsumableEvent(EntityRef entity, Event event, List<EventHandlerInfo> selectedHandlers) {
  266. ConsumableEvent consumableEvent = (ConsumableEvent) event;
  267. for (EventHandlerInfo handler : selectedHandlers) {
  268. // Check isValid at each stage in case components were removed.
  269. if (handler.isValidFor(entity)) {
  270. handler.invoke(entity, event);
  271. if (consumableEvent.isConsumed()) {
  272. return;
  273. }
  274. }
  275. }
  276. }
  277. private void networkReplicate(EntityRef entity, Event event) {
  278. EventMetadata metadata = eventLibrary.getMetadata(event);
  279. if (metadata != null && metadata.isNetworkEvent()) {
  280. logger.debug("Replicating event: {}", event);
  281. switch (metadata.getNetworkEventType()) {
  282. case BROADCAST:
  283. broadcastEvent(entity, event, metadata);
  284. break;
  285. case OWNER:
  286. sendEventToOwner(entity, event);
  287. break;
  288. case SERVER:
  289. sendEventToServer(entity, event);
  290. break;
  291. default:
  292. break;
  293. }
  294. }
  295. }
  296. private void sendEventToServer(EntityRef entity, Event event) {
  297. if (networkSystem.getMode() == NetworkMode.CLIENT) {
  298. NetworkComponent netComp = entity.getComponent(NetworkComponent.class);
  299. if (netComp != null) {
  300. networkSystem.getServer().send(event, entity);
  301. }
  302. }
  303. }
  304. private void sendEventToOwner(EntityRef entity, Event event) {
  305. if (networkSystem.getMode().isServer()) {
  306. NetworkComponent netComp = entity.getComponent(NetworkComponent.class);
  307. if (netComp != null) {
  308. Client client = networkSystem.getOwner(entity);
  309. if (client != null) {
  310. client.send(event, entity);
  311. }
  312. }
  313. }
  314. }
  315. private void broadcastEvent(EntityRef entity, Event event, EventMetadata metadata) {
  316. if (networkSystem.getMode().isServer()) {
  317. NetworkComponent netComp = entity.getComponent(NetworkComponent.class);
  318. BlockComponent blockComp = entity.getComponent(BlockComponent.class);
  319. if (netComp != null || blockComp != null) {
  320. Client instigatorClient = null;
  321. if (metadata.isSkipInstigator() && event instanceof NetworkEvent) {
  322. instigatorClient = networkSystem.getOwner(((NetworkEvent) event).getInstigator());
  323. }
  324. for (Client client : networkSystem.getPlayers()) {
  325. if (!client.equals(instigatorClient)) {
  326. client.send(event, entity);
  327. }
  328. }
  329. }
  330. }
  331. }
  332. @Override
  333. public void send(EntityRef entity, Event event, Component component) {
  334. if (Thread.currentThread() != mainThread) {
  335. pendingEvents.offer(new PendingEvent(entity, event, component));
  336. } else {
  337. if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.RECORDING) {
  338. eventCatcher.addEvent(new PendingEvent(entity, event, component));
  339. }
  340. SetMultimap<Class<? extends Component>, EventHandlerInfo> handlers = componentSpecificHandlers.get(event.getClass());
  341. if (handlers != null) {
  342. List<EventHandlerInfo> eventHandlers = Lists.newArrayList(handlers.get(component.getClass()));
  343. eventHandlers.sort(priorityComparator);
  344. for (EventHandlerInfo eventHandler : eventHandlers) {
  345. if (eventHandler.isValidFor(entity)) {
  346. eventHandler.invoke(entity, event);
  347. }
  348. }
  349. }
  350. }
  351. }
  352. private Set<EventHandlerInfo> selectEventHandlers(Class<? extends Event> eventType, EntityRef entity) {
  353. Set<EventHandlerInfo> result = Sets.newHashSet();
  354. result.addAll(generalHandlers.get(eventType));
  355. SetMultimap<Class<? extends Component>, EventHandlerInfo> handlers = componentSpecificHandlers.get(eventType);
  356. if (handlers == null) {
  357. return result;
  358. }
  359. for (Class<? extends Component> compClass : handlers.keySet()) {
  360. if (entity.hasComponent(compClass)) {
  361. for (EventHandlerInfo eventHandler : handlers.get(compClass)) {
  362. if (eventHandler.isValidFor(entity)) {
  363. result.add(eventHandler);
  364. }
  365. }
  366. }
  367. }
  368. return result;
  369. }
  370. private static class EventHandlerPriorityComparator implements Comparator<EventHandlerInfo> {
  371. @Override
  372. public int compare(EventHandlerInfo o1, EventHandlerInfo o2) {
  373. return o2.getPriority() - o1.getPriority();
  374. }
  375. }
  376. private interface EventHandlerInfo {
  377. boolean isValidFor(EntityRef entity);
  378. void invoke(EntityRef entity, Event event);
  379. int getPriority();
  380. Object getHandler();
  381. }
  382. private static class ReflectedEventHandlerInfo implements EventHandlerInfo {
  383. private ComponentSystem handler;
  384. private Method method;
  385. private ImmutableList<Class<? extends Component>> filterComponents;
  386. private ImmutableList<Class<? extends Component>> componentParams;
  387. private int priority;
  388. ReflectedEventHandlerInfo(ComponentSystem handler,
  389. Method method,
  390. int priority,
  391. Collection<Class<? extends Component>> filterComponents,
  392. Collection<Class<? extends Component>> componentParams) {
  393. this.handler = handler;
  394. this.method = method;
  395. this.filterComponents = ImmutableList.copyOf(filterComponents);
  396. this.componentParams = ImmutableList.copyOf(componentParams);
  397. this.priority = priority;
  398. }
  399. @Override
  400. public boolean isValidFor(EntityRef entity) {
  401. for (Class<? extends Component> component : filterComponents) {
  402. if (!entity.hasComponent(component)) {
  403. return false;
  404. }
  405. }
  406. return true;
  407. }
  408. @Override
  409. public void invoke(EntityRef entity, Event event) {
  410. try {
  411. Object[] params = new Object[2 + componentParams.size()];
  412. params[0] = event;
  413. params[1] = entity;
  414. for (int i = 0; i < componentParams.size(); ++i) {
  415. params[i + 2] = entity.getComponent(componentParams.get(i));
  416. }
  417. method.invoke(handler, params);
  418. } catch (Exception ex) {
  419. logger.error("Failed to invoke event", ex);
  420. }
  421. }
  422. @Override
  423. public int getPriority() {
  424. return priority;
  425. }
  426. @Override
  427. public ComponentSystem getHandler() {
  428. return handler;
  429. }
  430. }
  431. private static class ByteCodeEventHandlerInfo implements EventHandlerInfo {
  432. private ComponentSystem handler;
  433. private String activity;
  434. private MethodAccess methodAccess;
  435. private int methodIndex;
  436. private ImmutableList<Class<? extends Component>> filterComponents;
  437. private ImmutableList<Class<? extends Component>> componentParams;
  438. private int priority;
  439. ByteCodeEventHandlerInfo(ComponentSystem handler,
  440. Method method,
  441. int priority,
  442. String activity,
  443. Collection<Class<? extends Component>> filterComponents,
  444. Collection<Class<? extends Component>> componentParams) {
  445. this.handler = handler;
  446. this.activity = activity;
  447. this.methodAccess = MethodAccess.get(handler.getClass());
  448. methodIndex = methodAccess.getIndex(method.getName(), method.getParameterTypes());
  449. this.filterComponents = ImmutableList.copyOf(filterComponents);
  450. this.componentParams = ImmutableList.copyOf(componentParams);
  451. this.priority = priority;
  452. }
  453. @Override
  454. public boolean isValidFor(EntityRef entity) {
  455. for (Class<? extends Component> component : filterComponents) {
  456. if (!entity.hasComponent(component)) {
  457. return false;
  458. }
  459. }
  460. return true;
  461. }
  462. @Override
  463. public void invoke(EntityRef entity, Event event) {
  464. try {
  465. Object[] params = new Object[2 + componentParams.size()];
  466. params[0] = event;
  467. params[1] = entity;
  468. for (int i = 0; i < componentParams.size(); ++i) {
  469. params[i + 2] = entity.getComponent(componentParams.get(i));
  470. }
  471. if (!activity.isEmpty()) {
  472. PerformanceMonitor.startActivity(activity);
  473. }
  474. try {
  475. methodAccess.invoke(handler, methodIndex, params);
  476. } finally {
  477. if (!activity.isEmpty()) {
  478. PerformanceMonitor.endActivity();
  479. }
  480. }
  481. } catch (Exception ex) {
  482. logger.error("Failed to invoke event", ex);
  483. }
  484. }
  485. @Override
  486. public int getPriority() {
  487. return priority;
  488. }
  489. @Override
  490. public ComponentSystem getHandler() {
  491. return handler;
  492. }
  493. }
  494. private static class ReceiverEventHandlerInfo<T extends Event> implements EventHandlerInfo {
  495. private EventReceiver<T> receiver;
  496. private Class<? extends Component>[] components;
  497. private int priority;
  498. ReceiverEventHandlerInfo(EventReceiver<T> receiver, int priority, Class<? extends Component>... components) {
  499. this.receiver = receiver;
  500. this.priority = priority;
  501. this.components = Arrays.copyOf(components, components.length);
  502. }
  503. @Override
  504. public boolean isValidFor(EntityRef entity) {
  505. for (Class<? extends Component> component : components) {
  506. if (!entity.hasComponent(component)) {
  507. return false;
  508. }
  509. }
  510. return true;
  511. }
  512. @Override
  513. public void invoke(EntityRef entity, Event event) {
  514. receiver.onEvent((T) event, entity);
  515. }
  516. @Override
  517. public int getPriority() {
  518. return priority;
  519. }
  520. @Override
  521. public boolean equals(Object obj) {
  522. if (obj == this) {
  523. return true;
  524. }
  525. if (obj instanceof ReceiverEventHandlerInfo) {
  526. ReceiverEventHandlerInfo other = (ReceiverEventHandlerInfo) obj;
  527. if (Objects.equal(receiver, other.receiver)) {
  528. return true;
  529. }
  530. }
  531. return false;
  532. }
  533. @Override
  534. public int hashCode() {
  535. return Objects.hashCode(receiver);
  536. }
  537. @Override
  538. public Object getHandler() {
  539. return receiver;
  540. }
  541. }
  542. }