398 lines
13 KiB
Java
398 lines
13 KiB
Java
package com.mojang.realmsclient.dto;
|
|
|
|
import com.google.common.collect.ComparisonChain;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.gson.JsonArray;
|
|
import com.google.gson.JsonElement;
|
|
import com.google.gson.JsonObject;
|
|
import com.google.gson.JsonParser;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.realmsclient.util.JsonUtils;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.UUID;
|
|
import java.util.Map.Entry;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.client.multiplayer.ServerData;
|
|
import net.minecraft.client.multiplayer.ServerData.Type;
|
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class RealmsServer extends ValueObject {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final int NO_VALUE = -1;
|
|
public long id;
|
|
@Nullable
|
|
public String remoteSubscriptionId;
|
|
@Nullable
|
|
public String name;
|
|
public String motd;
|
|
public RealmsServer.State state;
|
|
@Nullable
|
|
public String owner;
|
|
public UUID ownerUUID = Util.NIL_UUID;
|
|
public List<PlayerInfo> players;
|
|
public Map<Integer, RealmsWorldOptions> slots;
|
|
public boolean expired;
|
|
public boolean expiredTrial;
|
|
public int daysLeft;
|
|
public RealmsServer.WorldType worldType;
|
|
public boolean isHardcore;
|
|
public int gameMode;
|
|
public int activeSlot;
|
|
@Nullable
|
|
public String minigameName;
|
|
public int minigameId;
|
|
@Nullable
|
|
public String minigameImage;
|
|
public long parentRealmId = -1L;
|
|
@Nullable
|
|
public String parentWorldName;
|
|
public String activeVersion = "";
|
|
public RealmsServer.Compatibility compatibility = RealmsServer.Compatibility.UNVERIFIABLE;
|
|
|
|
public String getDescription() {
|
|
return this.motd;
|
|
}
|
|
|
|
@Nullable
|
|
public String getName() {
|
|
return this.name;
|
|
}
|
|
|
|
@Nullable
|
|
public String getMinigameName() {
|
|
return this.minigameName;
|
|
}
|
|
|
|
public void setName(String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
public void setDescription(String motd) {
|
|
this.motd = motd;
|
|
}
|
|
|
|
public static RealmsServer parse(JsonObject json) {
|
|
RealmsServer realmsServer = new RealmsServer();
|
|
|
|
try {
|
|
realmsServer.id = JsonUtils.getLongOr("id", json, -1L);
|
|
realmsServer.remoteSubscriptionId = JsonUtils.getStringOr("remoteSubscriptionId", json, null);
|
|
realmsServer.name = JsonUtils.getStringOr("name", json, null);
|
|
realmsServer.motd = JsonUtils.getStringOr("motd", json, "");
|
|
realmsServer.state = getState(JsonUtils.getStringOr("state", json, RealmsServer.State.CLOSED.name()));
|
|
realmsServer.owner = JsonUtils.getStringOr("owner", json, null);
|
|
if (json.get("players") != null && json.get("players").isJsonArray()) {
|
|
realmsServer.players = parseInvited(json.get("players").getAsJsonArray());
|
|
sortInvited(realmsServer);
|
|
} else {
|
|
realmsServer.players = Lists.<PlayerInfo>newArrayList();
|
|
}
|
|
|
|
realmsServer.daysLeft = JsonUtils.getIntOr("daysLeft", json, 0);
|
|
realmsServer.expired = JsonUtils.getBooleanOr("expired", json, false);
|
|
realmsServer.expiredTrial = JsonUtils.getBooleanOr("expiredTrial", json, false);
|
|
realmsServer.worldType = getWorldType(JsonUtils.getStringOr("worldType", json, RealmsServer.WorldType.NORMAL.name()));
|
|
realmsServer.isHardcore = JsonUtils.getBooleanOr("isHardcore", json, false);
|
|
realmsServer.gameMode = JsonUtils.getIntOr("gameMode", json, -1);
|
|
realmsServer.ownerUUID = JsonUtils.getUuidOr("ownerUUID", json, Util.NIL_UUID);
|
|
if (json.get("slots") != null && json.get("slots").isJsonArray()) {
|
|
realmsServer.slots = parseSlots(json.get("slots").getAsJsonArray());
|
|
} else {
|
|
realmsServer.slots = createEmptySlots();
|
|
}
|
|
|
|
realmsServer.minigameName = JsonUtils.getStringOr("minigameName", json, null);
|
|
realmsServer.activeSlot = JsonUtils.getIntOr("activeSlot", json, -1);
|
|
realmsServer.minigameId = JsonUtils.getIntOr("minigameId", json, -1);
|
|
realmsServer.minigameImage = JsonUtils.getStringOr("minigameImage", json, null);
|
|
realmsServer.parentRealmId = JsonUtils.getLongOr("parentWorldId", json, -1L);
|
|
realmsServer.parentWorldName = JsonUtils.getStringOr("parentWorldName", json, null);
|
|
realmsServer.activeVersion = JsonUtils.getStringOr("activeVersion", json, "");
|
|
realmsServer.compatibility = getCompatibility(JsonUtils.getStringOr("compatibility", json, RealmsServer.Compatibility.UNVERIFIABLE.name()));
|
|
} catch (Exception var3) {
|
|
LOGGER.error("Could not parse McoServer: {}", var3.getMessage());
|
|
}
|
|
|
|
return realmsServer;
|
|
}
|
|
|
|
private static void sortInvited(RealmsServer realmsServer) {
|
|
realmsServer.players
|
|
.sort(
|
|
(playerInfo, playerInfo2) -> ComparisonChain.start()
|
|
.compareFalseFirst(playerInfo2.getAccepted(), playerInfo.getAccepted())
|
|
.compare(playerInfo.getName().toLowerCase(Locale.ROOT), playerInfo2.getName().toLowerCase(Locale.ROOT))
|
|
.result()
|
|
);
|
|
}
|
|
|
|
private static List<PlayerInfo> parseInvited(JsonArray jsonArray) {
|
|
List<PlayerInfo> list = Lists.<PlayerInfo>newArrayList();
|
|
|
|
for (JsonElement jsonElement : jsonArray) {
|
|
try {
|
|
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
|
PlayerInfo playerInfo = new PlayerInfo();
|
|
playerInfo.setName(JsonUtils.getStringOr("name", jsonObject, null));
|
|
playerInfo.setUuid(JsonUtils.getUuidOr("uuid", jsonObject, Util.NIL_UUID));
|
|
playerInfo.setOperator(JsonUtils.getBooleanOr("operator", jsonObject, false));
|
|
playerInfo.setAccepted(JsonUtils.getBooleanOr("accepted", jsonObject, false));
|
|
playerInfo.setOnline(JsonUtils.getBooleanOr("online", jsonObject, false));
|
|
list.add(playerInfo);
|
|
} catch (Exception var6) {
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
private static Map<Integer, RealmsWorldOptions> parseSlots(JsonArray jsonArray) {
|
|
Map<Integer, RealmsWorldOptions> map = Maps.<Integer, RealmsWorldOptions>newHashMap();
|
|
|
|
for (JsonElement jsonElement : jsonArray) {
|
|
try {
|
|
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
|
JsonElement jsonElement2 = JsonParser.parseString(jsonObject.get("options").getAsString());
|
|
RealmsSettings realmsSettings = parseSettings(jsonObject.get("settings"));
|
|
RealmsWorldOptions realmsWorldOptions;
|
|
if (jsonElement2 == null) {
|
|
realmsWorldOptions = RealmsWorldOptions.createDefaults();
|
|
} else {
|
|
realmsWorldOptions = RealmsWorldOptions.parse(jsonElement2.getAsJsonObject(), realmsSettings);
|
|
}
|
|
|
|
int i = JsonUtils.getIntOr("slotId", jsonObject, -1);
|
|
map.put(i, realmsWorldOptions);
|
|
} catch (Exception var9) {
|
|
}
|
|
}
|
|
|
|
for (int j = 1; j <= 3; j++) {
|
|
if (!map.containsKey(j)) {
|
|
map.put(j, RealmsWorldOptions.createEmptyDefaults());
|
|
}
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
private static RealmsSettings parseSettings(JsonElement json) {
|
|
boolean bl = false;
|
|
if (json.isJsonArray()) {
|
|
for (JsonElement jsonElement : json.getAsJsonArray()) {
|
|
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
|
bl = readBoolean(jsonObject, "hardcore", bl);
|
|
}
|
|
}
|
|
|
|
return new RealmsSettings(bl);
|
|
}
|
|
|
|
private static boolean readBoolean(JsonObject json, String memberName, boolean defaultValue) {
|
|
String string = JsonUtils.getStringOr("name", json, null);
|
|
return string != null && string.equals(memberName) ? JsonUtils.getBooleanOr("value", json, defaultValue) : defaultValue;
|
|
}
|
|
|
|
private static Map<Integer, RealmsWorldOptions> createEmptySlots() {
|
|
Map<Integer, RealmsWorldOptions> map = Maps.<Integer, RealmsWorldOptions>newHashMap();
|
|
map.put(1, RealmsWorldOptions.createEmptyDefaults());
|
|
map.put(2, RealmsWorldOptions.createEmptyDefaults());
|
|
map.put(3, RealmsWorldOptions.createEmptyDefaults());
|
|
return map;
|
|
}
|
|
|
|
public static RealmsServer parse(String json) {
|
|
try {
|
|
return parse(new JsonParser().parse(json).getAsJsonObject());
|
|
} catch (Exception var2) {
|
|
LOGGER.error("Could not parse McoServer: {}", var2.getMessage());
|
|
return new RealmsServer();
|
|
}
|
|
}
|
|
|
|
private static RealmsServer.State getState(String name) {
|
|
try {
|
|
return RealmsServer.State.valueOf(name);
|
|
} catch (Exception var2) {
|
|
return RealmsServer.State.CLOSED;
|
|
}
|
|
}
|
|
|
|
private static RealmsServer.WorldType getWorldType(String name) {
|
|
try {
|
|
return RealmsServer.WorldType.valueOf(name);
|
|
} catch (Exception var2) {
|
|
return RealmsServer.WorldType.NORMAL;
|
|
}
|
|
}
|
|
|
|
public static RealmsServer.Compatibility getCompatibility(@Nullable String id) {
|
|
try {
|
|
return RealmsServer.Compatibility.valueOf(id);
|
|
} catch (Exception var2) {
|
|
return RealmsServer.Compatibility.UNVERIFIABLE;
|
|
}
|
|
}
|
|
|
|
public boolean isCompatible() {
|
|
return this.compatibility.isCompatible();
|
|
}
|
|
|
|
public boolean needsUpgrade() {
|
|
return this.compatibility.needsUpgrade();
|
|
}
|
|
|
|
public boolean needsDowngrade() {
|
|
return this.compatibility.needsDowngrade();
|
|
}
|
|
|
|
public int hashCode() {
|
|
return Objects.hash(new Object[]{this.id, this.name, this.motd, this.state, this.owner, this.expired});
|
|
}
|
|
|
|
public boolean equals(Object object) {
|
|
if (object == null) {
|
|
return false;
|
|
} else if (object == this) {
|
|
return true;
|
|
} else if (object.getClass() != this.getClass()) {
|
|
return false;
|
|
} else {
|
|
RealmsServer realmsServer = (RealmsServer)object;
|
|
return new EqualsBuilder()
|
|
.append(this.id, realmsServer.id)
|
|
.append(this.name, realmsServer.name)
|
|
.append(this.motd, realmsServer.motd)
|
|
.append(this.state, realmsServer.state)
|
|
.append(this.owner, realmsServer.owner)
|
|
.append(this.expired, realmsServer.expired)
|
|
.append(this.worldType, this.worldType)
|
|
.isEquals();
|
|
}
|
|
}
|
|
|
|
public RealmsServer clone() {
|
|
RealmsServer realmsServer = new RealmsServer();
|
|
realmsServer.id = this.id;
|
|
realmsServer.remoteSubscriptionId = this.remoteSubscriptionId;
|
|
realmsServer.name = this.name;
|
|
realmsServer.motd = this.motd;
|
|
realmsServer.state = this.state;
|
|
realmsServer.owner = this.owner;
|
|
realmsServer.players = this.players;
|
|
realmsServer.slots = this.cloneSlots(this.slots);
|
|
realmsServer.expired = this.expired;
|
|
realmsServer.expiredTrial = this.expiredTrial;
|
|
realmsServer.daysLeft = this.daysLeft;
|
|
realmsServer.worldType = this.worldType;
|
|
realmsServer.isHardcore = this.isHardcore;
|
|
realmsServer.gameMode = this.gameMode;
|
|
realmsServer.ownerUUID = this.ownerUUID;
|
|
realmsServer.minigameName = this.minigameName;
|
|
realmsServer.activeSlot = this.activeSlot;
|
|
realmsServer.minigameId = this.minigameId;
|
|
realmsServer.minigameImage = this.minigameImage;
|
|
realmsServer.parentWorldName = this.parentWorldName;
|
|
realmsServer.parentRealmId = this.parentRealmId;
|
|
realmsServer.activeVersion = this.activeVersion;
|
|
realmsServer.compatibility = this.compatibility;
|
|
return realmsServer;
|
|
}
|
|
|
|
public Map<Integer, RealmsWorldOptions> cloneSlots(Map<Integer, RealmsWorldOptions> slots) {
|
|
Map<Integer, RealmsWorldOptions> map = Maps.<Integer, RealmsWorldOptions>newHashMap();
|
|
|
|
for (Entry<Integer, RealmsWorldOptions> entry : slots.entrySet()) {
|
|
map.put((Integer)entry.getKey(), ((RealmsWorldOptions)entry.getValue()).clone());
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
public boolean isSnapshotRealm() {
|
|
return this.parentRealmId != -1L;
|
|
}
|
|
|
|
public boolean isMinigameActive() {
|
|
return this.worldType == RealmsServer.WorldType.MINIGAME;
|
|
}
|
|
|
|
public String getWorldName(int slot) {
|
|
return this.name == null
|
|
? ((RealmsWorldOptions)this.slots.get(slot)).getSlotName(slot)
|
|
: this.name + " (" + ((RealmsWorldOptions)this.slots.get(slot)).getSlotName(slot) + ")";
|
|
}
|
|
|
|
public ServerData toServerData(String ip) {
|
|
return new ServerData((String)Objects.requireNonNullElse(this.name, "unknown server"), ip, Type.REALM);
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static enum Compatibility {
|
|
UNVERIFIABLE,
|
|
INCOMPATIBLE,
|
|
RELEASE_TYPE_INCOMPATIBLE,
|
|
NEEDS_DOWNGRADE,
|
|
NEEDS_UPGRADE,
|
|
COMPATIBLE;
|
|
|
|
public boolean isCompatible() {
|
|
return this == COMPATIBLE;
|
|
}
|
|
|
|
public boolean needsUpgrade() {
|
|
return this == NEEDS_UPGRADE;
|
|
}
|
|
|
|
public boolean needsDowngrade() {
|
|
return this == NEEDS_DOWNGRADE;
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class McoServerComparator implements Comparator<RealmsServer> {
|
|
private final String refOwner;
|
|
|
|
public McoServerComparator(String refOwner) {
|
|
this.refOwner = refOwner;
|
|
}
|
|
|
|
public int compare(RealmsServer first, RealmsServer second) {
|
|
return ComparisonChain.start()
|
|
.compareTrueFirst(first.isSnapshotRealm(), second.isSnapshotRealm())
|
|
.compareTrueFirst(first.state == RealmsServer.State.UNINITIALIZED, second.state == RealmsServer.State.UNINITIALIZED)
|
|
.compareTrueFirst(first.expiredTrial, second.expiredTrial)
|
|
.compareTrueFirst(Objects.equals(first.owner, this.refOwner), Objects.equals(second.owner, this.refOwner))
|
|
.compareFalseFirst(first.expired, second.expired)
|
|
.compareTrueFirst(first.state == RealmsServer.State.OPEN, second.state == RealmsServer.State.OPEN)
|
|
.compare(first.id, second.id)
|
|
.result();
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static enum State {
|
|
CLOSED,
|
|
OPEN,
|
|
UNINITIALIZED;
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static enum WorldType {
|
|
NORMAL,
|
|
MINIGAME,
|
|
ADVENTUREMAP,
|
|
EXPERIENCE,
|
|
INSPIRATION;
|
|
}
|
|
}
|