package ch.rasc.s4ws.drawboard; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.imageio.ImageIO; import org.springframework.beans.factory.annotation.Autowired; import ch.rasc.s4ws.drawboard.DrawMessage.ParseException; import reactor.bus.Event; import reactor.bus.EventBus; import reactor.spring.context.annotation.Consumer; import reactor.spring.context.annotation.Selector; @Consumer public final class Room { private final BufferedImage roomImage = new BufferedImage(900, 600, BufferedImage.TYPE_INT_RGB); private final Graphics2D roomGraphics = this.roomImage.createGraphics(); private final Map<String, Long> playerMap = new ConcurrentHashMap<>(); public final EventBus eventBus; @Autowired public Room(EventBus eventBus) { this.eventBus = eventBus; this.roomGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); this.roomGraphics.setBackground(Color.WHITE); this.roomGraphics.clearRect(0, 0, this.roomImage.getWidth(), this.roomImage.getHeight()); } @Selector("newPlayer") public void newPlayer(String sessionId) { this.playerMap.put(sessionId, 0L); Event<String> event = Event.wrap(MessageType.PLAYER_CHANGED.flag + "+"); event.getHeaders().set("excludeId", sessionId); this.eventBus.notify("sendString", event); event = Event.wrap( MessageType.IMAGE_MESSAGE.flag + String.valueOf(this.playerMap.size())); event.getHeaders().set("sessionId", sessionId); this.eventBus.notify("sendString", event); // Store image as PNG ByteArrayOutputStream bout = new ByteArrayOutputStream(); try { ImageIO.write(this.roomImage, "PNG", bout); } catch (IOException e) { /* Should never happen */ } Event<ByteBuffer> byteBufferEvent = Event .wrap(ByteBuffer.wrap(bout.toByteArray())); byteBufferEvent.getHeaders().set("sessionId", sessionId); this.eventBus.notify("sendBinary", byteBufferEvent); } @Selector("removePlayer") public void removePlayer(String sessionId) { Event<String> event = Event.wrap(MessageType.PLAYER_CHANGED.flag + "-"); this.playerMap.remove(sessionId); this.eventBus.notify("sendString", event); } @Selector("incomingMessage") public void handleIncomingData(Event<String> inboundEvent) { String msg = inboundEvent.getData(); String sessionId = inboundEvent.getHeaders().get("sessionId"); char messageType = msg.charAt(0); String messageContent = msg.substring(1); if (messageType == '1') { try { int indexOfChar = messageContent.indexOf('|'); Long msgId = Long.valueOf(messageContent.substring(0, indexOfChar)); this.playerMap.put(sessionId, msgId); DrawMessage drawMessage = DrawMessage .parseFromString(messageContent.substring(indexOfChar + 1)); drawMessage.draw(this.roomGraphics); String drawMessageString = drawMessage.toString(); for (String playerSessionId : this.playerMap.keySet()) { Event<String> event = Event .wrap("1" + this.playerMap.get(playerSessionId) + "," + drawMessageString); event.getHeaders().set("sessionId", playerSessionId); this.eventBus.notify("sendString", event); } } catch (NumberFormatException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } } }