From 849e53096cfc56e6443a30fa6e6b40dddd6a377a Mon Sep 17 00:00:00 2001 From: tkrmagid Date: Sat, 16 May 2026 19:52:40 +0900 Subject: [PATCH] v0.4.14: /videoCache clear + tighten default cap to 750 MB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New /videoCache clear subcommand: drops every named entry from server config and broadcasts DeleteCachePayload per URL so each client purges its disk cache in one shot. - Default max_preload_mb lowered from 1024 → 750. Sized to fit ~50 short FHD clips (FHD H.264 ~5 Mbps × 20 s ≈ 12.5 MB → 50 × 15 MB ≈ 750 MB with headroom). Config file's max_preload_mb still wins when set; the new default only affects fresh installs and the client-side bootstrap value before the JOIN policy packet arrives. --- gradle.properties | 2 +- .../ejclaw/videoplayer/VideoPlayerConfig.java | 19 ++++++++++++- .../client/playback/VideoCache.java | 8 +++--- .../command/VideoCacheCommand.java | 28 ++++++++++++++++++- 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index fe2ac98..06d6646 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.configuration-cache=false # Mod mod_id=video_player -mod_version=0.4.13 +mod_version=0.4.14 maven_group=com.ejclaw.videoplayer archives_base_name=video_player diff --git a/src/main/java/com/ejclaw/videoplayer/VideoPlayerConfig.java b/src/main/java/com/ejclaw/videoplayer/VideoPlayerConfig.java index 52e0bf3..886efce 100644 --- a/src/main/java/com/ejclaw/videoplayer/VideoPlayerConfig.java +++ b/src/main/java/com/ejclaw/videoplayer/VideoPlayerConfig.java @@ -49,7 +49,12 @@ public final class VideoPlayerConfig { private static final String FILE_NAME = "video_player.json"; - private static final int DEFAULT_MAX_PRELOAD_MB = 1024; + /** + * Default per-video download cap in MB. Sized to comfortably fit ~50 short FHD clips: + * FHD H.264 at ~5 Mbps × 20 s ≈ 12.5 MB, so 50 × 15 MB ≈ 750 MB with headroom for + * higher-bitrate sources. + */ + private static final int DEFAULT_MAX_PRELOAD_MB = 750; /** Default render-distance cap for video anchors, in blocks. 128 = the legacy hard-coded value. */ private static final int DEFAULT_RENDER_DISTANCE = 128; @@ -198,6 +203,18 @@ public final class VideoPlayerConfig { return removed; } + /** + * Drop every named cache entry and return the URLs that were registered so the caller + * can broadcast {@code DeleteCachePayload} for each. Persists on any non-empty removal. + */ + public static synchronized java.util.List clearCacheEntries() { + if (CACHE_ENTRIES.isEmpty()) return java.util.Collections.emptyList(); + java.util.List urls = new java.util.ArrayList<>(CACHE_ENTRIES.values()); + CACHE_ENTRIES.clear(); + save(); + return urls; + } + // -- io ---------------------------------------------------------------------------------- private static Path configPath() { diff --git a/src/main/java/com/ejclaw/videoplayer/client/playback/VideoCache.java b/src/main/java/com/ejclaw/videoplayer/client/playback/VideoCache.java index 832d9bd..11d387d 100644 --- a/src/main/java/com/ejclaw/videoplayer/client/playback/VideoCache.java +++ b/src/main/java/com/ejclaw/videoplayer/client/playback/VideoCache.java @@ -42,11 +42,11 @@ public final class VideoCache { private static final Set IN_FLIGHT = ConcurrentHashMap.newKeySet(); /** - * Hard ceiling on a single preload, in bytes. Default 1 GB so a fresh client without a - * policy packet (e.g. integrated server, dev test) still has a sensible cap. Overridden by - * {@link com.ejclaw.videoplayer.net.CachePolicyPayload} on join. + * Hard ceiling on a single preload, in bytes. Default 750 MB sized to fit ~50 short FHD + * clips; overridden per-session by {@link com.ejclaw.videoplayer.net.CachePolicyPayload} + * on join, which carries the server's {@code max_preload_mb} config value. */ - private static volatile long MAX_BYTES = 1024L * 1024 * 1024; + private static volatile long MAX_BYTES = 750L * 1024 * 1024; /** Server-driven override of the per-video cap. */ public static void setMaxBytes(long bytes) { diff --git a/src/main/java/com/ejclaw/videoplayer/command/VideoCacheCommand.java b/src/main/java/com/ejclaw/videoplayer/command/VideoCacheCommand.java index fd67efe..ebc9def 100644 --- a/src/main/java/com/ejclaw/videoplayer/command/VideoCacheCommand.java +++ b/src/main/java/com/ejclaw/videoplayer/command/VideoCacheCommand.java @@ -52,7 +52,9 @@ public final class VideoCacheCommand { .executes(VideoCacheCommand::runList)) .then(Commands.literal("remove") .then(Commands.argument("name", StringArgumentType.word()) - .executes(VideoCacheCommand::runRemove))); + .executes(VideoCacheCommand::runRemove))) + .then(Commands.literal("clear") + .executes(VideoCacheCommand::runClear)); } private static int runAdd(CommandContext ctx) throws CommandSyntaxException { @@ -123,6 +125,30 @@ public final class VideoCacheCommand { return entries.size(); } + private static int runClear(CommandContext ctx) { + CommandSourceStack src = ctx.getSource(); + java.util.List urls = VideoPlayerConfig.clearCacheEntries(); + if (urls.isEmpty()) { + src.sendSuccess(() -> Component.literal("[videocache] 저장된 항목이 없습니다") + .withStyle(ChatFormatting.GRAY), false); + return 0; + } + MinecraftServer server = src.getServer(); + int clients = 0; + for (ServerPlayer p : PlayerLookup.all(server)) { + for (String url : urls) { + ServerPlayNetworking.send(p, new DeleteCachePayload(url)); + } + clients++; + } + final int sentFinal = clients; + final int countFinal = urls.size(); + src.sendSuccess(() -> Component.literal( + "[videocache] 전체 삭제: " + countFinal + "개 항목" + + " (" + sentFinal + " 클라이언트에 cache_delete 전송)"), false); + return countFinal; + } + private static int runRemove(CommandContext ctx) throws CommandSyntaxException { CommandSourceStack src = ctx.getSource(); String name = StringArgumentType.getString(ctx, "name").trim();