package propra2012.gruppe33.bomberman.graphics.rendering.scenegraph.grid.transform; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import propra2012.gruppe33.bomberman.Game; import propra2012.gruppe33.bomberman.GameConstants; import com.indyforge.twod.engine.graphics.rendering.scenegraph.Entity; import com.indyforge.twod.engine.graphics.rendering.scenegraph.GraphicsEntity; import com.indyforge.twod.engine.graphics.rendering.scenegraph.Scene; import com.indyforge.twod.engine.graphics.rendering.scenegraph.SceneProcessor; import com.indyforge.twod.engine.graphics.rendering.scenegraph.math.Vector2f; import com.indyforge.twod.engine.util.task.Pause; import com.indyforge.twod.engine.util.task.Task; /** * Broadcasts the position changes (delta) of the parent which must be a * graphics entity. * * @author Christopher Probst * */ public final class DeltaPositionBroadcaster extends Entity implements GameConstants { private static final class RestartGame implements Task { /** * */ private static final long serialVersionUID = 1L; private final SceneProcessor processor; private final Game game; public RestartGame(SceneProcessor processor, Game game) { if (processor == null) { throw new NullPointerException("processor"); } else if (game == null) { throw new NullPointerException("game"); } this.processor = processor; this.game = game; } /* * (non-Javadoc) * * @see com.indyforge.twod.engine.util.task.Task#update(float ) */ @Override public boolean update(float tpf) { /* * Initiate new server game! */ try { // Start game game.serverGame(processor); } catch (Exception e) { e.printStackTrace(); } return true; } } /** * */ private static final long serialVersionUID = 1L; // The observed entities private final Map<UUID, Vector2f> entities = new LinkedHashMap<UUID, Vector2f>(); // The message private final ManyPositionsToMany message = new ManyPositionsToMany(); // Tells the passed time private float timePassed = Float.MAX_VALUE; // The minimal number of players private final int minPlayers; // The update delay private final float updateDelay; @Override protected void onUpdate(float tpf) { super.onUpdate(tpf); if (parent() instanceof Scene) { // Convert to scene final Scene scene = (Scene) parent(); // Server mode ? if (scene.processor().hasAdminSessionServer() && timePassed >= updateDelay) { // Are there any entities left ?? if (entities.size() < minPlayers) { // Pause + game restart scene.processor().taskQueue().tasks().add(new Pause(3f)); scene.processor() .taskQueue() .tasks() .add(new RestartGame(scene.processor(), scene.prop( NEXT, Game.class))); // Detach this broadcaster! detach(); return; } // Clear old message.entityMap().clear(); // Used to remove uuids later... List<UUID> removed = null; // Go through all observed entities for (Entry<UUID, Vector2f> entity : entities.entrySet()) { // Lookup entity GraphicsEntity ptr = (GraphicsEntity) scene.registry().get( entity.getKey()); // Add old uuid to remove list! if (ptr == null) { if (removed == null) { removed = new ArrayList<UUID>(); } removed.add(entity.getKey()); // Continue... continue; } // Calc the absolute position Vector2f absolutePosition = ptr.position().add( ((GraphicsEntity) ptr.parent()).position()); // If positions are not equal if (!absolutePosition.equals(entity.getValue())) { // Calc the absolute delta position Vector2f delta = absolutePosition .sub(entity.getValue()); // Save! entity.getValue().set(absolutePosition); // Put delta vector message.entityMap().put(entity.getKey(), delta); } } // Delete old entities if (removed != null) { for (UUID entity : removed) { entities.remove(entity); } } // Send if not empty! if (!message.entityMap().isEmpty()) { // Broadcast the change scene.processor().adminSessionServer().broadcast() .queueChange(message, true); } // Reset time timePassed = 0; } else { timePassed += tpf; } } } /** * Creats a new delta position broadcaster using the absolute update delay. * * @param updateDelay * The update delay. */ public DeltaPositionBroadcaster(float updateDelay, int minPlayers) { if (minPlayers < 1) { throw new IllegalArgumentException("minPlayers must be >= 1"); } this.updateDelay = updateDelay; this.minPlayers = minPlayers; } /** * @return the minimal number of players. */ public int minPlayers() { return minPlayers; } /** * @return the update delay. */ public float updateDelay() { return updateDelay; } public Map<UUID, Vector2f> entities() { return entities; } }