package net.glowstone.net.handler.status;
import com.flowpowered.network.MessageHandler;
import net.glowstone.EventFactory;
import net.glowstone.GlowServer;
import net.glowstone.net.GlowSession;
import net.glowstone.net.message.status.StatusRequestMessage;
import net.glowstone.net.message.status.StatusResponseMessage;
import net.glowstone.util.GlowServerIcon;
import org.bukkit.entity.Player;
import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.util.CachedServerIcon;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public final class StatusRequestHandler implements MessageHandler<GlowSession, StatusRequestMessage> {
@Override
@SuppressWarnings("unchecked")
public void handle(GlowSession session, StatusRequestMessage message) {
// create and call the event
GlowServer server = session.getServer();
int online = server.getOnlinePlayers().size();
InetAddress address = session.getAddress().getAddress();
StatusEvent event = new StatusEvent(address, server.getMotd(), online, server.getMaxPlayers());
event.players = new ArrayList<>(server.getOnlinePlayers());
event.icon = server.getServerIcon();
event.serverType = server.getServerType();
event.clientModsAllowed = server.getAllowClientMods();
EventFactory.callEvent(event);
// build the json
JSONObject json = new JSONObject();
JSONObject version = new JSONObject();
version.put("name", GlowServer.GAME_VERSION);
int protocolVersion = GlowServer.PROTOCOL_VERSION;
version.put("protocol", protocolVersion);
json.put("version", version);
JSONObject players = new JSONObject();
players.put("max", event.getMaxPlayers());
players.put("online", online);
if (!event.players.isEmpty()) {
event.players = event.players.subList(0, Math.min(event.players.size(), server.getPlayerSampleCount()));
Collections.shuffle(event.players);
JSONArray playersSample = new JSONArray();
for (Player player : event.players) {
JSONObject p = new JSONObject();
p.put("name", player.getName());
p.put("id", player.getUniqueId().toString());
playersSample.add(p);
}
players.put("sample", playersSample);
}
json.put("players", players);
JSONObject description = new JSONObject();
description.put("text", event.getMotd());
json.put("description", description);
if (event.icon.getData() != null) {
json.put("favicon", event.icon.getData());
}
// Mod list must be included but can be empty
// TODO: support adding GS-ported Forge server-side mods?
JSONArray modList = new JSONArray();
JSONObject modinfo = new JSONObject();
modinfo.put("type", event.serverType);
modinfo.put("modList", modList);
if (!event.clientModsAllowed) {
modinfo.put("clientModsAllowed", false);
}
json.put("modinfo", modinfo);
// send it off
session.send(new StatusResponseMessage(json));
}
private static class StatusEvent extends ServerListPingEvent {
private GlowServerIcon icon;
private List<Player> players;
private String serverType; // VANILLA, BUKKIT, or FML
private boolean clientModsAllowed;
private StatusEvent(InetAddress address, String motd, int numPlayers, int maxPlayers) {
super(address, motd, numPlayers, maxPlayers);
}
@Override
public void setServerIcon(CachedServerIcon icon) throws IllegalArgumentException, UnsupportedOperationException {
if (!(icon instanceof GlowServerIcon)) {
throw new IllegalArgumentException("Icon not provided by this implementation");
}
this.icon = (GlowServerIcon) icon;
}
@Override
public Iterator<Player> iterator() {
return players.iterator();
}
}
}