minecraft-src/net/minecraft/client/multiplayer/ServerData.java
2025-07-04 03:45:38 +03:00

180 lines
4.9 KiB
Java

package net.minecraft.client.multiplayer;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.SharedConstants;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.status.ServerStatus.Players;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.PngInfo;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class ServerData {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int MAX_ICON_SIZE = 1024;
public String name;
public String ip;
public Component status;
public Component motd;
@Nullable
public Players players;
public long ping;
public int protocol = SharedConstants.getCurrentVersion().getProtocolVersion();
public Component version = Component.literal(SharedConstants.getCurrentVersion().getName());
public List<Component> playerList = Collections.emptyList();
private ServerData.ServerPackStatus packStatus = ServerData.ServerPackStatus.PROMPT;
@Nullable
private byte[] iconBytes;
private ServerData.Type type;
private ServerData.State state = ServerData.State.INITIAL;
public ServerData(String name, String ip, ServerData.Type type) {
this.name = name;
this.ip = ip;
this.type = type;
}
/**
* Returns an NBTTagCompound with the server's name, IP and maybe acceptTextures.
*/
public CompoundTag write() {
CompoundTag compoundTag = new CompoundTag();
compoundTag.putString("name", this.name);
compoundTag.putString("ip", this.ip);
compoundTag.storeNullable("icon", ExtraCodecs.BASE64_STRING, this.iconBytes);
compoundTag.store(ServerData.ServerPackStatus.FIELD_CODEC, this.packStatus);
return compoundTag;
}
public ServerData.ServerPackStatus getResourcePackStatus() {
return this.packStatus;
}
public void setResourcePackStatus(ServerData.ServerPackStatus packStatus) {
this.packStatus = packStatus;
}
/**
* Takes an NBTTagCompound with 'name' and 'ip' keys, returns a ServerData instance.
*/
public static ServerData read(CompoundTag nbtCompound) {
ServerData serverData = new ServerData(nbtCompound.getStringOr("name", ""), nbtCompound.getStringOr("ip", ""), ServerData.Type.OTHER);
serverData.setIconBytes((byte[])nbtCompound.read("icon", ExtraCodecs.BASE64_STRING).orElse(null));
serverData.setResourcePackStatus(
(ServerData.ServerPackStatus)nbtCompound.read(ServerData.ServerPackStatus.FIELD_CODEC).orElse(ServerData.ServerPackStatus.PROMPT)
);
return serverData;
}
@Nullable
public byte[] getIconBytes() {
return this.iconBytes;
}
public void setIconBytes(@Nullable byte[] iconBytes) {
this.iconBytes = iconBytes;
}
/**
* Returns {@code true} if the server is a LAN server.
*/
public boolean isLan() {
return this.type == ServerData.Type.LAN;
}
public boolean isRealm() {
return this.type == ServerData.Type.REALM;
}
public ServerData.Type type() {
return this.type;
}
public void copyNameIconFrom(ServerData other) {
this.ip = other.ip;
this.name = other.name;
this.iconBytes = other.iconBytes;
}
public void copyFrom(ServerData serverData) {
this.copyNameIconFrom(serverData);
this.setResourcePackStatus(serverData.getResourcePackStatus());
this.type = serverData.type;
}
public ServerData.State state() {
return this.state;
}
public void setState(ServerData.State state) {
this.state = state;
}
@Nullable
public static byte[] validateIcon(@Nullable byte[] icon) {
if (icon != null) {
try {
PngInfo pngInfo = PngInfo.fromBytes(icon);
if (pngInfo.width() <= 1024 && pngInfo.height() <= 1024) {
return icon;
}
} catch (IOException var2) {
LOGGER.warn("Failed to decode server icon", (Throwable)var2);
}
}
return null;
}
@Environment(EnvType.CLIENT)
public static enum ServerPackStatus {
ENABLED("enabled"),
DISABLED("disabled"),
PROMPT("prompt");
public static final MapCodec<ServerData.ServerPackStatus> FIELD_CODEC = Codec.BOOL
.optionalFieldOf("acceptTextures")
.xmap(optional -> (ServerData.ServerPackStatus)optional.map(boolean_ -> boolean_ ? ENABLED : DISABLED).orElse(PROMPT), serverPackStatus -> {
return switch (serverPackStatus) {
case ENABLED -> Optional.of(true);
case DISABLED -> Optional.of(false);
case PROMPT -> Optional.empty();
};
});
private final Component name;
private ServerPackStatus(final String name) {
this.name = Component.translatable("addServer.resourcePack." + name);
}
public Component getName() {
return this.name;
}
}
@Environment(EnvType.CLIENT)
public static enum State {
INITIAL,
PINGING,
UNREACHABLE,
INCOMPATIBLE,
SUCCESSFUL;
}
@Environment(EnvType.CLIENT)
public static enum Type {
LAN,
REALM,
OTHER;
}
}