/* * This file is part of Spoutcraft. * * Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org/> * Spoutcraft is licensed under the GNU Lesser General Public License. * * Spoutcraft is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Spoutcraft 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.spoutcraft.client.gui.server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.yaml.snakeyaml.Yaml; import net.minecraft.src.GuiScreen; import org.spoutcraft.api.Spoutcraft; import org.spoutcraft.api.gui.Button; import org.spoutcraft.api.gui.Color; import org.spoutcraft.api.gui.GenericButton; import org.spoutcraft.api.gui.GenericLabel; import org.spoutcraft.api.gui.GenericScrollArea; import org.spoutcraft.api.gui.GenericTexture; import org.spoutcraft.api.gui.Orientation; import org.spoutcraft.api.gui.ScrollBarPolicy; import org.spoutcraft.api.gui.Texture; import org.spoutcraft.client.SpoutClient; import org.spoutcraft.client.gui.GuiSpoutScreen; import org.spoutcraft.client.gui.LinkButton; import org.spoutcraft.client.util.NetworkUtils; public class GuiServerInfo extends GuiSpoutScreen { private GenericButton buttonDone, buttonOpenBrowser, buttonRefresh, buttonAddFavorite, buttonJoin; private GenericLabel labelTitle, labelAddressLabel, labelAddress, labelMotdLabel, labelMotd, labelDescription, labelPlayersLabel, labelPlayers, labelSpoutcraftLabel, labelSpoutcraft, labelAccessLabel, labelAccess, labelMCVersionLabel, labelMCVersion, labelCategoryLabel, labelCategory; private LinkButton linkForum, linkSite; private GenericScrollArea content; private List<GenericLabel> labels = new ArrayList<GenericLabel>(); int labelWidth = 0; private GenericTexture textureIcon; private List<GalleryImage> gallery = new ArrayList<GuiServerInfo.GalleryImage>(); private GenericLabel labelGalleryImageTitle, labelGalleryImageDesc, labelGalleryTitle; private Texture textureGalleryImage; private Button buttonGalleryPrev, buttonGalleryNext; private int galleryCurrentImage = 0; static final int MAX_HEIGHT = 128; private GuiScreen back; private ServerItem item; private Thread loadThread; public GuiServerInfo(ServerItem item, GuiScreen back) { this.back = back; this.item = item; } @Override protected void createInstances() { labels.clear(); buttonDone = new GenericButton("Done"); getScreen().attachWidget("Spoutcraft", buttonDone); buttonRefresh = new GenericButton(); getScreen().attachWidget("Spoutcraft", buttonRefresh); buttonAddFavorite = new GenericButton("Add Favorite"); getScreen().attachWidget("Spoutcraft", buttonAddFavorite); buttonJoin = new GenericButton("Join"); getScreen().attachWidget("Spoutcraft", buttonJoin); content = new GenericScrollArea(); content.setScrollBarPolicy(Orientation.HORIZONTAL, ScrollBarPolicy.SHOW_NEVER); getScreen().attachWidget("Spoutcraft", content); labelTitle = new GenericLabel(item.getTitle()); getScreen().attachWidget("Spoutcraft", labelTitle); buttonOpenBrowser = new GenericButton("More Info..."); getScreen().attachWidget("Spoutcraft", buttonOpenBrowser); labelCategoryLabel = new GenericLabel("Category"); content.attachWidget("Spoutcraft", labelCategoryLabel); labels.add(labelCategoryLabel); labelCategory = new GenericLabel("..."); labelCategory.setTextColor(new Color(0xffaaaaaa)); content.attachWidget("Spoutcraft", labelCategory); labelMCVersionLabel = new GenericLabel("Minecraft Version"); content.attachWidget("Spoutcraft", labelMCVersionLabel); labels.add(labelMCVersionLabel); labelMCVersion = new GenericLabel("..."); labelMCVersion.setTextColor(new Color(0xffaaaaaa)); content.attachWidget("Spoutcraft", labelMCVersion); labelAccessLabel = new GenericLabel("Access Type"); content.attachWidget("Spoutcraft", labelAccessLabel); labels.add(labelAccessLabel); String access = "Open"; switch(item.accessType) { case ServerItem.WHITELIST: access = "Whitelist"; break; case ServerItem.GRAYLIST: access = "Graylist"; break; case ServerItem.BLACKLIST: access = "Blacklist"; break; } labelAccess = new GenericLabel(access); labelAccess.setTextColor(new Color(0xffaaaaaa)); content.attachWidget("Spoutcraft", labelAccess); labelAddress = new GenericLabel(item.getIp() + (item.getPort() != ServerItem.DEFAULT_PORT ? item.getPort() : "")); labelAddress.setTextColor(new Color(0xffaaaaaa)); content.attachWidget("Spoutcraft", labelAddress); labelAddressLabel = new GenericLabel("Address"); content.attachWidget("Spoutcraft", labelAddressLabel); labels.add(labelAddressLabel); labelMotd = new GenericLabel(item.getMotd()); content.attachWidget("Spoutcraft", labelMotd); labelMotd.setTextColor(new Color(0xffaaaaaa)); labelMotdLabel = new GenericLabel("MOTD"); content.attachWidget("Spoutcraft", labelMotdLabel); labels.add(labelMotdLabel); labelDescription = new GenericLabel("..."); content.attachWidget("Spoutcraft", labelDescription); labelDescription.setTextColor(new Color(0xffaaaaaa)); labelDescription.setWrapLines(true); labelPlayersLabel = new GenericLabel("Players"); content.attachWidget("Spoutcraft", labelPlayersLabel); labels.add(labelPlayersLabel); labelPlayers = new GenericLabel(); labelPlayers.setTextColor(new Color(0xffaaaaaa)); content.attachWidget("Spoutcraft", labelPlayers); linkForum = new LinkButton("Go to Forum", ""); getScreen().attachWidget("Spoutcraft", linkForum); linkSite = new LinkButton("Go to Website", ""); getScreen().attachWidget("Spoutcraft", linkSite); labelSpoutcraftLabel = new GenericLabel("Spoutcraft"); content.attachWidget("Spoutcraft", labelSpoutcraftLabel); labels.add(labelSpoutcraftLabel); labelSpoutcraft = new GenericLabel("..."); labelSpoutcraft.setTextColor(new Color(0xffaaaaaa)); content.attachWidget("Spoutcraft", labelSpoutcraft); textureIcon = new GenericTexture("http://cdn.spout.org/server/thumb/" + item.getDatabaseId() + ".png"); textureIcon.setFinishDelegate(new ImageUpdate()); textureIcon.setWidth(48).setHeight(48); content.attachWidget("Spoutcraft", textureIcon); for (GenericLabel lbl:labels) { labelWidth = (int) Math.max(labelWidth, lbl.getTextWidth()); } updateButtons(); refresh(); updateData(); } public boolean hasGallery() { return gallery.size() != 0; } public void setupGallery() { buttonGalleryNext = new GenericButton("->"); buttonGalleryPrev = new GenericButton("<-"); labelGalleryImageTitle = new GenericLabel(); labelGalleryImageDesc = new GenericLabel(); textureGalleryImage = new GenericTexture(""); textureGalleryImage.setFinishDelegate(new ImageUpdate()); labelGalleryTitle = new GenericLabel("Gallery"); ((GenericLabel) labelGalleryImageDesc).setWrapLines(true); content.attachWidgets("Spoutcraft", labelGalleryImageTitle, labelGalleryImageDesc, textureGalleryImage, buttonGalleryPrev, buttonGalleryNext, labelGalleryTitle); layoutWidgets(); setGalleryImage(0); } public void setGalleryImage(int n) { if (!hasGallery()) { return; } if (gallery.size() - 1 < n) { n = gallery.size() - 1; } if (n < 0) { n = 0; } galleryCurrentImage = n; GalleryImage image = gallery.get(n); labelGalleryImageTitle.setText(image.getTitle()); labelGalleryImageDesc.setText(image.getDesc()); if (labelGalleryImageDesc.getWidth() > 0) { labelGalleryImageDesc.recalculateLines(); content.updateInnerSize(); } textureGalleryImage.setUrl("http://cdn.spout.org/server/gallery/" + item.getDatabaseId() + "_" + image.getHash() + ".png"); textureGalleryImage.setFinishDelegate(new ImageUpdate()); if (n == 0) { buttonGalleryPrev.setEnabled(false); } else { buttonGalleryPrev.setEnabled(true); } if (n == gallery.size() - 1) { buttonGalleryNext.setEnabled(false); } else { buttonGalleryNext.setEnabled(true); } layoutWidgets(); } public void updateButtons() { linkForum.setEnabled(!linkForum.getUrl().isEmpty()); linkSite.setEnabled(!linkSite.getUrl().isEmpty()); boolean updating = loadThread != null; buttonRefresh.setEnabled(!updating); if (updating) { buttonRefresh.setText("Loading..."); } else { buttonRefresh.setText("Refresh"); } buttonAddFavorite.setEnabled(!SpoutClient.getInstance().getServerManager().getFavorites().containsSever(item)); if (!buttonAddFavorite.isEnabled()) { buttonAddFavorite.setTooltip("You already have this server in your favorites"); } else { buttonAddFavorite.setTooltip(""); } } @Override protected void layoutWidgets() { int w = Spoutcraft.getMinecraftFont().getTextWidth(labelTitle.getText()); int totalWidth = Math.min(width - 9, 200 * 3 + 10); int cellWidth = (totalWidth - 10)/3; int left = width / 2 - totalWidth / 2; int center = left + cellWidth + 5; int right = center + cellWidth + 5; labelTitle.setX(width / 2 - w / 2).setY(5 + 7).setWidth(w).setHeight(11); if (labelTitle.getX() + w > width - 110) { labelTitle.setX(width - 110 - w); } buttonRefresh.setX(width - 105).setY(5).setWidth(100).setHeight(20); content.setX(0).setY(5 + 7 + 11 + 5).setWidth(width).setHeight(height - 55 - (5 + 7 + 11 + 5)); int top = 5; textureIcon.setX(5).setY(top); updateImageWidth(textureIcon, cellWidth, MAX_HEIGHT); int labelLeft = (int) (10 + textureIcon.getWidth()); int valueLeft = labelLeft + 5 + labelWidth; top += 5; labelAddressLabel.setX(labelLeft).setY(top).setWidth(width - 10).setHeight(11); labelAddress.setX(valueLeft).setY(top).setWidth(width - valueLeft - 5).setHeight(11); top += 16; labelMotdLabel.setX(labelLeft).setY(top).setWidth(width - 10).setHeight(11); labelMotd.setX(valueLeft).setY(top).setWidth(width - valueLeft - 5).setHeight(11); labelMotd.setWrapLines(true); labelMotd.recalculateLines(); if (labelMotd.getLines().length > 1) { top += 10; } top += 16; labelPlayersLabel.setX(labelLeft).setY(top).setWidth(width - 10).setHeight(11); labelPlayers.setX(valueLeft).setY(top).setWidth(width - valueLeft - 5).setHeight(11); top += 16; labelSpoutcraftLabel.setX(labelLeft).setY(top).setWidth(width - 10).setHeight(11); labelSpoutcraft.setX(valueLeft).setY(top).setWidth(width - valueLeft - 5).setHeight(11); top += 16; labelAccessLabel.setX(labelLeft).setY(top).setWidth(width - 10).setHeight(11); labelAccess.setX(valueLeft).setY(top).setWidth(width - valueLeft - 5).setHeight(11); top += 16; labelMCVersionLabel.setX(labelLeft).setY(top).setWidth(width - 10).setHeight(11); labelMCVersion.setX(valueLeft).setY(top).setWidth(width - valueLeft - 5).setHeight(11); top += 16; labelCategoryLabel.setX(labelLeft).setY(top).setWidth(width - 10).setHeight(11); labelCategory.setX(valueLeft).setY(top).setWidth(width - valueLeft - 5).setHeight(11); top += 16; labelLeft = 5; valueLeft = labelLeft + labelWidth + 5; top = (int) Math.max(top, 5 + textureIcon.getHeight() + 5); labelDescription.setX(5).setY(top).setWidth(totalWidth).setHeight(11); labelDescription.recalculateLines(); top += labelDescription.getHeight() + 5; if (hasGallery()) { labelGalleryTitle.setGeometry(labelLeft, top, totalWidth, 10); top += 15; textureGalleryImage.setGeometry(labelLeft, top, totalWidth, 100); updateImageWidth(textureGalleryImage, totalWidth, (int) (content.getHeight() - 50)); w = (int) textureGalleryImage.getWidth(); textureGalleryImage.setX(totalWidth / 2 - w / 2); top += textureGalleryImage.getHeight() + 5; buttonGalleryPrev.setGeometry(labelLeft, top, 20, 20); buttonGalleryNext.setGeometry(labelLeft + totalWidth - 20, top, 20, 20); w = Spoutcraft.getRenderDelegate().getMinecraftFont().getTextWidth(labelGalleryImageTitle.getText()); labelGalleryImageTitle.setGeometry(totalWidth / 2 - w / 2, top + 5, w, 10); top += 25; labelGalleryImageDesc.setGeometry(labelLeft, top, totalWidth, 11); ((GenericLabel) labelGalleryImageDesc).recalculateLines(); top += labelGalleryImageDesc.getHeight() + 5; } linkForum.setX(left).setY(height - 50).setWidth(cellWidth).setHeight(20); linkSite.setX(center).setY(height - 50).setWidth(cellWidth).setHeight(20); buttonOpenBrowser.setX(right).setY(height - 50).setHeight(20).setWidth(cellWidth); buttonJoin.setX(left).setY(height - 25).setHeight(20).setWidth(cellWidth); buttonAddFavorite.setX(center).setY(height - 25).setHeight(20).setWidth(cellWidth); buttonDone.setX(right).setY(height - 25).setHeight(20).setWidth(cellWidth); content.updateInnerSize(); } @Override protected void buttonClicked(Button btn) { if (btn == buttonDone) { mc.displayGuiScreen(back); } if (btn == buttonOpenBrowser) { NetworkUtils.openInBrowser("http://servers.spout.org/info/" + item.getDatabaseId()); } if (btn == buttonRefresh) { refresh(); } if (btn == buttonAddFavorite) { SpoutClient.getInstance().getServerManager().getFavorites().addServer(item); SpoutClient.getInstance().getServerManager().getFavorites().save(); updateButtons(); } if (btn == buttonJoin) { item.onClick(-1, -1, true); } if (btn == buttonGalleryNext) { setGalleryImage(galleryCurrentImage + 1); } if (btn == buttonGalleryPrev) { setGalleryImage(galleryCurrentImage - 1); } } private void refresh() { loadThread = new Thread() { public void run() { try { URL url = new URL("http://servers.spout.org/api2.php?id=" + item.getDatabaseId()); BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); Yaml yaml = new Yaml(); ArrayList<Map<String, Object>> list = (ArrayList<Map<String, Object>>) yaml.load(reader); reader.close(); parseYaml(list); } catch(IOException e) { e.printStackTrace(); parseYaml(null); } } }; loadThread.start(); updateButtons(); } protected void parseYaml(ArrayList<Map<String, Object>> list) { loadThread = null; updateButtons(); try { if (list != null && list.size() > 0) { Map<String, Object> i = list.get(1); labelDescription.setText(URLDecoder.decode((String) i.get("longdescription"), "UTF-8")); linkSite.setUrl(URLDecoder.decode((String) i.get("site"), "UTF-8")); linkForum.setUrl(URLDecoder.decode((String) i.get("forumurl"), "UTF-8")); boolean spoutcraft = i.get("spoutcraft").equals("1"); labelSpoutcraft.setText(spoutcraft ? "Required" : "Not Required"); labelMCVersion.setText(URLDecoder.decode((String) i.get("mcversion"), "UTF-8")); labelCategory.setText(URLDecoder.decode((String) i.get("category"), "UTF-8")); if (i.containsKey("gallery")) { System.out.println("Has gallery"); List<Map<String, String>> gMap = (List<Map<String, String>>) i.get("gallery"); gallery.clear(); for (Map<String, String> image:gMap) { GalleryImage img = new GalleryImage(image.get("picid"), URLDecoder.decode((String) image.get("title"), "UTF-8"), URLDecoder.decode((String) image.get("desc"), "UTF-8")); gallery.add(img); } if (buttonGalleryNext == null) { setupGallery(); } else { setGalleryImage(0); } } } } catch(UnsupportedEncodingException e) {} layoutWidgets(); updateButtons(); } @Override public void updateScreen() { if (loadThread != null) { Color color = new Color(0, 1f, 0); double darkness = 0; long t = System.currentTimeMillis() % 1000; darkness = Math.cos(t * 2 * Math.PI / 1000) * 0.2 + 0.2; color.setGreen(1f - (float)darkness); buttonRefresh.setDisabledColor(color); } super.updateScreen(); } public void updateData() { labelMotd.setText(item.getMotd()); labelPlayers.setText(item.getPlayers() + " / " + item.getMaxPlayers()); } private class ImageUpdate implements Runnable { public void run() { layoutWidgets(); } } public void updateImageWidth(Texture texture, int maxWidth, int maxHeight) { int imgwidth, imgheight; imgwidth = texture.getOriginalWidth(); imgheight = texture.getOriginalHeight(); double ratio = (double) imgwidth / (double) imgheight; if (imgheight > maxHeight) { imgheight = maxHeight; imgwidth = (int) ((double) imgheight * ratio); } if (imgwidth > maxWidth) { imgwidth = maxWidth; imgheight = (int) ((double) imgwidth * (1.0/ratio)); } texture.setWidth(imgwidth).setHeight(imgheight); } protected class GalleryImage { private String hash, title, desc; public GalleryImage(String hash, String title, String desc) { this.hash = hash; this.title = title; this.desc = desc; } public String getHash() { return hash; } public void setHash(String hash) { this.hash = hash; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } } }