356 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			356 lines
		
	
	
	
		
			10 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.annotations.JsonAdapter;
 | |
| import com.google.gson.annotations.SerializedName;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import com.mojang.util.UUIDTypeAdapter;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Comparator;
 | |
| import java.util.HashMap;
 | |
| 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.Minecraft;
 | |
| import net.minecraft.client.multiplayer.ServerData;
 | |
| import net.minecraft.network.chat.Component;
 | |
| import org.apache.commons.lang3.builder.EqualsBuilder;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| public class RealmsServer extends ValueObject implements ReflectionBasedSerialization {
 | |
| 	private static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	private static final int NO_VALUE = -1;
 | |
| 	public static final Component WORLD_CLOSED_COMPONENT = Component.translatable("mco.play.button.realm.closed");
 | |
| 	@SerializedName("id")
 | |
| 	public long id = -1L;
 | |
| 	@Nullable
 | |
| 	@SerializedName("remoteSubscriptionId")
 | |
| 	public String remoteSubscriptionId;
 | |
| 	@Nullable
 | |
| 	@SerializedName("name")
 | |
| 	public String name;
 | |
| 	@SerializedName("motd")
 | |
| 	public String motd = "";
 | |
| 	@SerializedName("state")
 | |
| 	public RealmsServer.State state = RealmsServer.State.CLOSED;
 | |
| 	@Nullable
 | |
| 	@SerializedName("owner")
 | |
| 	public String owner;
 | |
| 	@SerializedName("ownerUUID")
 | |
| 	@JsonAdapter(UUIDTypeAdapter.class)
 | |
| 	public UUID ownerUUID = Util.NIL_UUID;
 | |
| 	@SerializedName("players")
 | |
| 	public List<PlayerInfo> players = Lists.<PlayerInfo>newArrayList();
 | |
| 	@SerializedName("slots")
 | |
| 	private List<RealmsSlot> slotList = createEmptySlots();
 | |
| 	@Exclude
 | |
| 	public Map<Integer, RealmsSlot> slots = new HashMap();
 | |
| 	@SerializedName("expired")
 | |
| 	public boolean expired;
 | |
| 	@SerializedName("expiredTrial")
 | |
| 	public boolean expiredTrial = false;
 | |
| 	@SerializedName("daysLeft")
 | |
| 	public int daysLeft;
 | |
| 	@SerializedName("worldType")
 | |
| 	public RealmsServer.WorldType worldType = RealmsServer.WorldType.NORMAL;
 | |
| 	@SerializedName("isHardcore")
 | |
| 	public boolean isHardcore = false;
 | |
| 	@SerializedName("gameMode")
 | |
| 	public int gameMode = -1;
 | |
| 	@SerializedName("activeSlot")
 | |
| 	public int activeSlot = -1;
 | |
| 	@Nullable
 | |
| 	@SerializedName("minigameName")
 | |
| 	public String minigameName;
 | |
| 	@SerializedName("minigameId")
 | |
| 	public int minigameId = -1;
 | |
| 	@Nullable
 | |
| 	@SerializedName("minigameImage")
 | |
| 	public String minigameImage;
 | |
| 	@SerializedName("parentWorldId")
 | |
| 	public long parentRealmId = -1L;
 | |
| 	@Nullable
 | |
| 	@SerializedName("parentWorldName")
 | |
| 	public String parentWorldName;
 | |
| 	@SerializedName("activeVersion")
 | |
| 	public String activeVersion = "";
 | |
| 	@SerializedName("compatibility")
 | |
| 	public RealmsServer.Compatibility compatibility = RealmsServer.Compatibility.UNVERIFIABLE;
 | |
| 	@Nullable
 | |
| 	@SerializedName("regionSelectionPreference")
 | |
| 	public RegionSelectionPreferenceDto regionSelectionPreference;
 | |
| 
 | |
| 	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(GuardedSerializer serializer, String json) {
 | |
| 		try {
 | |
| 			RealmsServer realmsServer = serializer.fromJson(json, RealmsServer.class);
 | |
| 			if (realmsServer == null) {
 | |
| 				LOGGER.error("Could not parse McoServer: {}", json);
 | |
| 				return new RealmsServer();
 | |
| 			} else {
 | |
| 				finalize(realmsServer);
 | |
| 				return realmsServer;
 | |
| 			}
 | |
| 		} catch (Exception var3) {
 | |
| 			LOGGER.error("Could not parse McoServer: {}", var3.getMessage());
 | |
| 			return new RealmsServer();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static void finalize(RealmsServer server) {
 | |
| 		if (server.players == null) {
 | |
| 			server.players = Lists.<PlayerInfo>newArrayList();
 | |
| 		}
 | |
| 
 | |
| 		if (server.slotList == null) {
 | |
| 			server.slotList = createEmptySlots();
 | |
| 		}
 | |
| 
 | |
| 		if (server.slots == null) {
 | |
| 			server.slots = new HashMap();
 | |
| 		}
 | |
| 
 | |
| 		if (server.worldType == null) {
 | |
| 			server.worldType = RealmsServer.WorldType.NORMAL;
 | |
| 		}
 | |
| 
 | |
| 		if (server.activeVersion == null) {
 | |
| 			server.activeVersion = "";
 | |
| 		}
 | |
| 
 | |
| 		if (server.compatibility == null) {
 | |
| 			server.compatibility = RealmsServer.Compatibility.UNVERIFIABLE;
 | |
| 		}
 | |
| 
 | |
| 		if (server.regionSelectionPreference == null) {
 | |
| 			server.regionSelectionPreference = RegionSelectionPreferenceDto.DEFAULT;
 | |
| 		}
 | |
| 
 | |
| 		sortInvited(server);
 | |
| 		finalizeSlots(server);
 | |
| 	}
 | |
| 
 | |
| 	private static void sortInvited(RealmsServer server) {
 | |
| 		server.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 void finalizeSlots(RealmsServer server) {
 | |
| 		server.slotList.forEach(realmsSlot -> server.slots.put(realmsSlot.slotId, realmsSlot));
 | |
| 
 | |
| 		for (int i = 1; i <= 3; i++) {
 | |
| 			if (!server.slots.containsKey(i)) {
 | |
| 				server.slots.put(i, RealmsSlot.defaults(i));
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private static List<RealmsSlot> createEmptySlots() {
 | |
| 		List<RealmsSlot> list = new ArrayList();
 | |
| 		list.add(RealmsSlot.defaults(1));
 | |
| 		list.add(RealmsSlot.defaults(2));
 | |
| 		list.add(RealmsSlot.defaults(3));
 | |
| 		return list;
 | |
| 	}
 | |
| 
 | |
| 	public boolean isCompatible() {
 | |
| 		return this.compatibility.isCompatible();
 | |
| 	}
 | |
| 
 | |
| 	public boolean needsUpgrade() {
 | |
| 		return this.compatibility.needsUpgrade();
 | |
| 	}
 | |
| 
 | |
| 	public boolean needsDowngrade() {
 | |
| 		return this.compatibility.needsDowngrade();
 | |
| 	}
 | |
| 
 | |
| 	public boolean shouldPlayButtonBeActive() {
 | |
| 		boolean bl = !this.expired && this.state == RealmsServer.State.OPEN;
 | |
| 		return bl && (this.isCompatible() || this.needsUpgrade() || this.isSelfOwnedServer());
 | |
| 	}
 | |
| 
 | |
| 	private boolean isSelfOwnedServer() {
 | |
| 		return Minecraft.getInstance().isLocalPlayer(this.ownerUUID);
 | |
| 	}
 | |
| 
 | |
| 	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.slotList = this.slotList.stream().map(RealmsSlot::clone).toList();
 | |
| 		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;
 | |
| 		realmsServer.regionSelectionPreference = this.regionSelectionPreference != null ? this.regionSelectionPreference.clone() : null;
 | |
| 		return realmsServer;
 | |
| 	}
 | |
| 
 | |
| 	public Map<Integer, RealmsSlot> cloneSlots(Map<Integer, RealmsSlot> slots) {
 | |
| 		Map<Integer, RealmsSlot> map = Maps.<Integer, RealmsSlot>newHashMap();
 | |
| 
 | |
| 		for (Entry<Integer, RealmsSlot> entry : slots.entrySet()) {
 | |
| 			map.put(
 | |
| 				(Integer)entry.getKey(), new RealmsSlot((Integer)entry.getKey(), ((RealmsSlot)entry.getValue()).options.clone(), ((RealmsSlot)entry.getValue()).settings)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		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
 | |
| 			? ((RealmsSlot)this.slots.get(slot)).options.getSlotName(slot)
 | |
| 			: this.name + " (" + ((RealmsSlot)this.slots.get(slot)).options.getSlotName(slot) + ")";
 | |
| 	}
 | |
| 
 | |
| 	public ServerData toServerData(String ip) {
 | |
| 		return new ServerData((String)Objects.requireNonNullElse(this.name, "unknown server"), ip, ServerData.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;
 | |
| 	}
 | |
| }
 |