/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * JavaWorld Library, Copyright 2011 Bryan Chadwick * * * * FILE: ./universe/base/UniverseBase.java * * * * This file is part of JavaWorld. * * * * JavaWorld is free software: you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation, either version * * 3 of the License, or (at your option) any later version. * * * * JavaWorld is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with JavaWorld. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package universe.base; import universe.control.*; import java.awt.Color; import java.awt.RenderingHints; import universe.*; import javax.swing.*; import java.awt.Graphics2D; import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.Serializable; import image.*; /* TODO: */ /** A Class representing a Universe (a collection of Worlds) of some type, and related methods * and Function Objects for handling messages and events */ public class UniverseBase{ public static int PORT = 4567; private Universe initial; double time; // Handlers OnDraw ondraw; OnTick ontick; OnNew onnew; OnDisconnect ondisconnect; OnMsg onmsg; public UniverseBase(Universe initial){ this(initial, 0.05, null, null, null, null, null); } public UniverseBase onDraw(OnDraw ondraw){ return new UniverseBase(this.initial, this.time, ondraw, this.ontick, this.onnew, this.ondisconnect, this.onmsg); } public UniverseBase onTick(OnTick ontick){ return onTick(ontick, 0.05); } public UniverseBase onTick(OnTick ontick, double time){ return new UniverseBase(this.initial, this.time, this.ondraw, ontick, this.onnew, this.ondisconnect, this.onmsg); } public UniverseBase onNew(OnNew onnew){ return new UniverseBase(this.initial, this.time, this.ondraw, this.ontick, onnew, this.ondisconnect, this.onmsg); } public UniverseBase onDisconnect(OnDisconnect ondisconnect){ return new UniverseBase(this.initial, this.time, this.ondraw, this.ontick, this.onnew, ondisconnect, this.onmsg); } public UniverseBase onMsg(OnMsg onmsg){ return new UniverseBase(this.initial, this.time, this.ondraw, this.ontick, this.onnew, this.ondisconnect, onmsg); } private static int SPACE = 5; public Universe universe(){ if(this.onmsg == null) throw new RuntimeException("No Universe Message Handler"); if(this.ondraw == null) throw new RuntimeException("No Universe Draw Handler"); JDialog f = new JDialog((JFrame)null, "Universe", true); Scene scn = doOnDraw(this.initial); final Handler handler = new Handler(this, this.initial, new BufferedImage((int)(scn.width()+2*SPACE), (int)(scn.height()+2*SPACE), BufferedImage.TYPE_INT_RGB), (int)(this.time*1000), f); f.setSize((int)(SPACE*2+Math.max(20, 14+scn.width())), (int)(Math.max(20, SPACE*2+31+scn.height()))); f.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); f.setResizable(false); f.getContentPane().add(handler); handler.run.start(); try{ final Server server = new Server(PORT, false, this); Thread msgs = new Thread(){ public void run(){ while(true){ try{ synchronized(server){ server.wait(); } if(server.hasMessage()){ // Handle messages... WithWorld m = server.nextMessage(); Bundle res = null; if(m.isConnect()){ res = doOnNew(handler.u, m.getWImp()); }else if(m.isDisconnect()){ res = doDisconnect(handler.u, m.getWImp(), server); }else if(m.isTransfer()){ res = doOnMsg(handler.u, m.getWImp(), m.payload()); }else Server.p("Unknown Message Type"); if(res != null){ handler.replace(res); for(Mail mail : res.getMails()){ server.processMail(mail, m.getWImp()); } // res.getWorlds() } } }catch(InterruptedException e){ Server.p("!!Interrupted!!"); } } } }; msgs.start(); f.setVisible(true); // Kill all the threads System.exit(0); //handler.run.stop(); }catch(java.io.IOException e){ throw new RuntimeException(e); } return handler.u; } // Private constructors... private UniverseBase(Universe init, double time, OnDraw ondraw, OnTick ontick, OnNew onnew, OnDisconnect ondisconnect, OnMsg onmsg){ this.initial = init; this.time = time; this.ondraw = ondraw; this.ontick = ontick; this.onnew = onnew; this.ondisconnect = ondisconnect; this.onmsg = onmsg; } /** Handles the nitty-gritty of Universe updates */ static class Handler extends javax.swing.JComponent implements ActionListener{ private static final long serialVersionUID = 1L; UniverseBase univ; Universe u; BufferedImage buffer; Graphics2D graph; Timer run; Handler(UniverseBase univ, Universe u, BufferedImage buff, int msec, JDialog dia){ this.univ = univ; this.u = u; this.run = new Timer(msec, this); this.buffer = buff; this.graph = buff.createGraphics(); this.graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); this.graph.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); } public void actionPerformed(ActionEvent e){ replace(this.univ.doOnTick(this.u)); } private synchronized void replace(Bundle b){ if(b == null)return; boolean change = !this.u.equals(b.getUniverse()); this.u = b.getUniverse(); if(change)repaint(); } public void paint(java.awt.Graphics g){ this.graph.setColor(Color.white); this.graph.fillRect(0,0, this.getWidth(), this.getHeight()); this.graph.clipRect(SPACE, SPACE, this.buffer.getWidth()-SPACE*2, this.buffer.getHeight()-SPACE*2); this.univ.doOnDraw(this.u).paint(this.graph,SPACE,SPACE); g.drawImage(this.buffer, 0, 0, null); } } Scene doOnDraw(Universe u){ return this.ondraw.apply(u); } Bundle doOnTick(Universe u){ if(this.ontick == null)return null; return this.ontick.apply(u); } Bundle doOnNew(Universe u, IWorld w){ if(this.onnew == null)return null; return this.onnew.apply(u, w); } Bundle doDisconnect(Universe u, IWorld w, Server server){ if(this.ondisconnect == null)return null; server.removeWorld(w); return this.ondisconnect.apply(u, w); } Bundle doOnMsg(Universe u, IWorld w, Msg msg){ if(this.onmsg == null)return null; return this.onmsg.apply(u, w, msg); } }