weirdly broken world renderer while triny to optimize
This commit is contained in:
@@ -10,7 +10,7 @@ package mightypork.util.constraints;
|
||||
public abstract class DigestCache<D> implements Digestable<D> {
|
||||
|
||||
private D last_digest;
|
||||
private boolean caching_enabled;
|
||||
private boolean caching_enabled = false;
|
||||
private boolean dirty = true;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package mightypork.util.control.eventbus;
|
||||
|
||||
|
||||
import mightypork.util.control.eventbus.events.flags.DelayedEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.NonConsumableEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.UnloggedEvent;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Event that can be handled by HANDLER, subscribing to the event bus.
|
||||
* </p>
|
||||
* <p>
|
||||
* Can be annotated as {@link SingleReceiverEvent} to be delivered once only,
|
||||
* and {@link DelayedEvent} or {@link ImmediateEvent} to specify default sending
|
||||
* mode. When marked as {@link UnloggedEvent}, it will not appear in detailed
|
||||
* bus logging (useful for very frequent events, such as UpdateEvent).
|
||||
* </p>
|
||||
* <p>
|
||||
* Events annotated as {@link NonConsumableEvent} will throw an exception upon
|
||||
* an attempt to consume them.
|
||||
* </p>
|
||||
* <p>
|
||||
* Default sending mode (if not changed by annotations) is <i>queued</i> with
|
||||
* zero delay.
|
||||
* </p>
|
||||
*
|
||||
* @author MightyPork
|
||||
* @param <HANDLER> handler type
|
||||
*/
|
||||
public abstract class BusEvent<HANDLER> {
|
||||
|
||||
private boolean consumed;
|
||||
private boolean served;
|
||||
|
||||
|
||||
/**
|
||||
* Ask handler to handle this message.
|
||||
*
|
||||
* @param handler handler instance
|
||||
*/
|
||||
protected abstract void handleBy(HANDLER handler);
|
||||
|
||||
|
||||
/**
|
||||
* Consume the event, so no other clients will receive it.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the {@link NonConsumableEvent}
|
||||
* annotation is present.
|
||||
*/
|
||||
public final void consume()
|
||||
{
|
||||
System.out.println("consume "+getClass());
|
||||
if (consumed) throw new IllegalStateException("Already consumed.");
|
||||
|
||||
if (getClass().isAnnotationPresent(NonConsumableEvent.class)) {
|
||||
throw new UnsupportedOperationException("Not consumable.");
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deliver to a handler using the handleBy method.
|
||||
*
|
||||
* @param handler handler instance
|
||||
*/
|
||||
final void deliverTo(HANDLER handler)
|
||||
{
|
||||
handleBy(handler);
|
||||
|
||||
if (!served) {
|
||||
if (getClass().isAnnotationPresent(SingleReceiverEvent.class)) {
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
served = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the event is consumed. Consumed event is not served to other
|
||||
* clients.
|
||||
*
|
||||
* @return true if consumed
|
||||
*/
|
||||
final boolean isConsumed()
|
||||
{
|
||||
return consumed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the event was served to at least 1 client
|
||||
*/
|
||||
final boolean wasServed()
|
||||
{
|
||||
return served;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear "served" and "consumed" flags before dispatching.
|
||||
*/
|
||||
final void clearFlags()
|
||||
{
|
||||
served = false;
|
||||
consumed = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import mightypork.util.control.Destroyable;
|
||||
import mightypork.util.control.eventbus.clients.DelegatingClient;
|
||||
import mightypork.util.control.eventbus.events.Event;
|
||||
import mightypork.util.control.eventbus.events.flags.DelayedEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
|
||||
@@ -32,10 +31,10 @@ final public class EventBus implements Destroyable {
|
||||
private class DelayQueueEntry implements Delayed {
|
||||
|
||||
private final long due;
|
||||
private final Event<?> evt;
|
||||
private final BusEvent<?> evt;
|
||||
|
||||
|
||||
public DelayQueueEntry(double seconds, Event<?> event)
|
||||
public DelayQueueEntry(double seconds, BusEvent<?> event)
|
||||
{
|
||||
super();
|
||||
this.due = System.currentTimeMillis() + (long) (seconds * 1000);
|
||||
@@ -57,7 +56,7 @@ final public class EventBus implements Destroyable {
|
||||
}
|
||||
|
||||
|
||||
public Event<?> getEvent()
|
||||
public BusEvent<?> getEvent()
|
||||
{
|
||||
return evt;
|
||||
}
|
||||
@@ -103,17 +102,17 @@ final public class EventBus implements Destroyable {
|
||||
static final String logMark = "<BUS> ";
|
||||
|
||||
|
||||
private static Class<?> getEventListenerClass(Event<?> event)
|
||||
private static Class<?> getEventListenerClass(BusEvent<?> event)
|
||||
{
|
||||
// BEHOLD, MAGIC!
|
||||
final Type[] interfaces = event.getClass().getGenericInterfaces();
|
||||
for (final Type interf : interfaces) {
|
||||
if (interf instanceof ParameterizedType) {
|
||||
if (((ParameterizedType) interf).getRawType() == Event.class) {
|
||||
final Type[] types = ((ParameterizedType) interf).getActualTypeArguments();
|
||||
for (final Type genericType : types) {
|
||||
return (Class<?>) genericType;
|
||||
}
|
||||
|
||||
final Type evtc = event.getClass().getGenericSuperclass();
|
||||
|
||||
if (evtc instanceof ParameterizedType) {
|
||||
if (((ParameterizedType) evtc).getRawType() == BusEvent.class) {
|
||||
final Type[] types = ((ParameterizedType) evtc).getActualTypeArguments();
|
||||
for (final Type genericType : types) {
|
||||
return (Class<?>) genericType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,7 +168,7 @@ final public class EventBus implements Destroyable {
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
public void send(Event<?> event)
|
||||
public void send(BusEvent<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
@@ -193,7 +192,7 @@ final public class EventBus implements Destroyable {
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
public void sendQueued(Event<?> event)
|
||||
public void sendQueued(BusEvent<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
@@ -207,7 +206,7 @@ final public class EventBus implements Destroyable {
|
||||
* @param event event
|
||||
* @param delay delay before event is dispatched
|
||||
*/
|
||||
public void sendDelayed(Event<?> event, double delay)
|
||||
public void sendDelayed(BusEvent<?> event, double delay)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
@@ -228,7 +227,7 @@ final public class EventBus implements Destroyable {
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
public void sendDirect(Event<?> event)
|
||||
public void sendDirect(BusEvent<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
@@ -238,7 +237,7 @@ final public class EventBus implements Destroyable {
|
||||
}
|
||||
|
||||
|
||||
public void sendDirectToChildren(DelegatingClient delegatingClient, Event<?> event)
|
||||
public void sendDirectToChildren(DelegatingClient delegatingClient, BusEvent<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
@@ -282,7 +281,7 @@ final public class EventBus implements Destroyable {
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean addChannelForEvent(Event<?> event)
|
||||
private boolean addChannelForEvent(BusEvent<?> event)
|
||||
{
|
||||
try {
|
||||
if (detailedLogging) {
|
||||
@@ -298,7 +297,7 @@ final public class EventBus implements Destroyable {
|
||||
//channels.flush();
|
||||
|
||||
if (detailedLogging) {
|
||||
Log.f2("<bus> Created new channel: " + Log.str(event.getClass()) + " -> " + Log.str(listener));
|
||||
Log.f2(logMark + "Created new channel: " + Log.str(event.getClass()) + " -> " + Log.str(listener));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -333,7 +332,7 @@ final public class EventBus implements Destroyable {
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
private synchronized void dispatch(Event<?> event)
|
||||
private synchronized void dispatch(BusEvent<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
@@ -349,12 +348,11 @@ final public class EventBus implements Destroyable {
|
||||
* @param clients clients
|
||||
* @param event event
|
||||
*/
|
||||
private synchronized void doDispatch(Collection<Object> clients, Event<?> event)
|
||||
private synchronized void doDispatch(Collection<Object> clients, BusEvent<?> event)
|
||||
{
|
||||
boolean sent = false;
|
||||
boolean accepted = false;
|
||||
|
||||
final boolean singular = event.getClass().isAnnotationPresent(SingleReceiverEvent.class);
|
||||
event.clearFlags();
|
||||
|
||||
for (int i = 0; i < 2; i++) { // two tries.
|
||||
|
||||
@@ -362,10 +360,10 @@ final public class EventBus implements Destroyable {
|
||||
for (final EventChannel<?, ?> b : channels) {
|
||||
if (b.canBroadcast(event)) {
|
||||
accepted = true;
|
||||
sent |= b.broadcast(event, clients);
|
||||
b.broadcast(event, clients);
|
||||
}
|
||||
|
||||
if (sent && singular) break;
|
||||
if (event.isConsumed()) break;
|
||||
}
|
||||
channels.setBuffering(false);
|
||||
|
||||
@@ -375,11 +373,11 @@ final public class EventBus implements Destroyable {
|
||||
}
|
||||
|
||||
if (!accepted) Log.e(logMark + "Not accepted by any channel: " + Log.str(event));
|
||||
if (!sent && shallLog(event)) Log.w(logMark + "Not delivered: " + Log.str(event));
|
||||
if (!event.wasServed() && shallLog(event)) Log.w(logMark + "Not delivered: " + Log.str(event));
|
||||
}
|
||||
|
||||
|
||||
private boolean shallLog(Event<?> event)
|
||||
private boolean shallLog(BusEvent<?> event)
|
||||
{
|
||||
if (!detailedLogging) return false;
|
||||
if (event.getClass().isAnnotationPresent(UnloggedEvent.class)) return false;
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.HashSet;
|
||||
|
||||
import mightypork.util.control.eventbus.clients.DelegatingClient;
|
||||
import mightypork.util.control.eventbus.clients.ToggleableClient;
|
||||
import mightypork.util.control.eventbus.events.Event;
|
||||
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
|
||||
import mightypork.util.logging.Log;
|
||||
|
||||
@@ -18,7 +17,7 @@ import mightypork.util.logging.Log;
|
||||
* @param <EVENT> event type
|
||||
* @param <CLIENT> client (subscriber) type
|
||||
*/
|
||||
class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
class EventChannel<EVENT extends BusEvent<CLIENT>, CLIENT> {
|
||||
|
||||
private final Class<CLIENT> clientClass;
|
||||
private final Class<EVENT> eventClass;
|
||||
@@ -48,13 +47,12 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
*
|
||||
* @param event a event to be sent
|
||||
* @param clients collection of clients
|
||||
* @return true if event was sent
|
||||
*/
|
||||
public boolean broadcast(Event<?> event, Collection<Object> clients)
|
||||
public void broadcast(BusEvent<?> event, Collection<Object> clients)
|
||||
{
|
||||
if (!canBroadcast(event)) return false;
|
||||
if (!canBroadcast(event)) return;
|
||||
|
||||
return doBroadcast(eventClass.cast(event), clients, new HashSet<>());
|
||||
doBroadcast(eventClass.cast(event), clients, new HashSet<>());
|
||||
}
|
||||
|
||||
|
||||
@@ -64,13 +62,9 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
* @param event sent event
|
||||
* @param clients subscribing clients
|
||||
* @param processed clients already processed
|
||||
* @return success
|
||||
*/
|
||||
private boolean doBroadcast(final EVENT event, final Collection<Object> clients, final Collection<Object> processed)
|
||||
private void doBroadcast(final EVENT event, final Collection<Object> clients, final Collection<Object> processed)
|
||||
{
|
||||
boolean sent = false;
|
||||
final boolean singular = event.getClass().isAnnotationPresent(SingleReceiverEvent.class);
|
||||
|
||||
for (final Object client : clients) {
|
||||
|
||||
// exclude obvious non-clients
|
||||
@@ -90,10 +84,9 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
if (!((ToggleableClient) client).isListening()) continue;
|
||||
}
|
||||
|
||||
sent |= sendTo(client, event);
|
||||
sendTo(client, event);
|
||||
|
||||
// singular event ain't no whore, handled once only.
|
||||
if (sent && singular) return true;
|
||||
if (event.isConsumed()) return;
|
||||
|
||||
// pass on to delegated clients
|
||||
if (client instanceof DelegatingClient) {
|
||||
@@ -102,14 +95,12 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
final Collection<Object> children = ((DelegatingClient) client).getChildClients();
|
||||
|
||||
if (children != null && children.size() > 0) {
|
||||
sent |= doBroadcast(event, children, processed);
|
||||
doBroadcast(event, children, processed);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,16 +109,13 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
*
|
||||
* @param client target client
|
||||
* @param event event to send
|
||||
* @return success
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean sendTo(Object client, EVENT event)
|
||||
private void sendTo(Object client, EVENT event)
|
||||
{
|
||||
if (isClientOfType(client)) {
|
||||
((Event<CLIENT>) event).handleBy((CLIENT) client);
|
||||
return true;
|
||||
if (isClientOfChannelType(client)) {
|
||||
((BusEvent<CLIENT>) event).deliverTo((CLIENT) client);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +125,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
* @param event event object
|
||||
* @return can be broadcasted
|
||||
*/
|
||||
public boolean canBroadcast(Event<?> event)
|
||||
public boolean canBroadcast(BusEvent<?> event)
|
||||
{
|
||||
return event != null && eventClass.isInstance(event);
|
||||
}
|
||||
@@ -150,7 +138,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
* @param clientClass client class
|
||||
* @return the broadcaster
|
||||
*/
|
||||
public static <F_EVENT extends Event<F_CLIENT>, F_CLIENT> EventChannel<F_EVENT, F_CLIENT> create(Class<F_EVENT> eventClass, Class<F_CLIENT> clientClass)
|
||||
public static <F_EVENT extends BusEvent<F_CLIENT>, F_CLIENT> EventChannel<F_EVENT, F_CLIENT> create(Class<F_EVENT> eventClass, Class<F_CLIENT> clientClass)
|
||||
{
|
||||
return new EventChannel<>(eventClass, clientClass);
|
||||
}
|
||||
@@ -162,7 +150,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
* @param client client
|
||||
* @return is of type
|
||||
*/
|
||||
private boolean isClientOfType(Object client)
|
||||
private boolean isClientOfChannelType(Object client)
|
||||
{
|
||||
return clientClass.isInstance(client);
|
||||
}
|
||||
@@ -176,7 +164,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
*/
|
||||
public boolean isClientValid(Object client)
|
||||
{
|
||||
return isClientOfType(client) || (client instanceof DelegatingClient);
|
||||
return isClientOfChannelType(client) || (client instanceof DelegatingClient);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,21 +34,21 @@ public abstract class BusNode implements BusAccess, ClientHub {
|
||||
|
||||
|
||||
@Override
|
||||
public final Collection<Object> getChildClients()
|
||||
public Collection<Object> getChildClients()
|
||||
{
|
||||
return clients;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean doesDelegate()
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
return delegating;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isListening()
|
||||
public boolean isListening()
|
||||
{
|
||||
return listening;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public abstract class BusNode implements BusAccess, ClientHub {
|
||||
* @param client
|
||||
*/
|
||||
@Override
|
||||
public final void addChildClient(Object client)
|
||||
public void addChildClient(Object client)
|
||||
{
|
||||
if (client instanceof RootBusNode) {
|
||||
throw new IllegalArgumentException("Cannot nest RootBusNode.");
|
||||
@@ -76,7 +76,7 @@ public abstract class BusNode implements BusAccess, ClientHub {
|
||||
* @param client subscriber to remove
|
||||
*/
|
||||
@Override
|
||||
public final void removeChildClient(Object client)
|
||||
public void removeChildClient(Object client)
|
||||
{
|
||||
if (client != null) {
|
||||
clients.remove(client);
|
||||
@@ -89,7 +89,7 @@ public abstract class BusNode implements BusAccess, ClientHub {
|
||||
*
|
||||
* @param listening receive events
|
||||
*/
|
||||
public final void setListening(boolean listening)
|
||||
public void setListening(boolean listening)
|
||||
{
|
||||
this.listening = listening;
|
||||
}
|
||||
@@ -100,14 +100,14 @@ public abstract class BusNode implements BusAccess, ClientHub {
|
||||
*
|
||||
* @param delegating
|
||||
*/
|
||||
public final void setDelegating(boolean delegating)
|
||||
public void setDelegating(boolean delegating)
|
||||
{
|
||||
this.delegating = delegating;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final EventBus getEventBus()
|
||||
public EventBus getEventBus()
|
||||
{
|
||||
return busAccess.getEventBus();
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package mightypork.util.control.eventbus.events;
|
||||
|
||||
|
||||
import mightypork.util.control.eventbus.events.flags.DelayedEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
|
||||
import mightypork.util.control.eventbus.events.flags.UnloggedEvent;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Something that can be handled by HANDLER, subscribing to the event bus.
|
||||
* </p>
|
||||
* <p>
|
||||
* Can be annotated as {@link SingleReceiverEvent} to be delivered once only,
|
||||
* and {@link DelayedEvent} or {@link ImmediateEvent} to specify default sending
|
||||
* mode. When marked as {@link UnloggedEvent}, it will not appear in detailed
|
||||
* bus logging (useful for very frequent events, such as UpdateEvent).
|
||||
* </p>
|
||||
* <p>
|
||||
* Default sending mode (if not changed by annotations) is <i>queued</i> with
|
||||
* zero delay.
|
||||
* </p>
|
||||
*
|
||||
* @author MightyPork
|
||||
* @param <HANDLER> handler type
|
||||
*/
|
||||
public interface Event<HANDLER> {
|
||||
|
||||
/**
|
||||
* Ask handler to handle this message.
|
||||
*
|
||||
* @param handler handler instance
|
||||
*/
|
||||
public void handleBy(HANDLER handler);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package mightypork.util.control.eventbus.events.flags;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Event that cannot be consumed
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface NonConsumableEvent {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user