upload client name and server address as description

This commit is contained in:
iceBear67
2026-08-08 13:05:57 +08:00
parent c3a9290477
commit 2c69d10361
25 changed files with 322 additions and 5 deletions
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
@@ -88,6 +89,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -2,6 +2,7 @@ package dev.photosync.platform.impl;
import dev.photosync.core.capture.CameraPose;
import dev.photosync.mcapi.GameContext;
import dev.photosync.platform.WindowTitle;
import lombok.extern.slf4j.Slf4j;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Util;
@@ -89,6 +90,18 @@ public final class GameAdapter implements GameContext {
return minecraftVersion;
}
@Override
public String clientName() {
String title = WindowTitle.last();
return title == null || title.isBlank() ? "Minecraft" : title;
}
@Override
public Optional<String> serverAddress() {
return Optional.ofNullable(Minecraft.getInstance().getCurrentServer())
.map(server -> server.ip);
}
@Override
public void quit() {
Minecraft.getInstance().stop();
@@ -0,0 +1,29 @@
package dev.photosync.platform;
/**
* The most recent window title, for the upload description's client name.
*
* <p>Static for the same reason as {@code ScreenshotBus} and {@code QuitGuard}:
* the thing that notices the title changing is {@code TitleMixin}, woven into a
* Minecraft class that nobody constructs, so it has nowhere to be handed a
* collaborator. A static rendezvous point is the only option, and the mixin
* writes here and the {@code GameAdapter} reads from here, so the storage has
* exactly one owner.
*/
public final class WindowTitle {
private static volatile String last = "";
private WindowTitle() {
}
/** Called by {@code TitleMixin} whenever the window is given a title. */
public static void record(String title) {
last = title;
}
/** The current window title, or empty before the first {@code setTitle}. */
public static String last() {
return last;
}
}
@@ -0,0 +1,30 @@
package dev.photosync.platform.mixin;
import com.mojang.blaze3d.platform.Window;
import dev.photosync.platform.WindowTitle;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Hooks the window title, for the upload description's client name.
*
* <p>There is no way to read the title back from GLFW before lwjgl 3.4 (the
* buckets below 26.x ship 3.3.x, which has no {@code glfwGetWindowTitle}), so
* the title is captured as every caller passes it through {@code setTitle} --
* the one public way to change it, and the one every title mod uses.
*
* <p>Like {@code QuitMixin}, the hook only records into a static holder and
* holds no state of its own. {@code setTitle(String)} has not moved in the
* supported range; the day a bucket disagrees, this class moves down into all
* nine copies like any other common class.
*/
@Mixin(Window.class)
public class TitleMixin {
@Inject(method = "setTitle", at = @At("HEAD"))
private void photosync$capture(String title, CallbackInfo callback) {
WindowTitle.record(title);
}
}
@@ -6,7 +6,8 @@
"client": [
"CaptureMixin",
"HudMixin",
"QuitMixin"
"QuitMixin",
"TitleMixin"
],
"injectors": {
"defaultRequire": 1