@Override public void update(int tick) { sortEntities(); @SuppressWarnings("unchecked") List<Entity> sorted = (List<Entity>) entities.clone(); Collections.reverse(sorted); for (Entity entity : sorted) { entity.update(tick); if (entity.isDead()) { if (entity.equals(selectedEntity)) selectedEntity = null; entities.remove(entity); } } for (Projectile p : projectiles) { p.update(tick); if (p.isDead()) projectiles.remove(p); } for (Animation a : animations) { a.update(tick); if (a.isDead()) animations.remove(a); } }
public void sortEntities() { @SuppressWarnings("unchecked") ArrayList<Entity> sorted = new ArrayList<>((List<Entity>) entities.clone()); try { Collections.sort( sorted, new Comparator<Entity>() { @Override public int compare(Entity o1, Entity o2) { float dif = (o1.getY() + o1.getHeight()) - (o2.getY() + o2.getHeight()); if (dif < 0) return -1; else if (dif > 0) return 1; return 0; } }); } catch (IllegalArgumentException e) { } entities = new CopyOnWriteArrayList<>(sorted); }
@Override public Object clone() { return copyOnWriteArrayList.clone(); }
/** * Handle replies to certain OFMessages, and pass others off to listeners * * @param sw * @param msgs * @throws IOException */ @SuppressWarnings("unchecked") protected void handleMessages(IOFSwitchExt sw, List<OFMessage> msgs) throws IOException { for (OFMessage m : msgs) { // If we detect a write failure, break early so we can disconnect if (((OFStream) sw.getInputStream()).getWriteFailure()) { break; } // Always handle ECHO REQUESTS, regardless of state switch (m.getType()) { case ECHO_REQUEST: OFMessageInStream in = sw.getInputStream(); OFMessageOutStream out = sw.getOutputStream(); OFEchoReply reply = (OFEchoReply) in.getMessageFactory().getMessage(OFType.ECHO_REPLY); reply.setXid(m.getXid()); out.write(reply); break; case ECHO_REPLY: // *Note, ECHO REPLIES need no handling due to last message timestamp break; case ERROR: logError(sw, (OFError) m); // fall through intentionally so error can be listened for default: switch (sw.getState()) { case DISCONNECTED: log.info("Switch {} in state DISCONNECTED, exiting message processing loop", sw); return; case HELLO_SENT: if (m.getType() == OFType.HELLO) { log.debug("HELLO from {}", sw); sw.transitionToState(OFSwitchState.FEATURES_REQUEST_SENT); // Send initial Features Request sw.getOutputStream().write(factory.getMessage(OFType.FEATURES_REQUEST)); } break; case FEATURES_REQUEST_SENT: if (m.getType() == OFType.FEATURES_REPLY) { log.debug("Features Reply from {}", sw); sw.setFeaturesReply((OFFeaturesReply) m); // Send Description Statistics Request OFStatisticsRequest sr = new OFStatisticsRequest(); sr.setStatisticType(OFStatisticsType.DESC); sw.getOutputStream().write(sr); sw.transitionToState(OFSwitchState.DESCRIPTION_STATISTICS_REQUEST_SENT); } break; case DESCRIPTION_STATISTICS_REQUEST_SENT: if (m.getType() == OFType.STATS_REPLY) { OFStatisticsReply sr = (OFStatisticsReply) m; if (sr.getStatisticType() == OFStatisticsType.DESC && sr.getStatistics().size() > 0) { OFDescriptionStatistics desc = (OFDescriptionStatistics) sr.getStatistics().get(0); sw.setDescriptionStatistics(desc); log.debug("Description Statistics Reply from {}: {}", sw, desc); // Set config and request to receive the config OFSetConfig config = (OFSetConfig) factory.getMessage(OFType.SET_CONFIG); config.setMissSendLength((short) 0xffff).setLengthU(OFSetConfig.MINIMUM_LENGTH); sw.getOutputStream().write(config); sw.getOutputStream().write(factory.getMessage(OFType.BARRIER_REQUEST)); sw.getOutputStream().write(factory.getMessage(OFType.GET_CONFIG_REQUEST)); sw.transitionToState(OFSwitchState.GET_CONFIG_REQUEST_SENT); } } break; case GET_CONFIG_REQUEST_SENT: if (m.getType() == OFType.GET_CONFIG_REPLY) { OFGetConfigReply cr = (OFGetConfigReply) m; if (cr.getMissSendLength() == (short) 0xffff) { log.debug("Config Reply from {} confirms miss length set to 0xffff", sw); sw.transitionToState(OFSwitchState.INITIALIZING); CopyOnWriteArrayList<IOFInitializerListener> initializers = (CopyOnWriteArrayList<IOFInitializerListener>) initializerList.clone(); // Add all existing initializers to the list this.initializerMap.put(sw, initializers); log.debug( "Remaining initializers for switch {}: {}", sw, this.initializerMap.get(sw)); // Delete all pre-existing flows if (deletePreExistingFlows) { OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL); OFMessage fm = ((OFFlowMod) sw.getInputStream().getMessageFactory().getMessage(OFType.FLOW_MOD)) .setMatch(match) .setCommand(OFFlowMod.OFPFC_DELETE) .setOutPort(OFPort.OFPP_NONE) .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH)); sw.getOutputStream().write(fm); sw.getOutputStream().write(factory.getMessage(OFType.BARRIER_REQUEST)); } if (initializers.size() > 0) queueInitializer(sw, initializers.iterator().next()); else advanceInitializers(sw); } else { log.error( "Switch {} refused to set miss send length to 0xffff, disconnecting", sw); disconnectSwitch(((OFStream) sw.getInputStream()).getKey(), sw); return; } } break; case INITIALIZING: CopyOnWriteArrayList<IOFInitializerListener> initializers = initializerMap.get(sw); Iterator<IOFInitializerListener> it = initializers.iterator(); if (it.hasNext()) { IOFInitializerListener listener = it.next(); try { listener.initializerReceive(sw, m); } catch (Exception e) { log.error( "Error calling initializer listener: {} on switch: {} for message: {}, removing listener", new Object[] {listener, sw, m}); advanceInitializers(sw); } } break; case ACTIVE: List<IOFMessageListener> listeners = messageListeners.get(m.getType()); if (listeners != null) { for (IOFMessageListener listener : listeners) { try { if (listener instanceof IOFSwitchFilter) { if (!((IOFSwitchFilter) listener).isInterested(sw)) { continue; } } if (Command.STOP.equals(listener.receive(sw, m))) { break; } } catch (Exception e) { log.error( "Failure calling listener [" + listener.toString() + "] with message [" + m.toString() + "]", e); } } } else { log.debug("Unhandled OF Message: {} from {}", m, sw); } break; } // end switch(sw.getState()) } // end switch(m.getType()) } }
/** * This method provides a "snapshot" in time of the bag items. It does not "lock" or reserve items * in any way. Call <code>reserve(T)</code> on items in the list, or understand the concurrency * implications of modifying items, before performing any action on them. * * @return a possibly empty list of (all) bag items */ @SuppressWarnings("unchecked") public List<T> values() { return (List<T>) sharedList.clone(); }