package env; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import dcpu.Dcpu; import dcpu.WorldPauseHandler; import dcpu.WorldPauser; import render.RenderNode; import shipmaker.EditorShip.EditorShipPart; public class Space implements WorldPauseHandler { HashSet<Entity> entities; TreeSet<RenderNode> rendities; private boolean die; boolean block; boolean canBlock; Object blockLock; private ArrayList<KeyListener> keylisteners; private ArrayList<Beacon> beacons; private ArrayList<Dcpu> cpus; public static final int MS_PER_TICK = 20; public Space() { entities = new HashSet<>(); rendities = new TreeSet<RenderNode>(new Comparator<RenderNode>() { public int compare(RenderNode a, RenderNode b) { if (a.layer() != b.layer()) { return a.layer() - b.layer(); } return a.hashCode() - b.hashCode(); } }); keylisteners = new ArrayList<>(); die = false; block = false; canBlock = false; blockLock = new Object(); beacons = new ArrayList<Beacon>(); cpus = new ArrayList<>(); } public Collection<Dcpu> cpus() { return cpus; } public Set<RenderNode> rendities() { return rendities; } public void addEntity(Entity e) { synchronized(entities) { entities.add(e); rendities.add(e.getVisuals()); } } public void removeEntity(Entity e) { synchronized(entities) { entities.remove(e); rendities.remove(e.getVisuals()); } } public Runnable removeEntityLater(final Entity e) { return new Runnable() { public void run() { removeEntity(e); } }; } public void tickFrame(int ms) { //TODO: make all of this stuff multi-threaded later synchronized(entities) { for (Entity e: entities) { e.tickInternals(ms, this); } for (Entity e: entities) { e.tickPhysics(ms, this); } } } public void blockRunning(boolean blk) { synchronized(blockLock) { if (blk) { while (!canBlock) try { blockLock.wait(); } catch (InterruptedException e) {} block = true; blockLock.notifyAll(); } else { block = false; blockLock.notifyAll(); } } } public void start() { new Thread() { public void run() { long last = System.currentTimeMillis(); while(!die) { try { synchronized(blockLock) { while (block) blockLock.wait(); } long time = System.currentTimeMillis(); long delay = MS_PER_TICK-(time-last); last = time; if (delay > 0) { sleep(delay); } } catch (InterruptedException e) {} synchronized(blockLock) { canBlock = false; } tickFrame(MS_PER_TICK); synchronized(blockLock) { canBlock = true; blockLock.notifyAll(); } } } }.start(); } public void keytyped(KeyEvent k) { for (KeyListener kl : keylisteners) { kl.keyTyped(k); } } public void addKeyListener(KeyListener kl) { keylisteners.add(kl); } public void removeKeyListener(KeyListener kl) { keylisteners.remove(kl); } public Runnable removeEntityAction(final EditorShipPart part) { return new Runnable() { public void run() { entities.remove(part); rendities.remove(part.getVisuals()); } }; } public void stop() { die=true; } public void clearEntities() { synchronized(entities) { entities.clear(); rendities.clear(); } } public Collection<Beacon>beacons() { return beacons; } public void woldPaused(WorldPauser pauser) { System.out.println("PAUSED"); synchronized(blockLock) { canBlock = true; blockLock.notifyAll(); } pauser.waitForUnpause(); synchronized(blockLock) { canBlock = false; } } }