minecraft-src/net/minecraft/client/quickplay/QuickPlayLog.java
2025-07-04 01:41:11 +03:00

126 lines
4.3 KiB
Java

package net.minecraft.client.quickplay;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.List;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.level.GameType;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class QuickPlayLog {
private static final QuickPlayLog INACTIVE = new QuickPlayLog("") {
@Override
public void log(Minecraft minecraft) {
}
@Override
public void setWorldData(QuickPlayLog.Type type, String id, String name) {
}
};
private static final Logger LOGGER = LogUtils.getLogger();
private static final Gson GSON = new GsonBuilder().create();
private final Path path;
@Nullable
private QuickPlayLog.QuickPlayWorld worldData;
QuickPlayLog(String path) {
this.path = Minecraft.getInstance().gameDirectory.toPath().resolve(path);
}
public static QuickPlayLog of(@Nullable String path) {
return path == null ? INACTIVE : new QuickPlayLog(path);
}
public void setWorldData(QuickPlayLog.Type type, String id, String name) {
this.worldData = new QuickPlayLog.QuickPlayWorld(type, id, name);
}
public void log(Minecraft minecraft) {
if (minecraft.gameMode != null && this.worldData != null) {
Util.ioPool()
.execute(
() -> {
try {
Files.deleteIfExists(this.path);
} catch (IOException var3) {
LOGGER.error("Failed to delete quickplay log file {}", this.path, var3);
}
QuickPlayLog.QuickPlayEntry quickPlayEntry = new QuickPlayLog.QuickPlayEntry(this.worldData, Instant.now(), minecraft.gameMode.getPlayerMode());
Codec.list(QuickPlayLog.QuickPlayEntry.CODEC)
.encodeStart(JsonOps.INSTANCE, List.of(quickPlayEntry))
.resultOrPartial(Util.prefix("Quick Play: ", LOGGER::error))
.ifPresent(jsonElement -> {
try {
Files.createDirectories(this.path.getParent());
Files.writeString(this.path, GSON.toJson(jsonElement));
} catch (IOException var3x) {
LOGGER.error("Failed to write to quickplay log file {}", this.path, var3x);
}
});
}
);
} else {
LOGGER.error("Failed to log session for quickplay. Missing world data or gamemode");
}
}
@Environment(EnvType.CLIENT)
record QuickPlayEntry(QuickPlayLog.QuickPlayWorld quickPlayWorld, Instant lastPlayedTime, GameType gamemode) {
public static final Codec<QuickPlayLog.QuickPlayEntry> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
QuickPlayLog.QuickPlayWorld.MAP_CODEC.forGetter(QuickPlayLog.QuickPlayEntry::quickPlayWorld),
ExtraCodecs.INSTANT_ISO8601.fieldOf("lastPlayedTime").forGetter(QuickPlayLog.QuickPlayEntry::lastPlayedTime),
GameType.CODEC.fieldOf("gamemode").forGetter(QuickPlayLog.QuickPlayEntry::gamemode)
)
.apply(instance, QuickPlayLog.QuickPlayEntry::new)
);
}
@Environment(EnvType.CLIENT)
record QuickPlayWorld(QuickPlayLog.Type type, String id, String name) {
public static final MapCodec<QuickPlayLog.QuickPlayWorld> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
QuickPlayLog.Type.CODEC.fieldOf("type").forGetter(QuickPlayLog.QuickPlayWorld::type),
ExtraCodecs.ESCAPED_STRING.fieldOf("id").forGetter(QuickPlayLog.QuickPlayWorld::id),
Codec.STRING.fieldOf("name").forGetter(QuickPlayLog.QuickPlayWorld::name)
)
.apply(instance, QuickPlayLog.QuickPlayWorld::new)
);
}
@Environment(EnvType.CLIENT)
public static enum Type implements StringRepresentable {
SINGLEPLAYER("singleplayer"),
MULTIPLAYER("multiplayer"),
REALMS("realms");
static final Codec<QuickPlayLog.Type> CODEC = StringRepresentable.fromEnum(QuickPlayLog.Type::values);
private final String name;
private Type(final String name) {
this.name = name;
}
@Override
public String getSerializedName() {
return this.name;
}
}
}