Revert "Revert "Implement Favicon API""

This reverts commit 13decac4b9.
This commit is contained in:
Jonas Konrad 2014-04-15 11:54:54 +02:00 committed by md_5
parent 13decac4b9
commit e2eba52162
5 changed files with 159 additions and 35 deletions

View File

@ -0,0 +1,106 @@
package net.md_5.bungee.api;
import com.google.common.io.BaseEncoding;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* Favicon shown in the server list.
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class Favicon
{
private static final TypeAdapter<Favicon> FAVICON_TYPE_ADAPTER = new TypeAdapter<Favicon>()
{
@Override
public void write(JsonWriter out, Favicon value) throws IOException
{
TypeAdapters.STRING.write( out, value.getEncoded() );
}
@Override
public Favicon read(JsonReader in) throws IOException
{
return create( TypeAdapters.STRING.read( in ) );
}
};
public static TypeAdapter<Favicon> getFaviconTypeAdapter()
{
return FAVICON_TYPE_ADAPTER;
}
/**
* The base64 encoded favicon, including MIME header.
*/
@Getter
private final String encoded;
/**
* Creates a favicon from an image.
*
* @param image the image to create on
* @return the created favicon instance
* @throws IllegalArgumentException if the favicon is larger than
* {@link Short#MAX_VALUE} or not of dimensions 64x64 pixels.
*/
public static Favicon create(BufferedImage image)
{
// check size
if ( image.getWidth() != 64 || image.getHeight() != 64 )
{
throw new IllegalArgumentException( "Server icon must be exactly 64x64 pixels" );
}
// dump image PNG
byte[] imageBytes;
try
{
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write( image, "PNG", stream );
imageBytes = stream.toByteArray();
} catch ( IOException e )
{
// ByteArrayOutputStream should never throw this
throw new AssertionError( e );
}
// encode with header
String encoded = "data:image/png;base64," + BaseEncoding.base64().encode( imageBytes );
// check encoded image size
if ( encoded.length() > Short.MAX_VALUE )
{
throw new IllegalArgumentException( "Favicon file too large for server to process" );
}
// create
return new Favicon( encoded );
}
/**
* Creates a Favicon from an encoded PNG.
*
* @param encodedString a base64 mime encoded PNG string
* @return the created favicon
* @deprecated Use #create(java.awt.image.BufferedImage) instead
*/
@Deprecated
public static Favicon create(String encodedString)
{
return new Favicon( encodedString );
}
}

View File

@ -1,12 +1,11 @@
package net.md_5.bungee.api; package net.md_5.bungee.api;
import java.util.UUID;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.md_5.bungee.Util; import net.md_5.bungee.Util;
import java.util.UUID;
/** /**
* Represents the standard list data returned by opening a server in the * Represents the standard list data returned by opening a server in the
* Minecraft client server list, or hitting it with a packet 0xFE. * Minecraft client server list, or hitting it with a packet 0xFE.
@ -73,5 +72,33 @@ public class ServerPing
} }
} }
private String description; private String description;
private String favicon; private Favicon favicon;
@Deprecated
public ServerPing(Protocol version, Players players, String description, String favicon)
{
this( version, players, description, Favicon.create( favicon ) );
}
@Deprecated
public String getFavicon()
{
return getFaviconObject() == null ? null : getFaviconObject().getEncoded();
}
public Favicon getFaviconObject()
{
return this.favicon;
}
@Deprecated
public void setFavicon(String favicon)
{
setFavicon( favicon == null ? null : Favicon.create( favicon ) );
}
public void setFavicon(Favicon favicon)
{
this.favicon = favicon;
}
} }

View File

@ -1,6 +1,7 @@
package net.md_5.bungee; package net.md_5.bungee;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.module.ModuleManager; import net.md_5.bungee.module.ModuleManager;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
@ -126,9 +127,11 @@ public class BungeeCord extends ProxyServer
@Getter @Getter
private final Logger logger; private final Logger logger;
public final Gson gson = new GsonBuilder() public final Gson gson = new GsonBuilder()
.registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer( 5 ) ).create(); .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer( 5 ) )
.registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create();
public final Gson gsonLegacy = new GsonBuilder() public final Gson gsonLegacy = new GsonBuilder()
.registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer( 4 ) ).create(); .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer( 4 ) )
.registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create();
@Getter @Getter
private ConnectionThrottle connectionThrottle; private ConnectionThrottle connectionThrottle;
private final ModuleManager moduleManager = new ModuleManager(); private final ModuleManager moduleManager = new ModuleManager();

View File

@ -1,12 +1,7 @@
package net.md_5.bungee.conf; package net.md_5.bungee.conf;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.io.BaseEncoding;
import com.google.common.io.Files;
import gnu.trove.map.TMap; import gnu.trove.map.TMap;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
@ -16,6 +11,7 @@ import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import lombok.Getter; import lombok.Getter;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ProxyConfig; import net.md_5.bungee.api.ProxyConfig;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ConfigurationAdapter; import net.md_5.bungee.api.config.ConfigurationAdapter;
@ -55,7 +51,7 @@ public class Configuration implements ProxyConfig
private Collection<String> disabledCommands; private Collection<String> disabledCommands;
private int throttle = 4000; private int throttle = 4000;
private boolean ipFoward; private boolean ipFoward;
public String favicon; private Favicon favicon;
public void load() public void load()
{ {
@ -67,28 +63,8 @@ public class Configuration implements ProxyConfig
{ {
try try
{ {
BufferedImage image = ImageIO.read( fav ); favicon = Favicon.create( ImageIO.read( fav ) );
if ( image != null ) } catch ( IOException | IllegalArgumentException ex )
{
if ( image.getHeight() == 64 && image.getWidth() == 64 )
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ImageIO.write( image, "png", bytes );
favicon = "data:image/png;base64," + BaseEncoding.base64().encode( bytes.toByteArray() );
if ( favicon.length() > Short.MAX_VALUE )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Favicon file too large for server to process" );
favicon = null;
}
} else
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Server icon must be exactly 64x64 pixels" );
}
} else
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load server icon for unknown reason. Please double check its format." );
}
} catch ( IOException ex )
{ {
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load server icon", ex ); ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load server icon", ex );
} }
@ -143,4 +119,15 @@ public class Configuration implements ProxyConfig
} }
} }
} }
@Deprecated
public String getFavicon()
{
return getFaviconObject().getEncoded();
}
public Favicon getFaviconObject()
{
return favicon;
}
} }

View File

@ -18,6 +18,7 @@ import lombok.RequiredArgsConstructor;
import net.md_5.bungee.*; import net.md_5.bungee.*;
import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
@ -130,7 +131,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
public void handle(LegacyPing ping) throws Exception public void handle(LegacyPing ping) throws Exception
{ {
ServerPing legacy = new ServerPing( new ServerPing.Protocol( bungee.getGameVersion(), bungee.getProtocolVersion() ), ServerPing legacy = new ServerPing( new ServerPing.Protocol( bungee.getGameVersion(), bungee.getProtocolVersion() ),
new ServerPing.Players( listener.getMaxPlayers(), bungee.getOnlineCount(), null ), listener.getMotd(), null ); new ServerPing.Players( listener.getMaxPlayers(), bungee.getOnlineCount(), null ), listener.getMotd(), (Favicon) null );
legacy = bungee.getPluginManager().callEvent( new ProxyPingEvent( this, legacy ) ).getResponse(); legacy = bungee.getPluginManager().callEvent( new ProxyPingEvent( this, legacy ) ).getResponse();
String kickMessage = ChatColor.DARK_BLUE String kickMessage = ChatColor.DARK_BLUE
@ -179,7 +180,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
pingBack.done( new ServerPing( pingBack.done( new ServerPing(
new ServerPing.Protocol( bungee.getGameVersion(), protocol ), new ServerPing.Protocol( bungee.getGameVersion(), protocol ),
new ServerPing.Players( listener.getMaxPlayers(), bungee.getOnlineCount(), null ), new ServerPing.Players( listener.getMaxPlayers(), bungee.getOnlineCount(), null ),
motd, BungeeCord.getInstance().config.favicon ), motd, BungeeCord.getInstance().config.getFaviconObject() ),
null ); null );
} }