weirdly broken world renderer while triny to optimize

v5stable
ondra 11 years ago
parent 0860836f85
commit d67b382f43
  1. 2
      src/mightypork/gamecore/audio/SoundSystem.java
  2. 2
      src/mightypork/gamecore/control/BaseApp.java
  3. 6
      src/mightypork/gamecore/control/GameLoop.java
  4. 32
      src/mightypork/gamecore/control/events/LayoutChangeEvent.java
  5. 48
      src/mightypork/gamecore/control/events/MainLoopTaskRequest.java
  6. 49
      src/mightypork/gamecore/control/events/ResourceLoadRequest.java
  7. 47
      src/mightypork/gamecore/control/events/ScreenRequestEvent.java
  8. 8
      src/mightypork/gamecore/control/events/core/DestroyEvent.java
  9. 11
      src/mightypork/gamecore/control/events/core/UpdateEvent.java
  10. 28
      src/mightypork/gamecore/control/events/gui/LayoutChangeEvent.java
  11. 6
      src/mightypork/gamecore/control/events/gui/LayoutChangeListener.java
  12. 28
      src/mightypork/gamecore/control/events/gui/ViewportChangeEvent.java
  13. 16
      src/mightypork/gamecore/control/events/gui/ViewportChangeListener.java
  14. 27
      src/mightypork/gamecore/control/events/input/KeyEvent.java
  15. 16
      src/mightypork/gamecore/control/events/input/KeyListener.java
  16. 26
      src/mightypork/gamecore/control/events/input/MouseButtonEvent.java
  17. 16
      src/mightypork/gamecore/control/events/input/MouseButtonListener.java
  18. 26
      src/mightypork/gamecore/control/events/input/MouseMotionEvent.java
  19. 16
      src/mightypork/gamecore/control/events/input/MouseMotionListener.java
  20. 32
      src/mightypork/gamecore/control/events/requests/MainLoopRequest.java
  21. 16
      src/mightypork/gamecore/control/events/requests/MainLoopRequestListener.java
  22. 33
      src/mightypork/gamecore/control/events/requests/ResourceLoadRequest.java
  23. 18
      src/mightypork/gamecore/control/events/requests/ResourceLoadRequestListener.java
  24. 33
      src/mightypork/gamecore/control/events/requests/ScreenRequestEvent.java
  25. 14
      src/mightypork/gamecore/control/events/requests/ScreenRequestListener.java
  26. 6
      src/mightypork/gamecore/gui/components/ClickableComponent.java
  27. 5
      src/mightypork/gamecore/gui/components/VisualComponent.java
  28. 5
      src/mightypork/gamecore/gui/screens/BaseScreen.java
  29. 56
      src/mightypork/gamecore/gui/screens/LayeredScreen.java
  30. 35
      src/mightypork/gamecore/gui/screens/Overlay.java
  31. 9
      src/mightypork/gamecore/gui/screens/ScreenRegistry.java
  32. 6
      src/mightypork/gamecore/input/InputSystem.java
  33. 5
      src/mightypork/gamecore/input/KeyBinding.java
  34. 5
      src/mightypork/gamecore/input/KeyBindingPool.java
  35. 8
      src/mightypork/gamecore/loading/AsyncResourceLoader.java
  36. 2
      src/mightypork/gamecore/render/DisplaySystem.java
  37. 2
      src/mightypork/gamecore/render/fonts/FontBank.java
  38. 2
      src/mightypork/gamecore/render/textures/TextureBank.java
  39. 4
      src/mightypork/rogue/App.java
  40. 4
      src/mightypork/rogue/events/ActionRequest.java
  41. 4
      src/mightypork/rogue/screens/CrossfadeOverlay.java
  42. 4
      src/mightypork/rogue/screens/CrossfadeRequest.java
  43. 2
      src/mightypork/rogue/screens/FpsOverlay.java
  44. 8
      src/mightypork/rogue/screens/gamescreen/HudLayer.java
  45. 50
      src/mightypork/rogue/screens/gamescreen/ScreenGame.java
  46. 115
      src/mightypork/rogue/screens/gamescreen/WRBasicControls.java
  47. 55
      src/mightypork/rogue/screens/gamescreen/WorldLayer.java
  48. 44
      src/mightypork/rogue/screens/gamescreen/WorldRenderComponent.java
  49. 2
      src/mightypork/rogue/screens/gamescreen/gui/HeartBar.java
  50. 7
      src/mightypork/rogue/screens/gamescreen/gui/NavItemSlot.java
  51. 45
      src/mightypork/rogue/screens/gamescreen/world/MIPKeyWalk.java
  52. 59
      src/mightypork/rogue/screens/gamescreen/world/MIPMouseWalk.java
  53. 18
      src/mightypork/rogue/screens/gamescreen/world/MapInteractionPlugin.java
  54. 124
      src/mightypork/rogue/screens/gamescreen/world/MapView.java
  55. 2
      src/mightypork/rogue/screens/main_menu/MenuLayer.java
  56. 2
      src/mightypork/rogue/screens/test_bouncyboxes/LayerBouncyBoxes.java
  57. 2
      src/mightypork/rogue/screens/test_cat_sound/LayerColor.java
  58. 7
      src/mightypork/rogue/screens/test_cat_sound/LayerFlyingCat.java
  59. 2
      src/mightypork/rogue/screens/test_render/LayerTestGradient.java
  60. 34
      src/mightypork/rogue/world/PlayerControl.java
  61. 18
      src/mightypork/rogue/world/World.java
  62. 48
      src/mightypork/rogue/world/WorldRenderer.java
  63. 22
      src/mightypork/rogue/world/level/render/MapRenderContext.java
  64. 2
      src/mightypork/util/constraints/DigestCache.java
  65. 115
      src/mightypork/util/control/eventbus/BusEvent.java
  66. 54
      src/mightypork/util/control/eventbus/EventBus.java
  67. 42
      src/mightypork/util/control/eventbus/EventChannel.java
  68. 16
      src/mightypork/util/control/eventbus/clients/BusNode.java
  69. 36
      src/mightypork/util/control/eventbus/events/Event.java
  70. 20
      src/mightypork/util/control/eventbus/events/flags/NonConsumableEvent.java

@ -8,7 +8,7 @@ import java.util.Set;
import mightypork.gamecore.audio.players.EffectPlayer; import mightypork.gamecore.audio.players.EffectPlayer;
import mightypork.gamecore.audio.players.LoopPlayer; import mightypork.gamecore.audio.players.LoopPlayer;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.events.ResourceLoadRequest; import mightypork.gamecore.control.events.requests.ResourceLoadRequest;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;
import mightypork.util.constraints.vect.mutable.VectVar; import mightypork.util.constraints.vect.mutable.VectVar;
import mightypork.util.control.eventbus.clients.RootBusNode; import mightypork.util.control.eventbus.clients.RootBusNode;

@ -8,7 +8,7 @@ import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import mightypork.gamecore.audio.SoundSystem; import mightypork.gamecore.audio.SoundSystem;
import mightypork.gamecore.control.events.DestroyEvent; import mightypork.gamecore.control.events.core.DestroyEvent;
import mightypork.gamecore.gui.screens.ScreenRegistry; import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.render.DisplaySystem; import mightypork.gamecore.render.DisplaySystem;

@ -4,8 +4,8 @@ package mightypork.gamecore.control;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import mightypork.gamecore.control.events.MainLoopTaskRequest; import mightypork.gamecore.control.events.core.UpdateEvent;
import mightypork.gamecore.control.events.UpdateEvent; import mightypork.gamecore.control.events.requests.MainLoopRequestListener;
import mightypork.gamecore.gui.screens.ScreenRegistry; import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.render.Renderable; import mightypork.gamecore.render.Renderable;
import mightypork.util.annotations.DefaultImpl; import mightypork.util.annotations.DefaultImpl;
@ -17,7 +17,7 @@ import mightypork.util.control.timing.TimerDelta;
* *
* @author MightyPork * @author MightyPork
*/ */
public abstract class GameLoop extends AppModule implements MainLoopTaskRequest.Listener { public abstract class GameLoop extends AppModule implements MainLoopRequestListener {
private final Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<>(); private final Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<>();
private TimerDelta timer; private TimerDelta timer;

@ -1,32 +0,0 @@
package mightypork.gamecore.control.events;
import mightypork.util.control.eventbus.events.Event;
import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
/**
* Intended use is to notify UI component sub-clients that they should poll
* their cached constraints.
*
* @author MightyPork
*/
@ImmediateEvent
public class LayoutChangeEvent implements Event<LayoutChangeEvent.Listener> {
public LayoutChangeEvent()
{
}
@Override
public void handleBy(Listener handler)
{
handler.onLayoutChanged();
}
public interface Listener {
public void onLayoutChanged();
}
}

@ -1,48 +0,0 @@
package mightypork.gamecore.control.events;
import mightypork.util.control.eventbus.events.Event;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
/**
* Request to execute given {@link Runnable} in main loop.
*
* @author MightyPork
*/
@SingleReceiverEvent
public class MainLoopTaskRequest implements Event<MainLoopTaskRequest.Listener> {
private final Runnable task;
/**
* @param task task to run on main thread in rendering context
*/
public MainLoopTaskRequest(Runnable task)
{
this.task = task;
}
@Override
public void handleBy(Listener handler)
{
handler.queueTask(task);
}
/**
* {@link MainLoopTaskRequest} listener
*
* @author MightyPork
*/
public interface Listener {
/**
* Perform the requested action
*
* @param request
*/
void queueTask(Runnable request);
}
}

@ -1,49 +0,0 @@
package mightypork.gamecore.control.events;
import mightypork.gamecore.loading.Deferred;
import mightypork.util.control.eventbus.events.Event;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
/**
* Request to load a deferred resource.
*
* @author MightyPork
*/
@SingleReceiverEvent
public class ResourceLoadRequest implements Event<ResourceLoadRequest.Listener> {
private final Deferred resource;
/**
* @param resource resource to load
*/
public ResourceLoadRequest(Deferred resource)
{
this.resource = resource;
}
@Override
public void handleBy(Listener handler)
{
handler.loadResource(resource);
}
/**
* {@link ResourceLoadRequest} listener
*
* @author MightyPork
*/
public interface Listener {
/**
* Load a resource
*
* @param resource
*/
void loadResource(Deferred resource);
}
}

@ -1,47 +0,0 @@
package mightypork.gamecore.control.events;
import mightypork.util.control.eventbus.events.Event;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
/**
* Request to change screen
*
* @author MightyPork
*/
@SingleReceiverEvent
public class ScreenRequestEvent implements Event<ScreenRequestEvent.Listener> {
private final String scrName;
/**
* @param screenKey screen name
*/
public ScreenRequestEvent(String screenKey)
{
scrName = screenKey;
}
@Override
public void handleBy(Listener handler)
{
handler.showScreen(scrName);
}
/**
* {@link ScreenRequestEvent} listener
*
* @author MightyPork
*/
public interface Listener {
/**
* @param key screen to show
*/
void showScreen(String key);
}
}

@ -1,9 +1,10 @@
package mightypork.gamecore.control.events; package mightypork.gamecore.control.events.core;
import mightypork.util.control.Destroyable; import mightypork.util.control.Destroyable;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.ImmediateEvent; import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
import mightypork.util.control.eventbus.events.flags.NonConsumableEvent;
/** /**
@ -12,7 +13,8 @@ import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
* @author MightyPork * @author MightyPork
*/ */
@ImmediateEvent @ImmediateEvent
public class DestroyEvent implements Event<Destroyable> { @NonConsumableEvent
public class DestroyEvent extends BusEvent<Destroyable> {
@Override @Override
public void handleBy(Destroyable handler) public void handleBy(Destroyable handler)

@ -1,8 +1,9 @@
package mightypork.gamecore.control.events; package mightypork.gamecore.control.events.core;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.ImmediateEvent; import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
import mightypork.util.control.eventbus.events.flags.NonConsumableEvent;
import mightypork.util.control.eventbus.events.flags.UnloggedEvent; import mightypork.util.control.eventbus.events.flags.UnloggedEvent;
import mightypork.util.control.timing.Updateable; import mightypork.util.control.timing.Updateable;
@ -14,7 +15,8 @@ import mightypork.util.control.timing.Updateable;
*/ */
@UnloggedEvent @UnloggedEvent
@ImmediateEvent @ImmediateEvent
public class UpdateEvent implements Event<Updateable> { @NonConsumableEvent
public class UpdateEvent extends BusEvent<Updateable> {
private final double deltaTime; private final double deltaTime;
@ -22,8 +24,7 @@ public class UpdateEvent implements Event<Updateable> {
/** /**
* @param deltaTime time since last update (sec) * @param deltaTime time since last update (sec)
*/ */
public UpdateEvent(double deltaTime) public UpdateEvent(double deltaTime) {
{
this.deltaTime = deltaTime; this.deltaTime = deltaTime;
} }

@ -0,0 +1,28 @@
package mightypork.gamecore.control.events.gui;
import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
import mightypork.util.control.eventbus.events.flags.NonConsumableEvent;
/**
* Intended use is to notify UI component sub-clients that they should poll
* their cached constraints.
*
* @author MightyPork
*/
@ImmediateEvent
@NonConsumableEvent
public class LayoutChangeEvent extends BusEvent<LayoutChangeListener> {
public LayoutChangeEvent() {
}
@Override
public void handleBy(LayoutChangeListener handler)
{
handler.onLayoutChanged();
}
}

@ -0,0 +1,6 @@
package mightypork.gamecore.control.events.gui;
public interface LayoutChangeListener {
public void onLayoutChanged();
}

@ -1,8 +1,9 @@
package mightypork.gamecore.control.events; package mightypork.gamecore.control.events.gui;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.NonConsumableEvent;
/** /**
@ -10,7 +11,8 @@ import mightypork.util.control.eventbus.events.Event;
* *
* @author MightyPork * @author MightyPork
*/ */
public class ViewportChangeEvent implements Event<ViewportChangeEvent.Listener> { @NonConsumableEvent
public class ViewportChangeEvent extends BusEvent<ViewportChangeListener> {
private final boolean fullscreen; private final boolean fullscreen;
private final Vect screenSize; private final Vect screenSize;
@ -22,8 +24,7 @@ public class ViewportChangeEvent implements Event<ViewportChangeEvent.Listener>
* @param fullscreen is now fullscreen * @param fullscreen is now fullscreen
* @param size new screen size * @param size new screen size
*/ */
public ViewportChangeEvent(boolean fsChanged, boolean fullscreen, Vect size) public ViewportChangeEvent(boolean fsChanged, boolean fullscreen, Vect size) {
{
this.fullscreen = fullscreen; this.fullscreen = fullscreen;
this.screenSize = size; this.screenSize = size;
this.fsChanged = fsChanged; this.fsChanged = fsChanged;
@ -58,23 +59,8 @@ public class ViewportChangeEvent implements Event<ViewportChangeEvent.Listener>
@Override @Override
public void handleBy(Listener handler) public void handleBy(ViewportChangeListener handler)
{ {
handler.onViewportChanged(this); handler.onViewportChanged(this);
} }
/**
* {@link ViewportChangeEvent} listener
*
* @author MightyPork
*/
public interface Listener {
/**
* Handle event
*
* @param event
*/
void onViewportChanged(ViewportChangeEvent event);
}
} }

@ -0,0 +1,16 @@
package mightypork.gamecore.control.events.gui;
/**
* {@link ViewportChangeEvent} listener
*
* @author MightyPork
*/
public interface ViewportChangeListener {
/**
* Handle event
*
* @param event
*/
void onViewportChanged(ViewportChangeEvent event);
}

@ -1,7 +1,7 @@
package mightypork.gamecore.control.events; package mightypork.gamecore.control.events.input;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
@ -11,7 +11,7 @@ import org.lwjgl.input.Keyboard;
* *
* @author MightyPork * @author MightyPork
*/ */
public class KeyEvent implements Event<KeyEvent.Listener> { public class KeyEvent extends BusEvent<KeyListener> {
private final int key; private final int key;
private final boolean down; private final boolean down;
@ -23,8 +23,7 @@ public class KeyEvent implements Event<KeyEvent.Listener> {
* @param c typed char (can be zero char) * @param c typed char (can be zero char)
* @param down true = pressed, false = released. * @param down true = pressed, false = released.
*/ */
public KeyEvent(int key, char c, boolean down) public KeyEvent(int key, char c, boolean down) {
{
this.key = key; this.key = key;
this.c = c; this.c = c;
this.down = down; this.down = down;
@ -68,27 +67,11 @@ public class KeyEvent implements Event<KeyEvent.Listener> {
@Override @Override
public void handleBy(Listener keh) public void handleBy(KeyListener keh)
{ {
keh.receive(this); keh.receive(this);
} }
/**
* {@link KeyEvent} listener
*
* @author MightyPork
*/
public interface Listener {
/**
* Handle an event
*
* @param event event
*/
void receive(KeyEvent event);
}
@Override @Override
public String toString() public String toString()
{ {

@ -0,0 +1,16 @@
package mightypork.gamecore.control.events.input;
/**
* {@link KeyEvent} listener
*
* @author MightyPork
*/
public interface KeyListener {
/**
* Handle an event
*
* @param event event
*/
void receive(KeyEvent event);
}

@ -1,10 +1,10 @@
package mightypork.gamecore.control.events; package mightypork.gamecore.control.events.input;
import mightypork.util.constraints.rect.proxy.RectBound; import mightypork.util.constraints.rect.proxy.RectBound;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;
import mightypork.util.constraints.vect.VectConst; import mightypork.util.constraints.vect.VectConst;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
/** /**
@ -12,7 +12,7 @@ import mightypork.util.control.eventbus.events.Event;
* *
* @author MightyPork * @author MightyPork
*/ */
public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> { public class MouseButtonEvent extends BusEvent<MouseButtonListener> {
public static final int BUTTON_LEFT = 0; public static final int BUTTON_LEFT = 0;
public static final int BUTTON_MIDDLE = 1; public static final int BUTTON_MIDDLE = 1;
@ -32,8 +32,7 @@ public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
* @param down button pressed * @param down button pressed
* @param wheeld wheel change * @param wheeld wheel change
*/ */
public MouseButtonEvent(Vect pos, int button, boolean down, int wheeld) public MouseButtonEvent(Vect pos, int button, boolean down, int wheeld) {
{
this.button = button; this.button = button;
this.down = down; this.down = down;
this.pos = pos.freeze(); this.pos = pos.freeze();
@ -117,23 +116,8 @@ public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
@Override @Override
public void handleBy(Listener handler) public void handleBy(MouseButtonListener handler)
{ {
handler.receive(this); handler.receive(this);
} }
/**
* {@link MouseButtonEvent} listener
*
* @author MightyPork
*/
public interface Listener {
/**
* Handle an event
*
* @param event event
*/
void receive(MouseButtonEvent event);
}
} }

@ -0,0 +1,16 @@
package mightypork.gamecore.control.events.input;
/**
* {@link MouseButtonEvent} listener
*
* @author MightyPork
*/
public interface MouseButtonListener {
/**
* Handle an event
*
* @param event event
*/
void receive(MouseButtonEvent event);
}

@ -1,9 +1,9 @@
package mightypork.gamecore.control.events; package mightypork.gamecore.control.events.input;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;
import mightypork.util.constraints.vect.VectConst; import mightypork.util.constraints.vect.VectConst;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.UnloggedEvent; import mightypork.util.control.eventbus.events.flags.UnloggedEvent;
@ -13,7 +13,7 @@ import mightypork.util.control.eventbus.events.flags.UnloggedEvent;
* @author MightyPork * @author MightyPork
*/ */
@UnloggedEvent @UnloggedEvent
public class MouseMotionEvent implements Event<MouseMotionEvent.Listener> { public class MouseMotionEvent extends BusEvent<MouseMotionListener> {
private final VectConst move; private final VectConst move;
private final VectConst pos; private final VectConst pos;
@ -23,8 +23,7 @@ public class MouseMotionEvent implements Event<MouseMotionEvent.Listener> {
* @param pos end pos * @param pos end pos
* @param move move vector * @param move move vector
*/ */
public MouseMotionEvent(Vect pos, Vect move) public MouseMotionEvent(Vect pos, Vect move) {
{
this.move = move.freeze(); this.move = move.freeze();
this.pos = pos.freeze(); this.pos = pos.freeze();
} }
@ -49,24 +48,9 @@ public class MouseMotionEvent implements Event<MouseMotionEvent.Listener> {
@Override @Override
public void handleBy(Listener keh) public void handleBy(MouseMotionListener keh)
{ {
keh.receive(this); keh.receive(this);
} }
/**
* {@link MouseMotionEvent} listener
*
* @author MightyPork
*/
public interface Listener {
/**
* Handle an event
*
* @param event event
*/
void receive(MouseMotionEvent event);
}
} }

@ -0,0 +1,16 @@
package mightypork.gamecore.control.events.input;
/**
* {@link MouseMotionEvent} listener
*
* @author MightyPork
*/
public interface MouseMotionListener {
/**
* Handle an event
*
* @param event event
*/
void receive(MouseMotionEvent event);
}

@ -0,0 +1,32 @@
package mightypork.gamecore.control.events.requests;
import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
/**
* Request to execute given {@link Runnable} in main loop.
*
* @author MightyPork
*/
@SingleReceiverEvent
public class MainLoopRequest extends BusEvent<MainLoopRequestListener> {
private final Runnable task;
/**
* @param task task to run on main thread in rendering context
*/
public MainLoopRequest(Runnable task) {
this.task = task;
}
@Override
public void handleBy(MainLoopRequestListener handler)
{
handler.queueTask(task);
}
}

@ -0,0 +1,16 @@
package mightypork.gamecore.control.events.requests;
/**
* {@link MainLoopRequest} listener
*
* @author MightyPork
*/
public interface MainLoopRequestListener {
/**
* Perform the requested action
*
* @param request
*/
void queueTask(Runnable request);
}

@ -0,0 +1,33 @@
package mightypork.gamecore.control.events.requests;
import mightypork.gamecore.loading.Deferred;
import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
/**
* Request to load a deferred resource.
*
* @author MightyPork
*/
@SingleReceiverEvent
public class ResourceLoadRequest extends BusEvent<ResourceLoadRequestListener> {
private final Deferred resource;
/**
* @param resource resource to load
*/
public ResourceLoadRequest(Deferred resource) {
this.resource = resource;
}
@Override
public void handleBy(ResourceLoadRequestListener handler)
{
handler.loadResource(resource);
}
}

@ -0,0 +1,18 @@
package mightypork.gamecore.control.events.requests;
import mightypork.gamecore.loading.Deferred;
/**
* {@link ResourceLoadRequest} listener
*
* @author MightyPork
*/
public interface ResourceLoadRequestListener {
/**
* Load a resource
*
* @param resource
*/
void loadResource(Deferred resource);
}

@ -0,0 +1,33 @@
package mightypork.gamecore.control.events.requests;
import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
/**
* Request to change screen
*
* @author MightyPork
*/
@SingleReceiverEvent
public class ScreenRequestEvent extends BusEvent<ScreenRequestListener> {
private final String scrName;
/**
* @param screenKey screen name
*/
public ScreenRequestEvent(String screenKey) {
scrName = screenKey;
}
@Override
public void handleBy(ScreenRequestListener handler)
{
handler.showScreen(scrName);
}
}

@ -0,0 +1,14 @@
package mightypork.gamecore.control.events.requests;
/**
* {@link ScreenRequestEvent} listener
*
* @author MightyPork
*/
public interface ScreenRequestListener {
/**
* @param key screen to show
*/
void showScreen(String key);
}

@ -1,12 +1,13 @@
package mightypork.gamecore.gui.components; package mightypork.gamecore.gui.components;
import mightypork.gamecore.control.events.MouseButtonEvent; import mightypork.gamecore.control.events.input.MouseButtonEvent;
import mightypork.gamecore.control.events.input.MouseButtonListener;
import mightypork.util.control.Action; import mightypork.util.control.Action;
import mightypork.util.control.ActionTrigger; import mightypork.util.control.ActionTrigger;
public abstract class ClickableComponent extends InputComponent implements ActionTrigger, MouseButtonEvent.Listener { public abstract class ClickableComponent extends InputComponent implements ActionTrigger, MouseButtonListener {
private boolean btnDownOver; private boolean btnDownOver;
private Action action; private Action action;
@ -38,6 +39,7 @@ public abstract class ClickableComponent extends InputComponent implements Actio
if (btnDownOver && event.isOver(this)) { if (btnDownOver && event.isOver(this)) {
triggerAction(); triggerAction();
event.consume();
} }
btnDownOver = false; btnDownOver = false;

@ -1,7 +1,8 @@
package mightypork.gamecore.gui.components; package mightypork.gamecore.gui.components;
import mightypork.gamecore.control.events.LayoutChangeEvent; import mightypork.gamecore.control.events.gui.LayoutChangeEvent;
import mightypork.gamecore.control.events.gui.LayoutChangeListener;
import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.render.Renderable; import mightypork.gamecore.render.Renderable;
import mightypork.util.annotations.DefaultImpl; import mightypork.util.annotations.DefaultImpl;
@ -17,7 +18,7 @@ import mightypork.util.constraints.rect.proxy.RectBoundAdapter;
* *
* @author MightyPork * @author MightyPork
*/ */
public abstract class VisualComponent extends AbstractRectCache implements Component, LayoutChangeEvent.Listener { public abstract class VisualComponent extends AbstractRectCache implements Component, LayoutChangeListener {
private Rect source; private Rect source;
private boolean visible = true; private boolean visible = true;

@ -3,7 +3,8 @@ package mightypork.gamecore.gui.screens;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppSubModule; import mightypork.gamecore.control.AppSubModule;
import mightypork.gamecore.control.events.LayoutChangeEvent; import mightypork.gamecore.control.events.gui.LayoutChangeEvent;
import mightypork.gamecore.control.events.gui.LayoutChangeListener;
import mightypork.gamecore.input.KeyBinder; import mightypork.gamecore.input.KeyBinder;
import mightypork.gamecore.input.KeyBindingPool; import mightypork.gamecore.input.KeyBindingPool;
import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.KeyStroke;
@ -17,7 +18,7 @@ import mightypork.util.constraints.rect.Rect;
* *
* @author MightyPork * @author MightyPork
*/ */
public abstract class BaseScreen extends AppSubModule implements Screen, KeyBinder, LayoutChangeEvent.Listener { public abstract class BaseScreen extends AppSubModule implements Screen, KeyBinder, LayoutChangeListener {
private final KeyBindingPool keybindings = new KeyBindingPool(); private final KeyBindingPool keybindings = new KeyBindingPool();

@ -2,9 +2,12 @@ package mightypork.gamecore.gui.screens;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator;
import java.util.TreeSet; import java.util.TreeSet;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.util.control.eventbus.clients.DelegatingClient;
import mightypork.util.control.eventbus.clients.RootBusNode;
/** /**
@ -14,22 +17,59 @@ import mightypork.gamecore.control.AppAccess;
*/ */
public abstract class LayeredScreen extends BaseScreen { public abstract class LayeredScreen extends BaseScreen {
private final Collection<ScreenLayer> layers = new TreeSet<>(); private class LayersClient implements DelegatingClient {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Collection getChildClients()
{
return layersByEventPriority;
}
@Override
public boolean doesDelegate()
{
return true;
}
}
private final Collection<ScreenLayer> layersByZIndex = new TreeSet<>(new Comparator<Overlay>() {
@Override
public int compare(Overlay o1, Overlay o2)
{
return o1.getZIndex() - o2.getZIndex();
}
});
private final Collection<ScreenLayer> layersByEventPriority = new TreeSet<>(new Comparator<Overlay>() {
@Override
public int compare(Overlay o1, Overlay o2)
{
return o2.getEventPriority() - o1.getEventPriority();
}
});
private final LayersClient layersClient = new LayersClient();
/** /**
* @param app app access * @param app app access
*/ */
public LayeredScreen(AppAccess app) public LayeredScreen(AppAccess app) {
{
super(app); super(app);
addChildClient(layersClient);
} }
@Override @Override
protected void renderScreen() protected void renderScreen()
{ {
for (final ScreenLayer layer : layers) { for (final ScreenLayer layer : layersByZIndex) {
if (layer.isVisible()) layer.render(); if (layer.isVisible()) layer.render();
} }
} }
@ -42,15 +82,15 @@ public abstract class LayeredScreen extends BaseScreen {
*/ */
protected void addLayer(ScreenLayer layer) protected void addLayer(ScreenLayer layer)
{ {
this.layers.add(layer); this.layersByZIndex.add(layer);
addChildClient(layer); this.layersByEventPriority.add(layer);
} }
@Override @Override
protected void onScreenEnter() protected void onScreenEnter()
{ {
for (final ScreenLayer layer : layers) { for (final ScreenLayer layer : layersByEventPriority) {
layer.onScreenEnter(); layer.onScreenEnter();
} }
} }
@ -59,7 +99,7 @@ public abstract class LayeredScreen extends BaseScreen {
@Override @Override
protected void onScreenLeave() protected void onScreenLeave()
{ {
for (final ScreenLayer layer : layers) { for (final ScreenLayer layer : layersByEventPriority) {
layer.onScreenLeave(); layer.onScreenLeave();
} }
} }

@ -6,7 +6,7 @@ import java.util.LinkedHashSet;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppSubModule; import mightypork.gamecore.control.AppSubModule;
import mightypork.gamecore.control.events.LayoutChangeEvent; import mightypork.gamecore.control.events.gui.LayoutChangeListener;
import mightypork.gamecore.gui.Hideable; import mightypork.gamecore.gui.Hideable;
import mightypork.gamecore.gui.components.layout.ConstraintLayout; import mightypork.gamecore.gui.components.layout.ConstraintLayout;
import mightypork.gamecore.input.KeyBinder; import mightypork.gamecore.input.KeyBinder;
@ -24,7 +24,7 @@ import mightypork.util.control.timing.Updateable;
* *
* @author MightyPork * @author MightyPork
*/ */
public abstract class Overlay extends AppSubModule implements Updateable, Comparable<Overlay>, Renderable, KeyBinder, Hideable, LayoutChangeEvent.Listener { public abstract class Overlay extends AppSubModule implements Comparable<Overlay>, Updateable, Renderable, KeyBinder, Hideable, LayoutChangeListener {
private boolean visible = true; private boolean visible = true;
private final KeyBindingPool keybindings = new KeyBindingPool(); private final KeyBindingPool keybindings = new KeyBindingPool();
@ -42,8 +42,7 @@ public abstract class Overlay extends AppSubModule implements Updateable, Compar
protected final Collection<Updateable> updated = new LinkedHashSet<>(); protected final Collection<Updateable> updated = new LinkedHashSet<>();
public Overlay(AppAccess app) public Overlay(AppAccess app) {
{
super(app); super(app);
this.mouse = getInput().getMousePos(); this.mouse = getInput().getMousePos();
@ -84,20 +83,24 @@ public abstract class Overlay extends AppSubModule implements Updateable, Compar
} }
@Override
public final int compareTo(Overlay o)
{
return getPriority() - o.getPriority();
}
/** /**
* Get rendering priority * Get rendering layer
* *
* @return higher = on top. * @return higher = on top.
*/ */
@DefaultImpl @DefaultImpl
public abstract int getPriority(); public abstract int getZIndex();
/**
* Get event bus listening priority - useful to block incoming events.
*
* @return higher = first.
*/
public int getEventPriority()
{
return getZIndex();
}
/** /**
@ -120,6 +123,12 @@ public abstract class Overlay extends AppSubModule implements Updateable, Compar
} }
} }
@Override
public int compareTo(Overlay o)
{
return o.getEventPriority() - getEventPriority();
}
/** /**
* <p> * <p>

@ -8,9 +8,10 @@ import java.util.TreeSet;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppModule; import mightypork.gamecore.control.AppModule;
import mightypork.gamecore.control.events.LayoutChangeEvent; import mightypork.gamecore.control.events.gui.LayoutChangeEvent;
import mightypork.gamecore.control.events.ScreenRequestEvent; import mightypork.gamecore.control.events.gui.ViewportChangeEvent;
import mightypork.gamecore.control.events.ViewportChangeEvent; import mightypork.gamecore.control.events.gui.ViewportChangeListener;
import mightypork.gamecore.control.events.requests.ScreenRequestListener;
import mightypork.gamecore.render.Renderable; import mightypork.gamecore.render.Renderable;
import mightypork.util.annotations.DefaultImpl; import mightypork.util.annotations.DefaultImpl;
import mightypork.util.logging.Log; import mightypork.util.logging.Log;
@ -21,7 +22,7 @@ import mightypork.util.logging.Log;
* *
* @author MightyPork * @author MightyPork
*/ */
public class ScreenRegistry extends AppModule implements ScreenRequestEvent.Listener, ViewportChangeEvent.Listener, Renderable { public class ScreenRegistry extends AppModule implements ScreenRequestListener, ViewportChangeListener, Renderable {
private final Map<String, Screen> screens = new HashMap<>(); private final Map<String, Screen> screens = new HashMap<>();
private final Collection<Overlay> overlays = new TreeSet<>(); private final Collection<Overlay> overlays = new TreeSet<>();

@ -2,9 +2,9 @@ package mightypork.gamecore.input;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.events.KeyEvent; import mightypork.gamecore.control.events.input.KeyEvent;
import mightypork.gamecore.control.events.MouseButtonEvent; import mightypork.gamecore.control.events.input.MouseButtonEvent;
import mightypork.gamecore.control.events.MouseMotionEvent; import mightypork.gamecore.control.events.input.MouseMotionEvent;
import mightypork.rogue.events.ActionRequest; import mightypork.rogue.events.ActionRequest;
import mightypork.rogue.events.ActionRequest.RequestType; import mightypork.rogue.events.ActionRequest.RequestType;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;

@ -1,7 +1,8 @@
package mightypork.gamecore.input; package mightypork.gamecore.input;
import mightypork.gamecore.control.events.KeyEvent; import mightypork.gamecore.control.events.input.KeyEvent;
import mightypork.gamecore.control.events.input.KeyListener;
/** /**
@ -9,7 +10,7 @@ import mightypork.gamecore.control.events.KeyEvent;
* *
* @author MightyPork * @author MightyPork
*/ */
public class KeyBinding implements KeyEvent.Listener { public class KeyBinding implements KeyListener {
private final KeyStroke keystroke; private final KeyStroke keystroke;
private Runnable handler; private Runnable handler;

@ -5,7 +5,8 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import mightypork.gamecore.control.events.KeyEvent; import mightypork.gamecore.control.events.input.KeyEvent;
import mightypork.gamecore.control.events.input.KeyListener;
import mightypork.util.logging.Log; import mightypork.util.logging.Log;
@ -14,7 +15,7 @@ import mightypork.util.logging.Log;
* *
* @author MightyPork * @author MightyPork
*/ */
public class KeyBindingPool implements KeyBinder, KeyEvent.Listener { public class KeyBindingPool implements KeyBinder, KeyListener {
private final Set<KeyBinding> bindings = new HashSet<>(); private final Set<KeyBinding> bindings = new HashSet<>();

@ -5,8 +5,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import mightypork.gamecore.control.events.MainLoopTaskRequest; import mightypork.gamecore.control.events.requests.MainLoopRequest;
import mightypork.gamecore.control.events.ResourceLoadRequest; import mightypork.gamecore.control.events.requests.ResourceLoadRequestListener;
import mightypork.util.annotations.FactoryMethod; import mightypork.util.annotations.FactoryMethod;
import mightypork.util.control.Destroyable; import mightypork.util.control.Destroyable;
import mightypork.util.control.eventbus.BusAccess; import mightypork.util.control.eventbus.BusAccess;
@ -18,7 +18,7 @@ import mightypork.util.logging.Log;
* *
* @author MightyPork * @author MightyPork
*/ */
public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.Listener, Destroyable { public class AsyncResourceLoader extends Thread implements ResourceLoadRequestListener, Destroyable {
/** /**
* Start a new loader thread. * Start a new loader thread.
@ -73,7 +73,7 @@ public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.L
} else { } else {
Log.f3("<LOADER> Delegating to main thread:\n " + Log.str(resource)); Log.f3("<LOADER> Delegating to main thread:\n " + Log.str(resource));
app.getEventBus().send(new MainLoopTaskRequest(new Runnable() { app.getEventBus().send(new MainLoopRequest(new Runnable() {
@Override @Override
public void run() public void run()

@ -7,7 +7,7 @@ import java.nio.ByteBuffer;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppModule; import mightypork.gamecore.control.AppModule;
import mightypork.gamecore.control.events.ViewportChangeEvent; import mightypork.gamecore.control.events.gui.ViewportChangeEvent;
import mightypork.util.constraints.rect.Rect; import mightypork.util.constraints.rect.Rect;
import mightypork.util.constraints.rect.proxy.RectBound; import mightypork.util.constraints.rect.proxy.RectBound;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;

@ -5,7 +5,7 @@ import java.util.HashMap;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppAdapter; import mightypork.gamecore.control.AppAdapter;
import mightypork.gamecore.control.events.ResourceLoadRequest; import mightypork.gamecore.control.events.requests.ResourceLoadRequest;
import mightypork.gamecore.render.fonts.impl.DeferredFont; import mightypork.gamecore.render.fonts.impl.DeferredFont;
import org.newdawn.slick.opengl.Texture; import org.newdawn.slick.opengl.Texture;

@ -6,7 +6,7 @@ import java.util.Map;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppAdapter; import mightypork.gamecore.control.AppAdapter;
import mightypork.gamecore.control.events.ResourceLoadRequest; import mightypork.gamecore.control.events.requests.ResourceLoadRequest;
import mightypork.util.constraints.rect.Rect; import mightypork.util.constraints.rect.Rect;
import mightypork.util.error.KeyAlreadyExistsException; import mightypork.util.error.KeyAlreadyExistsException;

@ -26,8 +26,8 @@ import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.item.Item; import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.level.Level; import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.Tile;
import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.EventBus; import mightypork.util.control.eventbus.EventBus;
import mightypork.util.control.eventbus.events.Event;
import mightypork.util.ion.Ion; import mightypork.util.ion.Ion;
import mightypork.util.logging.Log; import mightypork.util.logging.Log;
import mightypork.util.logging.writers.LogWriter; import mightypork.util.logging.writers.LogWriter;
@ -139,7 +139,7 @@ public final class App extends BaseApp {
} }
private void bindToKey(final Event<?> event, int... keys) private void bindToKey(final BusEvent<?> event, int... keys)
{ {
getInput().bindKey(new KeyStroke(keys), new Runnable() { getInput().bindKey(new KeyStroke(keys), new Runnable() {

@ -1,7 +1,7 @@
package mightypork.rogue.events; package mightypork.rogue.events;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent; import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
@ -11,7 +11,7 @@ import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
* @author MightyPork * @author MightyPork
*/ */
@SingleReceiverEvent @SingleReceiverEvent
public class ActionRequest implements Event<ActionRequest.Listener> { public class ActionRequest extends BusEvent<ActionRequest.Listener> {
private final RequestType type; private final RequestType type;

@ -2,7 +2,7 @@ package mightypork.rogue.screens;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.events.ScreenRequestEvent; import mightypork.gamecore.control.events.requests.ScreenRequestEvent;
import mightypork.gamecore.gui.components.painters.QuadPainter; import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.screens.Overlay; import mightypork.gamecore.gui.screens.Overlay;
import mightypork.rogue.events.ActionRequest; import mightypork.rogue.events.ActionRequest;
@ -62,7 +62,7 @@ public class CrossfadeOverlay extends Overlay implements CrossfadeRequest.Listen
@Override @Override
public int getPriority() public int getZIndex()
{ {
return Integer.MAX_VALUE - 1; // let FPS go on top return Integer.MAX_VALUE - 1; // let FPS go on top
} }

@ -1,13 +1,13 @@
package mightypork.rogue.screens; package mightypork.rogue.screens;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.BusEvent;
/** /**
* @author MightyPork * @author MightyPork
*/ */
public class CrossfadeRequest implements Event<CrossfadeRequest.Listener> { public class CrossfadeRequest extends BusEvent<CrossfadeRequest.Listener> {
private final String screen; private final String screen;

@ -60,7 +60,7 @@ public class FpsOverlay extends Overlay {
@Override @Override
public int getPriority() public int getZIndex()
{ {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} }

@ -7,13 +7,15 @@ import mightypork.gamecore.gui.components.painters.ImagePainter;
import mightypork.gamecore.gui.screens.Screen; import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer; import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.rogue.Res; import mightypork.rogue.Res;
import mightypork.rogue.screens.gamescreen.gui.HeartBar;
import mightypork.rogue.screens.gamescreen.gui.NavItemSlot;
import mightypork.util.constraints.num.Num; import mightypork.util.constraints.num.Num;
import mightypork.util.constraints.rect.Rect; import mightypork.util.constraints.rect.Rect;
public class GameGui extends ScreenLayer { public class HudLayer extends ScreenLayer {
public GameGui(Screen screen) public HudLayer(Screen screen)
{ {
super(screen); super(screen);
@ -48,7 +50,7 @@ public class GameGui extends ScreenLayer {
@Override @Override
public int getPriority() public int getZIndex()
{ {
return 100; return 100;
} }

@ -1,18 +1,60 @@
package mightypork.rogue.screens.gamescreen; package mightypork.rogue.screens.gamescreen;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.rogue.Paths;
import mightypork.rogue.world.MapGenerator;
import mightypork.rogue.world.World;
import mightypork.util.ion.Ion;
public class ScreenGame extends LayeredScreen { public class ScreenGame extends LayeredScreen {
public ScreenGame(AppAccess app) public ScreenGame(AppAccess app) {
{
super(app); super(app);
addLayer(new WorldLayer(this)); //TODO with provided world addLayer(new WorldLayer(this, obtainWorld())); //TODO with provided world
addLayer(new GameGui(this)); addLayer(new HudLayer(this));
}
private World obtainWorld()
{
// FIXME just temporary test here
final Random rand = new Random();
final File f = new File(Paths.WORKDIR, "test-world.ion");
// SAVE
World world = MapGenerator.createWorld(rand.nextLong());
addChildClient(world);
try {
Ion.toFile(f, world);
} catch (final IOException e) {
e.printStackTrace();
}
// LOAD
// final World w;
//
// try {
// world = Ion.fromFile(f, World.class);
// } catch (IOException e) {
// e.printStackTrace();
// System.exit(1);
// return;
// }
return world;
} }

@ -1,115 +0,0 @@
package mightypork.rogue.screens.gamescreen;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.World;
import mightypork.rogue.world.WorldPos;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.models.EntityMoveListener;
import mightypork.rogue.world.level.Level;
import mightypork.util.constraints.vect.Vect;
import mightypork.util.math.Polar;
import mightypork.util.math.Calc.Deg;
import mightypork.gamecore.control.events.KeyEvent;
import mightypork.gamecore.control.events.MouseButtonEvent;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.Keys;
public class WRBasicControls extends WorldRenderComponent implements KeyEvent.Listener, MouseButtonEvent.Listener, EntityMoveListener {
private final PlayerControl pc;
public WRBasicControls(World world) {
super(world);
pc = world.getPlayerControl();
pc.addMoveListener(this);
}
private void handleHeldKey()
{
if (InputSystem.isKeyDown(Keys.LEFT)) {
pc.walkWest();
} else if (InputSystem.isKeyDown(Keys.RIGHT)) {
pc.walkEast();
} else if (InputSystem.isKeyDown(Keys.UP)) {
pc.walkNorth();
} else if (InputSystem.isKeyDown(Keys.DOWN)) {
pc.walkSouth();
}
if(InputSystem.isMouseButtonDown(0)) {
walkByMouse(InputSystem.getMousePos());
}
}
@Override
public void onStepFinished(Entity entity, World world, Level level)
{
handleHeldKey();
}
@Override
public void onPathFinished(Entity entity, World world, Level level)
{
handleHeldKey();
}
@Override
public void onPathInterrupted(Entity entity, World world, Level level)
{
handleHeldKey();
}
@Override
public void receive(MouseButtonEvent event)
{
if (!event.isDown()) return;
walkByMouse(event.getPos());
}
private void walkByMouse(Vect mouse)
{
WorldPos clicked = toWorldPos(mouse);
WorldPos plpos = pc.getPos();
Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y);
int dir = Deg.round90(p.getAngleDeg()) / 90;
switch (dir) {
case 0:
pc.walkEast();
return;
case 1:
pc.walkSouth();
return;
case 2:
pc.walkWest();
return;
case 3:
pc.walkNorth();
return;
}
}
@Override
public void receive(KeyEvent event)
{
handleHeldKey();
}
}

@ -1,64 +1,31 @@
package mightypork.rogue.screens.gamescreen; package mightypork.rogue.screens.gamescreen;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import mightypork.gamecore.gui.components.InputComponent;
import mightypork.gamecore.gui.screens.Screen; import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer; import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.rogue.Paths; import mightypork.rogue.screens.gamescreen.world.MIPKeyWalk;
import mightypork.rogue.world.MapGenerator; import mightypork.rogue.screens.gamescreen.world.MIPMouseWalk;
import mightypork.rogue.screens.gamescreen.world.MapView;
import mightypork.rogue.world.World; import mightypork.rogue.world.World;
import mightypork.util.constraints.num.Num; import mightypork.util.constraints.num.Num;
import mightypork.util.ion.Ion;
public class WorldLayer extends ScreenLayer { public class WorldLayer extends ScreenLayer {
private World world; private MapView worldView;
private InputComponent worldView;
public WorldLayer(Screen screen) { public WorldLayer(Screen screen, World world) {
super(screen); super(screen);
// FIXME just temporary test here // render component
final Random rand = new Random();
final File f = new File(Paths.WORKDIR, "test-world.ion");
// SAVE
world = MapGenerator.createWorld(rand.nextLong());
updated.add(world);
try {
Ion.toFile(f, world);
} catch (final IOException e) {
e.printStackTrace();
System.exit(1); // fail
return;
}
// LOAD
// final World w;
//
// try {
// world = Ion.fromFile(f, World.class);
// } catch (IOException e) {
// e.printStackTrace();
// System.exit(1);
// return;
// }
worldView = new MapView(world);
// render component // map input plugins
worldView.addPlugin(new MIPKeyWalk());
worldView.addPlugin(new MIPMouseWalk());
worldView = new WRBasicControls(world);
// size of lower navbar // size of lower navbar
final Num lownav = root.width().min(root.height()).max(700).perc(7); final Num lownav = root.width().min(root.height()).max(700).perc(7);
@ -69,7 +36,7 @@ public class WorldLayer extends ScreenLayer {
@Override @Override
public int getPriority() public int getZIndex()
{ {
return -1; // stay down return -1; // stay down
} }

@ -1,44 +0,0 @@
package mightypork.rogue.screens.gamescreen;
import mightypork.gamecore.gui.components.InputComponent;
import mightypork.rogue.world.World;
import mightypork.rogue.world.WorldPos;
import mightypork.rogue.world.WorldRenderer;
import mightypork.util.constraints.vect.Vect;
public class WorldRenderComponent extends InputComponent {
protected final WorldRenderer worldRenderer;
protected final World world;
public WorldRenderComponent(World world) {
this.world = world;
this.worldRenderer = new WorldRenderer(world, this, 8, 6, 72);
}
@Override
protected void renderComponent()
{
worldRenderer.render();
}
@Override
public void updateLayout()
{
worldRenderer.poll(); // update sizing
}
/**
* Get tile coord at a screen position
*/
public WorldPos toWorldPos(Vect pos)
{
return worldRenderer.getClickedTile(pos);
}
}

@ -1,4 +1,4 @@
package mightypork.rogue.screens.gamescreen; package mightypork.rogue.screens.gamescreen.gui;
import mightypork.gamecore.gui.AlignX; import mightypork.gamecore.gui.AlignX;

@ -1,7 +1,8 @@
package mightypork.rogue.screens.gamescreen; package mightypork.rogue.screens.gamescreen.gui;
import mightypork.gamecore.control.events.MouseMotionEvent; import mightypork.gamecore.control.events.input.MouseMotionEvent;
import mightypork.gamecore.control.events.input.MouseMotionListener;
import mightypork.gamecore.gui.components.ClickableComponent; import mightypork.gamecore.gui.components.ClickableComponent;
import mightypork.gamecore.render.Render; import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.TxQuad; import mightypork.gamecore.render.textures.TxQuad;
@ -15,7 +16,7 @@ import mightypork.util.control.timing.Updateable;
import mightypork.util.math.Easing; import mightypork.util.math.Easing;
public class NavItemSlot extends ClickableComponent implements MouseMotionEvent.Listener, Updateable { public class NavItemSlot extends ClickableComponent implements MouseMotionListener, Updateable {
private final TxQuad image; private final TxQuad image;
private final TxQuad frame; private final TxQuad frame;

@ -0,0 +1,45 @@
package mightypork.rogue.screens.gamescreen.world;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.Keys;
import mightypork.rogue.world.PlayerControl;
import mightypork.util.constraints.vect.Vect;
public class MIPKeyWalk implements MapInteractionPlugin {
@Override
public void onStepEnd(MapView wv, PlayerControl player)
{
walkByKey(player);
}
@Override
public void onClick(MapView wv, PlayerControl player, Vect mouse)
{
}
@Override
public void onKey(MapView wv, PlayerControl player, int key)
{
walkByKey(player);
}
private void walkByKey(PlayerControl player)
{
if (InputSystem.isKeyDown(Keys.LEFT)) {
player.goWest();
} else if (InputSystem.isKeyDown(Keys.RIGHT)) {
player.goEast();
} else if (InputSystem.isKeyDown(Keys.UP)) {
player.goNorth();
} else if (InputSystem.isKeyDown(Keys.DOWN)) {
player.goSouth();
}
}
}

@ -0,0 +1,59 @@
package mightypork.rogue.screens.gamescreen.world;
import mightypork.gamecore.input.InputSystem;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.WorldPos;
import mightypork.util.constraints.vect.Vect;
import mightypork.util.math.Polar;
import mightypork.util.math.Calc.Deg;
public class MIPMouseWalk implements MapInteractionPlugin {
@Override
public void onStepEnd(MapView wv, PlayerControl player)
{
if (InputSystem.isMouseButtonDown(0)) {
// walk by holding btn
onClick(wv, player, InputSystem.getMousePos());
}
}
@Override
public void onClick(MapView wv, PlayerControl player, Vect mouse)
{
WorldPos plpos = player.getPos();
WorldPos clicked = wv.toWorldPos(mouse);
Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y);
int dir = Deg.round90(p.getAngleDeg()) / 90;
switch (dir) {
case 0:
player.goEast();
return;
case 1:
player.goSouth();
return;
case 2:
player.goWest();
return;
case 3:
player.goNorth();
return;
}
}
@Override
public void onKey(MapView wv, PlayerControl player, int key)
{
}
}

@ -0,0 +1,18 @@
package mightypork.rogue.screens.gamescreen.world;
import mightypork.rogue.world.PlayerControl;
import mightypork.util.constraints.vect.Vect;
public interface MapInteractionPlugin {
void onStepEnd(MapView wv, PlayerControl player);
void onClick(MapView wv, PlayerControl player, Vect mouse);
void onKey(MapView wv, PlayerControl player, int key);
}

@ -0,0 +1,124 @@
package mightypork.rogue.screens.gamescreen.world;
import java.util.HashSet;
import java.util.Set;
import mightypork.gamecore.control.events.input.KeyEvent;
import mightypork.gamecore.control.events.input.KeyListener;
import mightypork.gamecore.control.events.input.MouseButtonEvent;
import mightypork.gamecore.control.events.input.MouseButtonListener;
import mightypork.gamecore.gui.components.InputComponent;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.World;
import mightypork.rogue.world.WorldPos;
import mightypork.rogue.world.WorldRenderer;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.models.EntityMoveListener;
import mightypork.rogue.world.level.Level;
import mightypork.util.constraints.vect.Vect;
public class MapView extends InputComponent implements KeyListener, MouseButtonListener, EntityMoveListener {
protected final WorldRenderer worldRenderer;
protected final World world;
private final PlayerControl pc;
private final Set<MapInteractionPlugin> plugins = new HashSet<>();
public MapView(World world) {
this.world = world;
this.worldRenderer = new WorldRenderer(world, this, 8, 6, 72);
pc = world.getPlayerControl();
pc.addMoveListener(this);
}
@Override
protected void renderComponent()
{
worldRenderer.render();
}
@Override
public void updateLayout()
{
worldRenderer.poll(); // update sizing
}
/**
* Get tile coord at a screen position
*
* @param pos position on screen (px)
* @return position on map (tiles)
*/
public WorldPos toWorldPos(Vect pos)
{
return worldRenderer.getClickedTile(pos);
}
@Override
public void onStepFinished(Entity entity, World world, Level level)
{
for (MapInteractionPlugin p : plugins) {
p.onStepEnd(this, pc);
}
}
@Override
public void onPathFinished(Entity entity, World world, Level level)
{
for (MapInteractionPlugin p : plugins) {
p.onStepEnd(this, pc);
}
}
@Override
public void onPathInterrupted(Entity entity, World world, Level level)
{
for (MapInteractionPlugin p : plugins) {
p.onStepEnd(this, pc);
}
}
@Override
public void receive(MouseButtonEvent event)
{
if (!event.isOver(this)) return;
if (!event.isUp()) return; // only btn-release evt
for (MapInteractionPlugin p : plugins) {
p.onClick(this, pc, event.getPos());
}
event.consume(); // only our clicks.
}
@Override
public void receive(KeyEvent event)
{
if (!event.isDown()) return;
for (MapInteractionPlugin p : plugins) {
p.onKey(this, pc, event.getKey());
}
// don't consume key events, can be useful for others.
}
public void addPlugin(MapInteractionPlugin plugin)
{
plugins.add(plugin);
}
}

@ -112,7 +112,7 @@ class MenuLayer extends ScreenLayer {
@Override @Override
public int getPriority() public int getZIndex()
{ {
return 2; return 2;
} }

@ -81,7 +81,7 @@ public class LayerBouncyBoxes extends ScreenLayer {
@Override @Override
public int getPriority() public int getZIndex()
{ {
return 0; return 0;
} }

@ -18,7 +18,7 @@ public class LayerColor extends ScreenLayer {
@Override @Override
public int getPriority() public int getZIndex()
{ {
return Integer.MIN_VALUE; return Integer.MIN_VALUE;
} }

@ -3,7 +3,8 @@ package mightypork.rogue.screens.test_cat_sound;
import java.util.Random; import java.util.Random;
import mightypork.gamecore.control.events.MouseButtonEvent; import mightypork.gamecore.control.events.input.MouseButtonEvent;
import mightypork.gamecore.control.events.input.MouseButtonListener;
import mightypork.gamecore.gui.AlignX; import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.painters.ImagePainter; import mightypork.gamecore.gui.components.painters.ImagePainter;
import mightypork.gamecore.gui.components.painters.QuadPainter; import mightypork.gamecore.gui.components.painters.QuadPainter;
@ -21,7 +22,7 @@ import mightypork.util.math.Easing;
import mightypork.util.math.color.Color; import mightypork.util.math.color.Color;
public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.Listener { public class LayerFlyingCat extends ScreenLayer implements MouseButtonListener {
private final NumAnimated size = new NumAnimated(300, Easing.SINE_BOTH); private final NumAnimated size = new NumAnimated(300, Easing.SINE_BOTH);
private final VectAnimated cat_position = VectAnimated.makeVar(Easing.ELASTIC_OUT); private final VectAnimated cat_position = VectAnimated.makeVar(Easing.ELASTIC_OUT);
@ -99,7 +100,7 @@ public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.List
@Override @Override
public int getPriority() public int getZIndex()
{ {
return 10; return 10;
} }

@ -33,7 +33,7 @@ public class LayerTestGradient extends ScreenLayer {
@Override @Override
public int getPriority() public int getZIndex()
{ {
return 0; return 0;
} }

@ -2,6 +2,7 @@ package mightypork.rogue.world;
import mightypork.rogue.world.entity.models.EntityMoveListener; import mightypork.rogue.world.entity.models.EntityMoveListener;
import mightypork.rogue.world.level.Level;
public class PlayerControl { public class PlayerControl {
@ -9,50 +10,55 @@ public class PlayerControl {
private final World world; private final World world;
public PlayerControl(World w) public PlayerControl(World w) {
{
this.world = w; this.world = w;
} }
public void walkNorth() public void goNorth()
{ {
world.playerEntity.addStep(PathStep.NORTH); world.getPlayerEntity().addStep(PathStep.NORTH);
} }
public void walkSouth() public void goSouth()
{ {
world.playerEntity.addStep(PathStep.SOUTH); world.getPlayerEntity().addStep(PathStep.SOUTH);
} }
public void walkEast() public void goEast()
{ {
world.playerEntity.addStep(PathStep.EAST); world.getPlayerEntity().addStep(PathStep.EAST);
} }
public void walkWest() public void goWest()
{ {
world.playerEntity.addStep(PathStep.WEST); world.getPlayerEntity().addStep(PathStep.WEST);
} }
public void addMoveListener(EntityMoveListener eml) public void addMoveListener(EntityMoveListener eml)
{ {
world.playerEntity.addMoveListener(eml); world.getPlayerEntity().addMoveListener(eml);
} }
public WorldPos getPos() public WorldPos getPos()
{ {
return world.playerEntity.getPosition(); return world.getPlayerEntity().getPosition();
}
public World getWorld()
{
return world;
} }
public void walk(PathStep step) public Level getLevel()
{ {
world.playerEntity.addStep(step); return world.getCurrentLevel();
} }
} }

@ -21,8 +21,8 @@ public class World implements IonBundled, Updateable {
private final ArrayList<Level> levels = new ArrayList<>(); private final ArrayList<Level> levels = new ArrayList<>();
final PlayerInfo player = new PlayerInfo(); private final PlayerInfo playerInfo = new PlayerInfo();
Entity playerEntity; private Entity playerEntity;
private final PlayerControl control = new PlayerControl(this); private final PlayerControl control = new PlayerControl(this);
@ -36,9 +36,9 @@ public class World implements IonBundled, Updateable {
seed = in.get("seed", 0L); seed = in.get("seed", 0L);
eid = in.get("next_eid", 0); eid = in.get("next_eid", 0);
in.loadSequence("levels", levels); in.loadSequence("levels", levels);
in.loadBundled("player", player); in.loadBundled("player", playerInfo);
playerEntity = levels.get(player.getLevel()).getEntity(player.getEID()); playerEntity = levels.get(playerInfo.getLevel()).getEntity(playerInfo.getEID());
} }
@ -48,7 +48,7 @@ public class World implements IonBundled, Updateable {
out.put("seed", seed); out.put("seed", seed);
out.put("next_eid", eid); out.put("next_eid", eid);
out.putSequence("levels", levels); out.putSequence("levels", levels);
out.putBundled("player", player); out.putBundled("player", playerInfo);
} }
@ -88,7 +88,7 @@ public class World implements IonBundled, Updateable {
public void createPlayer(int x, int y, int level) public void createPlayer(int x, int y, int level)
{ {
if (player.isInitialized()) { if (playerInfo.isInitialized()) {
throw new RuntimeException("Player already created."); throw new RuntimeException("Player already created.");
} }
@ -97,8 +97,8 @@ public class World implements IonBundled, Updateable {
playerEntity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y)); playerEntity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y));
player.setLevel(level); playerInfo.setLevel(level);
player.setEID(playerEid); playerInfo.setEID(playerEid);
levels.get(level).addEntity(playerEntity); levels.get(level).addEntity(playerEntity);
} }
@ -106,7 +106,7 @@ public class World implements IonBundled, Updateable {
public Level getCurrentLevel() public Level getCurrentLevel()
{ {
return levels.get(player.getLevel()); return levels.get(playerInfo.getLevel());
} }

@ -14,6 +14,7 @@ import mightypork.util.constraints.rect.RectConst;
import mightypork.util.constraints.rect.caching.RectCache; import mightypork.util.constraints.rect.caching.RectCache;
import mightypork.util.constraints.rect.proxy.RectProxy; import mightypork.util.constraints.rect.proxy.RectProxy;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;
import mightypork.util.constraints.vect.VectConst;
import mightypork.util.constraints.vect.caching.VectCache; import mightypork.util.constraints.vect.caching.VectCache;
import mightypork.util.math.color.RGB; import mightypork.util.math.color.RGB;
@ -42,12 +43,14 @@ public class WorldRenderer extends RectProxy implements Pollable {
private final Rect topShadow; private final Rect topShadow;
private final Rect bottomShadow; private final Rect bottomShadow;
private TileRenderContext trc;
public WorldRenderer(World world, Rect viewport, int xTiles, int yTiles, int minTileSize) { public WorldRenderer(World world, Rect viewport, int xTiles, int yTiles, int minTileSize) {
super(viewport); super(viewport);
this.world = world; this.world = world;
this.player = world.playerEntity; this.player = world.getPlayerEntity();
tileSize = width().div(xTiles).min(height().div(yTiles)).max(minTileSize).cached(); tileSize = width().div(xTiles).min(height().div(yTiles)).max(minTileSize).cached();
@ -62,11 +65,11 @@ public class WorldRenderer extends RectProxy implements Pollable {
topShadow = topEdge().growDown(grY); topShadow = topEdge().growDown(grY);
bottomShadow = bottomEdge().growUp(grY); bottomShadow = bottomEdge().growUp(grY);
setupMapRect(); rebuildTiles();
} }
private void setupMapRect() private void rebuildTiles()
{ {
Level level = world.getCurrentLevel(); Level level = world.getCurrentLevel();
@ -74,29 +77,30 @@ public class WorldRenderer extends RectProxy implements Pollable {
activeLevel = level; activeLevel = level;
mapRect = Rect.make(vpCenter, tileSize.mul(level.getWidth()), tileSize.mul(level.getHeight())).cached(); mapRect = Rect.make(vpCenter, tileSize.mul(level.getWidth()), tileSize.mul(level.getHeight())).cached();
trc = new TileRenderContext(activeLevel, mapRect);
} }
private RectConst getCurrentDrawRect() private int[] getOffset()
{ {
WorldPos pos = player.getPosition(); WorldPos pos = player.getPosition();
final double playerX = pos.getVisualX(); final double playerX = pos.getVisualX();
final double playerY = pos.getVisualY(); final double playerY = pos.getVisualY();
double ts = tileSize.value(); double ts = tileSize.value();
final RectConst drawRect = mapRect.move(-ts * playerX, -ts * playerY).freeze(); return new int[]{(int) (-ts * playerX), (int) (-ts * playerY)};
return drawRect;
} }
public void render() public void render()
{ {
setupMapRect(); int[] off = getOffset();
System.out.println(trc.getRectForTile(10, 10));
final TileRenderContext rc = new TileRenderContext(activeLevel, getCurrentDrawRect()); Render.pushMatrix();
Render.translate(off[0], off[1]);
// tiles to render // tiles to render
final WorldPos pos = player.getPosition(); final WorldPos pos = player.getPosition();
@ -117,9 +121,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles16")); Render.enterBatchTexturedQuadMode(Res.getTexture("tiles16"));
} }
for (rc.y = y1; rc.y <= y2; rc.y++) { for (trc.y = y1; trc.y <= y2; trc.y++) {
for (rc.x = x1; rc.x <= x2; rc.x++) { for (trc.x = x1; trc.x <= x2; trc.x++) {
rc.renderTile(); trc.renderTile();
} }
} }
@ -129,9 +133,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
// === ITEMS ON TILES === // === ITEMS ON TILES ===
for (rc.y = y1; rc.y <= y2; rc.y++) { for (trc.y = y1; trc.y <= y2; trc.y++) {
for (rc.x = x1; rc.x <= x2; rc.x++) { for (trc.x = x1; trc.x <= x2; trc.x++) {
rc.renderItems(); trc.renderItems();
} }
} }
@ -146,9 +150,11 @@ public class WorldRenderer extends RectProxy implements Pollable {
if (x < x1 - ts || x > x2 + ts) continue; if (x < x1 - ts || x > x2 + ts) continue;
if (y < y1 - ts || y > y2 + ts) continue; if (y < y1 - ts || y > y2 + ts) continue;
e.render(rc); e.render(trc);
} }
Render.popMatrix();
// === OVERLAY SHADOW === // === OVERLAY SHADOW ===
Render.quadGradH(leftShadow, RGB.BLACK, RGB.NONE); Render.quadGradH(leftShadow, RGB.BLACK, RGB.NONE);
@ -161,9 +167,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
public WorldPos getClickedTile(Vect clickPos) public WorldPos getClickedTile(Vect clickPos)
{ {
RectConst drawRect = getCurrentDrawRect(); int[] off = getOffset();
Vect v = clickPos.sub(drawRect.origin()); Vect v = clickPos.sub(mapRect.origin().add(off[0], off[1]));
int ts = (int)tileSize.value(); int ts = (int) tileSize.value();
return new WorldPos(v.xi() / ts, v.yi() / ts); return new WorldPos(v.xi() / ts, v.yi() / ts);
} }
@ -176,6 +182,8 @@ public class WorldRenderer extends RectProxy implements Pollable {
tileSize.poll(); tileSize.poll();
mapRect.poll(); mapRect.poll();
rebuildTiles();
} }
} }

@ -3,6 +3,7 @@ package mightypork.rogue.world.level.render;
import mightypork.rogue.world.level.MapAccess; import mightypork.rogue.world.level.MapAccess;
import mightypork.util.constraints.rect.Rect; import mightypork.util.constraints.rect.Rect;
import mightypork.util.constraints.rect.RectConst;
import mightypork.util.constraints.rect.builders.TiledRect; import mightypork.util.constraints.rect.builders.TiledRect;
@ -12,18 +13,33 @@ public abstract class MapRenderContext {
protected final TiledRect tiler; protected final TiledRect tiler;
private final Rect mapRect; private final Rect mapRect;
private RectConst tileRects[][];
public MapRenderContext(MapAccess map, Rect drawArea)
{ public MapRenderContext(MapAccess map, Rect drawArea) {
this.map = map; this.map = map;
this.tiler = drawArea.tiles(map.getWidth(), map.getHeight()); this.tiler = drawArea.tiles(map.getWidth(), map.getHeight());
this.mapRect = drawArea; this.mapRect = drawArea;
tileRects = new RectConst[map.getHeight()][map.getWidth()];
rebuildTileRects();
}
public void rebuildTileRects()
{
for(int y=0;y<map.getHeight();y++) {
for(int x=0;x<map.getWidth();x++) {
tileRects[y][x] = tiler.tile(x, y).freeze();
}
}
} }
public Rect getRectForTile(int x, int y) public Rect getRectForTile(int x, int y)
{ {
return tiler.tile(x, y); return tileRects[y][x];
} }

@ -10,7 +10,7 @@ package mightypork.util.constraints;
public abstract class DigestCache<D> implements Digestable<D> { public abstract class DigestCache<D> implements Digestable<D> {
private D last_digest; private D last_digest;
private boolean caching_enabled; private boolean caching_enabled = false;
private boolean dirty = true; 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.Destroyable;
import mightypork.util.control.eventbus.clients.DelegatingClient; 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.DelayedEvent;
import mightypork.util.control.eventbus.events.flags.ImmediateEvent; import mightypork.util.control.eventbus.events.flags.ImmediateEvent;
import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent; import mightypork.util.control.eventbus.events.flags.SingleReceiverEvent;
@ -32,10 +31,10 @@ final public class EventBus implements Destroyable {
private class DelayQueueEntry implements Delayed { private class DelayQueueEntry implements Delayed {
private final long due; 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(); super();
this.due = System.currentTimeMillis() + (long) (seconds * 1000); 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; return evt;
} }
@ -103,17 +102,17 @@ final public class EventBus implements Destroyable {
static final String logMark = "<BUS> "; static final String logMark = "<BUS> ";
private static Class<?> getEventListenerClass(Event<?> event) private static Class<?> getEventListenerClass(BusEvent<?> event)
{ {
// BEHOLD, MAGIC! // BEHOLD, MAGIC!
final Type[] interfaces = event.getClass().getGenericInterfaces();
for (final Type interf : interfaces) { final Type evtc = event.getClass().getGenericSuperclass();
if (interf instanceof ParameterizedType) {
if (((ParameterizedType) interf).getRawType() == Event.class) { if (evtc instanceof ParameterizedType) {
final Type[] types = ((ParameterizedType) interf).getActualTypeArguments(); if (((ParameterizedType) evtc).getRawType() == BusEvent.class) {
for (final Type genericType : types) { final Type[] types = ((ParameterizedType) evtc).getActualTypeArguments();
return (Class<?>) genericType; for (final Type genericType : types) {
} return (Class<?>) genericType;
} }
} }
} }
@ -169,7 +168,7 @@ final public class EventBus implements Destroyable {
* *
* @param event event * @param event event
*/ */
public void send(Event<?> event) public void send(BusEvent<?> event)
{ {
assertLive(); assertLive();
@ -193,7 +192,7 @@ final public class EventBus implements Destroyable {
* *
* @param event event * @param event event
*/ */
public void sendQueued(Event<?> event) public void sendQueued(BusEvent<?> event)
{ {
assertLive(); assertLive();
@ -207,7 +206,7 @@ final public class EventBus implements Destroyable {
* @param event event * @param event event
* @param delay delay before event is dispatched * @param delay delay before event is dispatched
*/ */
public void sendDelayed(Event<?> event, double delay) public void sendDelayed(BusEvent<?> event, double delay)
{ {
assertLive(); assertLive();
@ -228,7 +227,7 @@ final public class EventBus implements Destroyable {
* *
* @param event event * @param event event
*/ */
public void sendDirect(Event<?> event) public void sendDirect(BusEvent<?> event)
{ {
assertLive(); 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(); assertLive();
@ -282,7 +281,7 @@ final public class EventBus implements Destroyable {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private boolean addChannelForEvent(Event<?> event) private boolean addChannelForEvent(BusEvent<?> event)
{ {
try { try {
if (detailedLogging) { if (detailedLogging) {
@ -298,7 +297,7 @@ final public class EventBus implements Destroyable {
//channels.flush(); //channels.flush();
if (detailedLogging) { 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; return true;
@ -333,7 +332,7 @@ final public class EventBus implements Destroyable {
* *
* @param event event * @param event event
*/ */
private synchronized void dispatch(Event<?> event) private synchronized void dispatch(BusEvent<?> event)
{ {
assertLive(); assertLive();
@ -349,12 +348,11 @@ final public class EventBus implements Destroyable {
* @param clients clients * @param clients clients
* @param event event * @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; boolean accepted = false;
final boolean singular = event.getClass().isAnnotationPresent(SingleReceiverEvent.class); event.clearFlags();
for (int i = 0; i < 2; i++) { // two tries. for (int i = 0; i < 2; i++) { // two tries.
@ -362,10 +360,10 @@ final public class EventBus implements Destroyable {
for (final EventChannel<?, ?> b : channels) { for (final EventChannel<?, ?> b : channels) {
if (b.canBroadcast(event)) { if (b.canBroadcast(event)) {
accepted = true; accepted = true;
sent |= b.broadcast(event, clients); b.broadcast(event, clients);
} }
if (sent && singular) break; if (event.isConsumed()) break;
} }
channels.setBuffering(false); 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 (!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 (!detailedLogging) return false;
if (event.getClass().isAnnotationPresent(UnloggedEvent.class)) 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.DelegatingClient;
import mightypork.util.control.eventbus.clients.ToggleableClient; 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.control.eventbus.events.flags.SingleReceiverEvent;
import mightypork.util.logging.Log; import mightypork.util.logging.Log;
@ -18,7 +17,7 @@ import mightypork.util.logging.Log;
* @param <EVENT> event type * @param <EVENT> event type
* @param <CLIENT> client (subscriber) 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<CLIENT> clientClass;
private final Class<EVENT> eventClass; private final Class<EVENT> eventClass;
@ -48,13 +47,12 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* *
* @param event a event to be sent * @param event a event to be sent
* @param clients collection of clients * @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 event sent event
* @param clients subscribing clients * @param clients subscribing clients
* @param processed clients already processed * @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) { for (final Object client : clients) {
// exclude obvious non-clients // exclude obvious non-clients
@ -90,10 +84,9 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
if (!((ToggleableClient) client).isListening()) continue; if (!((ToggleableClient) client).isListening()) continue;
} }
sent |= sendTo(client, event); sendTo(client, event);
// singular event ain't no whore, handled once only. if (event.isConsumed()) return;
if (sent && singular) return true;
// pass on to delegated clients // pass on to delegated clients
if (client instanceof DelegatingClient) { if (client instanceof DelegatingClient) {
@ -102,14 +95,12 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
final Collection<Object> children = ((DelegatingClient) client).getChildClients(); final Collection<Object> children = ((DelegatingClient) client).getChildClients();
if (children != null && children.size() > 0) { 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 client target client
* @param event event to send * @param event event to send
* @return success
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private boolean sendTo(Object client, EVENT event) private void sendTo(Object client, EVENT event)
{ {
if (isClientOfType(client)) { if (isClientOfChannelType(client)) {
((Event<CLIENT>) event).handleBy((CLIENT) client); ((BusEvent<CLIENT>) event).deliverTo((CLIENT) client);
return true;
} }
return false;
} }
@ -137,7 +125,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* @param event event object * @param event event object
* @return can be broadcasted * @return can be broadcasted
*/ */
public boolean canBroadcast(Event<?> event) public boolean canBroadcast(BusEvent<?> event)
{ {
return event != null && eventClass.isInstance(event); return event != null && eventClass.isInstance(event);
} }
@ -150,7 +138,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* @param clientClass client class * @param clientClass client class
* @return the broadcaster * @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); return new EventChannel<>(eventClass, clientClass);
} }
@ -162,7 +150,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* @param client client * @param client client
* @return is of type * @return is of type
*/ */
private boolean isClientOfType(Object client) private boolean isClientOfChannelType(Object client)
{ {
return clientClass.isInstance(client); return clientClass.isInstance(client);
} }
@ -176,7 +164,7 @@ class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
*/ */
public boolean isClientValid(Object 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 @Override
public final Collection<Object> getChildClients() public Collection<Object> getChildClients()
{ {
return clients; return clients;
} }
@Override @Override
public final boolean doesDelegate() public boolean doesDelegate()
{ {
return delegating; return delegating;
} }
@Override @Override
public final boolean isListening() public boolean isListening()
{ {
return listening; return listening;
} }
@ -60,7 +60,7 @@ public abstract class BusNode implements BusAccess, ClientHub {
* @param client * @param client
*/ */
@Override @Override
public final void addChildClient(Object client) public void addChildClient(Object client)
{ {
if (client instanceof RootBusNode) { if (client instanceof RootBusNode) {
throw new IllegalArgumentException("Cannot nest RootBusNode."); throw new IllegalArgumentException("Cannot nest RootBusNode.");
@ -76,7 +76,7 @@ public abstract class BusNode implements BusAccess, ClientHub {
* @param client subscriber to remove * @param client subscriber to remove
*/ */
@Override @Override
public final void removeChildClient(Object client) public void removeChildClient(Object client)
{ {
if (client != null) { if (client != null) {
clients.remove(client); clients.remove(client);
@ -89,7 +89,7 @@ public abstract class BusNode implements BusAccess, ClientHub {
* *
* @param listening receive events * @param listening receive events
*/ */
public final void setListening(boolean listening) public void setListening(boolean listening)
{ {
this.listening = listening; this.listening = listening;
} }
@ -100,14 +100,14 @@ public abstract class BusNode implements BusAccess, ClientHub {
* *
* @param delegating * @param delegating
*/ */
public final void setDelegating(boolean delegating) public void setDelegating(boolean delegating)
{ {
this.delegating = delegating; this.delegating = delegating;
} }
@Override @Override
public final EventBus getEventBus() public EventBus getEventBus()
{ {
return busAccess.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 {
}
Loading…
Cancel
Save