v0.4.14: /videoCache clear + tighten default cap to 750 MB
Some checks failed
build / build (push) Has been cancelled

- 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.
This commit is contained in:
tkrmagid
2026-05-16 19:52:40 +09:00
parent c53ebcc30d
commit 849e53096c
4 changed files with 50 additions and 7 deletions

View File

@@ -5,7 +5,7 @@ org.gradle.configuration-cache=false
# Mod # Mod
mod_id=video_player mod_id=video_player
mod_version=0.4.13 mod_version=0.4.14
maven_group=com.ejclaw.videoplayer maven_group=com.ejclaw.videoplayer
archives_base_name=video_player archives_base_name=video_player

View File

@@ -49,7 +49,12 @@ public final class VideoPlayerConfig {
private static final String FILE_NAME = "video_player.json"; 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. */ /** Default render-distance cap for video anchors, in blocks. 128 = the legacy hard-coded value. */
private static final int DEFAULT_RENDER_DISTANCE = 128; private static final int DEFAULT_RENDER_DISTANCE = 128;
@@ -198,6 +203,18 @@ public final class VideoPlayerConfig {
return removed; 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<String> clearCacheEntries() {
if (CACHE_ENTRIES.isEmpty()) return java.util.Collections.emptyList();
java.util.List<String> urls = new java.util.ArrayList<>(CACHE_ENTRIES.values());
CACHE_ENTRIES.clear();
save();
return urls;
}
// -- io ---------------------------------------------------------------------------------- // -- io ----------------------------------------------------------------------------------
private static Path configPath() { private static Path configPath() {

View File

@@ -42,11 +42,11 @@ public final class VideoCache {
private static final Set<String> IN_FLIGHT = ConcurrentHashMap.newKeySet(); private static final Set<String> IN_FLIGHT = ConcurrentHashMap.newKeySet();
/** /**
* Hard ceiling on a single preload, in bytes. Default 1 GB so a fresh client without a * Hard ceiling on a single preload, in bytes. Default 750 MB sized to fit ~50 short FHD
* policy packet (e.g. integrated server, dev test) still has a sensible cap. Overridden by * clips; overridden per-session by {@link com.ejclaw.videoplayer.net.CachePolicyPayload}
* {@link com.ejclaw.videoplayer.net.CachePolicyPayload} on join. * 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. */ /** Server-driven override of the per-video cap. */
public static void setMaxBytes(long bytes) { public static void setMaxBytes(long bytes) {

View File

@@ -52,7 +52,9 @@ public final class VideoCacheCommand {
.executes(VideoCacheCommand::runList)) .executes(VideoCacheCommand::runList))
.then(Commands.literal("remove") .then(Commands.literal("remove")
.then(Commands.argument("name", StringArgumentType.word()) .then(Commands.argument("name", StringArgumentType.word())
.executes(VideoCacheCommand::runRemove))); .executes(VideoCacheCommand::runRemove)))
.then(Commands.literal("clear")
.executes(VideoCacheCommand::runClear));
} }
private static int runAdd(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException { private static int runAdd(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
@@ -123,6 +125,30 @@ public final class VideoCacheCommand {
return entries.size(); return entries.size();
} }
private static int runClear(CommandContext<CommandSourceStack> ctx) {
CommandSourceStack src = ctx.getSource();
java.util.List<String> 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<CommandSourceStack> ctx) throws CommandSyntaxException { private static int runRemove(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
CommandSourceStack src = ctx.getSource(); CommandSourceStack src = ctx.getSource();
String name = StringArgumentType.getString(ctx, "name").trim(); String name = StringArgumentType.getString(ctx, "name").trim();