package rts.views; import java.io.IOException; import java.util.ArrayList; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Image; import org.newdawn.slick.SlickException; import org.newdawn.slick.state.StateBasedGame; import org.newdawn.slick.state.transition.FadeInTransition; import org.newdawn.slick.state.transition.FadeOutTransition; import de.matthiasmann.twl.Button; import de.matthiasmann.twl.EditField; import de.matthiasmann.twl.Label; import de.matthiasmann.twl.ScrollPane; import de.matthiasmann.twl.Table; import de.matthiasmann.twl.ThemeInfo; import de.matthiasmann.twl.Widget; import de.matthiasmann.twl.TableBase.CellWidgetCreator; import de.matthiasmann.twl.model.AbstractTableModel; import rts.core.Game; import rts.core.engine.GameGoal; import rts.core.network.INetworkDiscoverListener; import rts.core.network.NetworkManager; import rts.core.network.menu_tcp_containers.ServerState; import rts.utils.ResourceManager; import rts.utils.Timer; /** * Menu associated to the network. * * @author Vince * */ public class NetworkView extends View { private NetworkManager manager; private Timer unreachableServerTimer; private Image background; private Image title; // Gui private Button createButton; private Button refreshButton; private TableServerModel tableModel; private Button joinButton; private EditField ipTextField; private Button exitButton; @Override public void initResources() { background = ResourceManager.getImage("network_view_background"); title = ResourceManager.getSpriteSheet("menutitles").getSprite(0, 0); manager = game.getNetworkManager(); unreachableServerTimer = new Timer(4000); unreachableServerTimer.setTimeComplete(); } @Override public void initTwlComponent() { int x = container.getWidth() / 2; int y = container.getHeight() / 2; createButton = new Button("Create Game"); createButton.setSize(80, 30); createButton.setPosition(x - 360, y - 240); createButton.addCallback(new Runnable() { @Override public void run() { create(); } }); root.add(createButton); refreshButton = new Button("Refresh"); refreshButton.setSize(70, 30); refreshButton.setPosition(x + 250, y - 240); refreshButton.addCallback(new Runnable() { @Override public void run() { try { tableModel.clear(); manager.discover(); } catch (IOException e) { e.printStackTrace(); } } }); root.add(refreshButton); Table table = new Table(); table.setSize(692, 367); table.setDefaultSelectionManager(); tableModel = new TableServerModel(); table.setModel(tableModel); table.registerCellRenderer(String.class, new EditFieldCellWidgetCreator()); table.registerCellRenderer(ServerInfo.class, new ButtonCellWidgetCreator()); table.setColumnWidth(0, 75); table.setColumnWidth(1, 75); table.setColumnWidth(2, 50); table.setColumnWidth(3, 200); table.setColumnWidth(4, 150); table.setColumnWidth(5, 100); ScrollPane scrollPane = new ScrollPane(table); scrollPane.setFixed(ScrollPane.Fixed.HORIZONTAL); scrollPane.setPosition(9, 6); scrollPane.setSize(702, 367); Widget widget = new Widget(); widget.setSize(720, 380); widget.setPosition(x - 360, y - 200); widget.add(scrollPane); root.add(widget); widget = new Widget(); widget.setSize(720, 50); widget.setPosition(x - 360, y + 200); Label label = new Label("Connection using ip:"); label.setPosition(20, 25); widget.add(label); ipTextField = new EditField(); ipTextField.setText("localhost"); ipTextField.setMaxTextLength(15); ipTextField.setSize(120, 15); ipTextField.setPosition(170, 15); widget.add(ipTextField); joinButton = new Button(); joinButton.setText("Join"); joinButton.setSize(70, 20); joinButton.setPosition(310, 14); joinButton.addCallback(new Runnable() { @Override public void run() { join(ipTextField.getText()); } }); widget.add(joinButton); exitButton = new Button("Exit"); exitButton.setSize(70, 30); exitButton.setPosition(x - 360, y + 255); exitButton.addCallback(new Runnable() { @Override public void run() { NetworkView.this.game.enterState(Game.MAIN_MENU_VIEW_ID, new FadeOutTransition(), new FadeInTransition()); } }); root.add(exitButton); root.add(widget); } private void create() { try { createButton.setEnabled(false); joinButton.setEnabled(false); game.getNetworkManager().createServer(); game.getNetworkManager().joinServer("localhost"); game.enterState(Game.CREATE_VIEW_ID, new FadeOutTransition(), new FadeInTransition()); } catch (IOException e) { createButton.setEnabled(true); joinButton.setEnabled(true); e.printStackTrace(); } } private void join(String ip) { try { createButton.setEnabled(false); joinButton.setEnabled(false); game.getNetworkManager().joinServer(ip); game.enterState(Game.CREATE_VIEW_ID, new FadeOutTransition(), new FadeInTransition()); } catch (IOException e) { createButton.setEnabled(true); joinButton.setEnabled(true); unreachableServerTimer.resetTime(); } } @Override public void enter(GameContainer container, StateBasedGame game) throws SlickException { super.enter(container, game); createButton.setEnabled(true); joinButton.setEnabled(true); manager.launchClientListening(new INetworkDiscoverListener() { @Override public void receiveServerInfos(String state, String gameType, String nbPlayer, String maxPlayer, String mapName, String ip) { ServerInfo si = new ServerInfo(); si.state = state; si.gameType = gameType; si.nbPlayer = nbPlayer; si.maxPlayer = maxPlayer; si.mapName = mapName.split("]")[1].trim(); si.ip = ip; tableModel.addServerInfo(si); } }); } @Override public void leave(GameContainer container, StateBasedGame game) throws SlickException { super.leave(container, game); manager.stopClientListening(); } @Override public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException { g.drawImage(background, 0, 0); super.render(container, game, g); int x = container.getWidth() / 2 - 370; int y = container.getHeight() / 2 - 250; g.drawImage(title, x + 290, y - 40); if (!unreachableServerTimer.isTimeComplete()) { g.setColor(Color.red); g.drawString("Server is unreachable !", x + 468, y + 466); } } @Override public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException { super.update(container, game, delta); unreachableServerTimer.update(delta); } @Override public int getID() { return Game.NETWORK_VIEW_ID; } private class TableServerModel extends AbstractTableModel { private ArrayList<ServerInfo> datas; public TableServerModel() { datas = new ArrayList<ServerInfo>(); } public void clear() { datas.clear(); fireAllChanged(); } public void addServerInfo(ServerInfo si) { datas.add(si); fireRowsInserted(datas.size() - 1, datas.size()); } @Override public Object getCell(int row, int column) { if (row < datas.size()) { if (column == 5) return datas.get(row); else return datas.get(row).getInfo(column); } return ""; } @Override public int getNumRows() { return datas.size(); } @Override public String getColumnHeaderText(int colomn) { switch (colomn) { case 0: return "State"; case 1: return "Game Type"; case 2: return "Players"; case 3: return "Map Name"; case 4: return "Ip"; case 5: return "Join"; default: return null; } } @Override public int getNumColumns() { return 6; } } private class EditFieldCellWidgetCreator implements CellWidgetCreator { private String data; public void applyTheme(ThemeInfo themeInfo) { } public String getTheme() { return "EditFieldCellRenderer"; } public Widget updateWidget(Widget existingWidget) { EditField field = (EditField) existingWidget; if (field == null) { field = new EditField(); field.setReadOnly(true); field.setText(data); } return field; } public void positionWidget(Widget widget, int x, int y, int w, int h) { // this method will size and position the ComboBox // If the widget should be centered (like a check box) then this // would be done here widget.setPosition(x, y); widget.setSize(w, h); } public void setCellData(int row, int column, Object data) { // we have to remember the cell data for the next call of // updateWidget this.data = (String) data; } public Widget getCellRenderWidget(int x, int y, int width, int height, boolean isSelected) { // this cell does not render anything itself return null; } public int getColumnSpan() { // no column spanning return 1; } public int getPreferredHeight() { // we have to inform the table about the required cell height // before // we can create the widget - so we need to get the required // height // from the theme - see applyTheme/getTheme return 20; } } private class ButtonCellWidgetCreator implements CellWidgetCreator { private ServerInfo info; public void applyTheme(ThemeInfo themeInfo) { } public String getTheme() { return "button"; } public Widget updateWidget(Widget existingWidget) { MyButton button = (MyButton) existingWidget; if (info.canJoin()) { if (button == null) { button = new MyButton("Join"); button.setIp(info.ip); button.setSize(50, 20); } } return button; } public void positionWidget(Widget widget, int x, int y, int w, int h) { // this method will size and position the ComboBox // If the widget should be centered (like a check box) then this // would be done here widget.setPosition(x, y); widget.setSize(w, h); } public void setCellData(int row, int column, Object data) { // we have to remember the cell data for the next call of // updateWidget this.info = (ServerInfo) data; } public Widget getCellRenderWidget(int x, int y, int width, int height, boolean isSelected) { // this cell does not render anything itself return null; } public int getColumnSpan() { // no column spanning return 1; } public int getPreferredHeight() { // we have to inform the table about the required cell height // before // we can create the widget - so we need to get the required // height // from the theme - see applyTheme/getTheme return 20; } } private class MyButton extends Button { private String ip; public MyButton(String title) { super(title); setTheme("button"); } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; this.addCallback(new Runnable() { @Override public void run() { join(MyButton.this.ip); } }); } } private class ServerInfo { private String state; private String gameType; private String nbPlayer; private String maxPlayer; private String mapName; private String ip; public Object getInfo(int column) { switch (column) { case 0: switch (Integer.parseInt(state)) { case ServerState.FULL: return "Full"; case ServerState.IN_GAME: return "In Game"; case ServerState.OK: return "OK"; default: break; } case 1: return GameGoal.getType(gameType); case 2: return nbPlayer + "/" + maxPlayer; case 3: return mapName; case 4: return ip; default: return null; } } public boolean canJoin() { return Integer.parseInt(state) == ServerState.OK; } } }