diff --git a/client/fabric_1_16_5/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_16_5/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 3acfb136..ba762a80 100644 --- a/client/fabric_1_16_5/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_16_5/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -208,5 +208,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { RenderSystem.recordRenderCall(AllMusicCore::renderInit); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } \ No newline at end of file diff --git a/client/fabric_1_16_5/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_16_5/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..eb1d1c94 --- /dev/null +++ b/client/fabric_1_16_5/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,30 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager; + +/** + * Fabric(1.16.5)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandManager.DISPATCHER.register(ClientCommandManager.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(ClientCommandManager.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 53f2ae8e..ad834134 100644 --- a/client/fabric_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -138,5 +138,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { RenderSystem.recordRenderCall(AllMusicCore::renderInit); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_1_20_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_20_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_1_20_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_1_21/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_21/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index a2826149..648e20b0 100644 --- a/client/fabric_1_21/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_21/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -140,5 +140,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { RenderSystem.recordRenderCall(AllMusicCore::renderInit); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_1_21/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_21/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_1_21/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_1_21_11/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_21_11/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index d8a8c172..1ff14043 100644 --- a/client/fabric_1_21_11/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_21_11/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -135,5 +135,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { AllMusicCore.init(FabricLoader.getInstance().getConfigDir(), this); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_1_21_11/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_21_11/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_1_21_11/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_1_21_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_21_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 61ca28d8..f1384a4a 100644 --- a/client/fabric_1_21_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_21_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -140,5 +140,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { RenderSystem.recordRenderCall(AllMusicCore::renderInit); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_1_21_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_21_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_1_21_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_1_21_4/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_21_4/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 61ca28d8..f1384a4a 100644 --- a/client/fabric_1_21_4/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_21_4/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -140,5 +140,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { RenderSystem.recordRenderCall(AllMusicCore::renderInit); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_1_21_4/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_21_4/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_1_21_4/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_1_21_6/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_21_6/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 0dc948f7..4b172164 100644 --- a/client/fabric_1_21_6/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_21_6/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -133,5 +133,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { AllMusicCore.init(FabricLoader.getInstance().getConfigDir(), this); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_1_21_6/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_21_6/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_1_21_6/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_1_21_8/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_1_21_8/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 0dc948f7..4b172164 100644 --- a/client/fabric_1_21_8/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_1_21_8/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -133,5 +133,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { AllMusicCore.init(FabricLoader.getInstance().getConfigDir(), this); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_1_21_8/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_1_21_8/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_1_21_8/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_26_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_26_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 1c9d88a2..34587a88 100644 --- a/client/fabric_26_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_26_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -135,5 +135,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { AllMusicCore.init(FabricLoader.getInstance().getConfigDir(), this); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_26_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_26_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_26_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_26_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_26_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index cc5dd9bc..1242a08f 100644 --- a/client/fabric_26_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_26_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -134,5 +134,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { AllMusicCore.init(FabricLoader.getInstance().getConfigDir(), this); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_26_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_26_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_26_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/fabric_26_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/fabric_26_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 97073e42..3eb6c512 100644 --- a/client/fabric_26_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/fabric_26_3/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -131,5 +131,8 @@ public class AllMusicClient implements ClientModInitializer, AllMusicBridge { AllMusicCore.init(FabricLoader.getInstance().getConfigDir(), this); ClientLifecycleEvents.CLIENT_STOPPING.register((a) -> AllMusicCore.stop()); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + CommandMusicClientFabric.register(); } } diff --git a/client/fabric_26_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java b/client/fabric_26_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java new file mode 100644 index 00000000..1a02aa4a --- /dev/null +++ b/client/fabric_26_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientFabric.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.arguments.StringArgumentType; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.minecraft.commands.Commands; + +/** + * Fabric(1.19.3+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientFabric { + private CommandMusicClientFabric() { + } + + public static void register() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args"))))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/forge_1_12_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/forge_1_12_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index 6b029639..063494da 100644 --- a/client/forge_1_12_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/forge_1_12_2/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -14,6 +14,7 @@ import net.minecraft.network.NetworkManager; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.sound.PlaySoundEvent; import net.minecraftforge.common.MinecraftForge; @@ -61,6 +62,9 @@ public class AllMusicClient implements AllMusicBridge { } AllMusicCore.init(evt.getModConfigurationDirectory().toPath(), this); MinecraftForge.EVENT_BUS.register(this); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + ClientCommandHandler.instance.registerCommand(new CommandMusicClientForge()); try { Class server = Class.forName("com.coloryr.allmusic.server.AllMusicServer"); Field m = server.getField("channel"); diff --git a/client/forge_1_12_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java b/client/forge_1_12_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java new file mode 100644 index 00000000..968a9d7f --- /dev/null +++ b/client/forge_1_12_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java @@ -0,0 +1,60 @@ +package com.coloryr.allmusic.client; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.BlockPos; + +import java.util.Collections; +import java.util.List; + +/** + * 1.12.2 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public class CommandMusicClientForge extends CommandBase { + @Override + public String getName() { + return CommandMusicClient.NAME; + } + + @Override + public String getUsage(ICommandSender sender) { + return CommandMusicClient.usage(); + } + + @Override + public List getAliases() { + return Collections.emptyList(); + } + + @Override + public int getRequiredPermissionLevel() { + return 0; + } + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) { + return true; + } + + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CommandMusicClient.run(args); + } + + @Override + public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos targetPos) { + if (args.length <= 1) { + return getListOfStringsMatchingLastWord(args, CommandMusicClient.SUB_COMMANDS); + } + return Collections.emptyList(); + } + + @Override + public boolean isUsernameIndex(String[] args, int index) { + return false; + } +} diff --git a/client/forge_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java b/client/forge_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java index b9388a1d..ecb705d5 100644 --- a/client/forge_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java +++ b/client/forge_1_20_1/src/main/java/com/coloryr/allmusic/client/AllMusicClient.java @@ -14,6 +14,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.Resource; import net.minecraft.sounds.SoundSource; import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.client.event.RegisterClientCommandsEvent; import net.minecraftforge.client.event.RenderGuiOverlayEvent; import net.minecraftforge.client.event.sound.SoundEngineLoadEvent; import net.minecraftforge.client.event.sound.SoundEvent; @@ -135,6 +136,11 @@ public class AllMusicClient implements AllMusicBridge { AllMusicCore.tick(); } + @SubscribeEvent + public void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandMusicClientForge.register(event.getDispatcher()); + } + @Override public TextFrameBuffer makeTextRender(String name) { return new CoreRenderTarget(name); diff --git a/client/forge_1_20_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java b/client/forge_1_20_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java new file mode 100644 index 00000000..a1ce839e --- /dev/null +++ b/client/forge_1_20_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java @@ -0,0 +1,32 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; + +/** + * Forge(1.16.5+)的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public final class CommandMusicClientForge { + private CommandMusicClientForge() { + } + + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/AllMusic.java b/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/AllMusic.java index 1fcd8135..3b2dfe3b 100644 --- a/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/AllMusic.java +++ b/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/AllMusic.java @@ -22,6 +22,7 @@ import net.minecraft.network.NetworkManager; import net.minecraft.util.ChatComponentText; import net.minecraft.util.IChatComponent; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.sound.PlaySoundEvent17; import net.minecraftforge.common.MinecraftForge; @@ -77,6 +78,9 @@ public class AllMusic implements AllMusicBridge { IntBuffer source = findOpenAlSource(); AllMusicCore.init(new File("config").toPath(), this, source); AllMusicCore.renderInit(); + + // 客户端指令:/music_client help | info | test | imagesize <大小> + ClientCommandHandler.instance.registerCommand(new CommandMusicClientForge()); } /** diff --git a/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java b/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java new file mode 100644 index 00000000..0ff0a8a8 --- /dev/null +++ b/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/CommandMusicClientForge.java @@ -0,0 +1,87 @@ +package com.coloryr.allmusic.client; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +import java.util.Collections; +import java.util.List; + +/** + * 1.7.10 的 /music_client 指令壳 + *

+ * 只负责把 {@link CommandMusicClient#execute(String[])} 的结果发到聊天栏, + * 具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +public class CommandMusicClientForge implements ICommand { + @Override + public String getCommandName() { + return CommandMusicClient.NAME; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return CommandMusicClient.usage(); + } + + @Override + public List getCommandAliases() { + return Collections.emptyList(); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + CommandMusicClient.Result result = CommandMusicClient.execute(args); + + if (result.title != null) { + send(sender, result.title, EnumChatFormatting.YELLOW); + } + for (String line : result.lines) { + send(sender, line, color(CommandMusicClient.styleOf(line))); + } + } + + private static EnumChatFormatting color(int style) { + switch (style) { + case CommandMusicClient.STYLE_OK: + return EnumChatFormatting.GREEN; + case CommandMusicClient.STYLE_ERROR: + return EnumChatFormatting.RED; + default: + return null; + } + } + + private static void send(ICommandSender sender, String message, EnumChatFormatting color) { + ChatComponentText text = new ChatComponentText("[AllMusic Client] " + message); + if (color != null) { + text.getChatStyle().setColor(color); + } + sender.addChatMessage(text); + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) { + return true; + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args) { + if (args.length == 1) { + return CommandBase.getListOfStringsMatchingLastWord(args, CommandMusicClient.SUB_COMMANDS); + } + return null; + } + + @Override + public boolean isUsernameIndex(String[] args, int index) { + return false; + } + + @Override + public int compareTo(Object o) { + return 0; + } +} diff --git a/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/PicRender.java b/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/PicRender.java index ffd142bf..028c79c3 100644 --- a/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/PicRender.java +++ b/client/forge_1_7_10/src/main/java/com/coloryr/allmusic/client/PicRender.java @@ -38,6 +38,12 @@ public class PicRender extends PictureFrameBuffer { } } + @Override + public void dispose() { + sourceTexture.deleteGlTexture(); + rotateTexture.deleteGlTexture(); + } + @Override public void draw(boolean rotate, int size, float x, float y, int ang, HudPosType dir, float alpha) { Point2f point = AllMusicHud.getPos(size, size, x, y, dir); diff --git a/client/neoforge_1_21/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_1_21/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_1_21/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/neoforge_1_21_11/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_1_21_11/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_1_21_11/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/neoforge_1_21_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_1_21_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_1_21_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/neoforge_1_21_4/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_1_21_4/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_1_21_4/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/neoforge_1_21_6/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_1_21_6/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_1_21_6/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/neoforge_26_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_26_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_26_1/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/neoforge_26_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_26_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_26_2/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/neoforge_26_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java b/client/neoforge_26_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java new file mode 100644 index 00000000..4749b3ec --- /dev/null +++ b/client/neoforge_26_3/src/main/java/com/coloryr/allmusic/client/CommandMusicClientNeoForge.java @@ -0,0 +1,40 @@ +package com.coloryr.allmusic.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; + +/** + * NeoForge 的 /music_client 指令壳 + *

+ * 只负责注册指令,具体逻辑都在通用的 {@link CommandMusicClient} 里 + */ +@EventBusSubscriber(modid = AllMusicClient.MODID, value = Dist.CLIENT) +public final class CommandMusicClientNeoForge { + private CommandMusicClientNeoForge() { + } + + @SubscribeEvent + public static void onRegisterCommands(RegisterClientCommandsEvent event) { + CommandDispatcher dispatcher = event.getDispatcher(); + + dispatcher.register(Commands.literal(CommandMusicClient.NAME) + .executes(context -> CommandMusicClient.run(new String[0])) + .then(Commands.argument("args", StringArgumentType.greedyString()) + .executes(context -> CommandMusicClient.run( + split(StringArgumentType.getString(context, "args")))))); + } + + private static String[] split(String args) { + String text = args == null ? "" : args.trim(); + if (text.isEmpty()) { + return new String[0]; + } + return text.split("\\s+"); + } +} diff --git a/client/src/main/java/com/coloryr/allmusic/client/CommandMusicClient.java b/client/src/main/java/com/coloryr/allmusic/client/CommandMusicClient.java new file mode 100644 index 00000000..c1bc2ac7 --- /dev/null +++ b/client/src/main/java/com/coloryr/allmusic/client/CommandMusicClient.java @@ -0,0 +1,204 @@ +package com.coloryr.allmusic.client; + +import com.coloryr.allmusic.client.core.AllMusicCore; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * /music_client 指令的通用实现 + *

+ * 这里只做参数解析和输出内容,不依赖任何 Minecraft 类, + * 每个版本各自实现一层很薄的指令壳(比如 1.7.10 的 {@code CommandMusicClientForge}), + * 把 {@link #execute(String[])} 的结果发给玩家即可 + */ +public class CommandMusicClient { + public static final String NAME = "music_client"; + + private static final String ARG_HELP = "help"; + private static final String ARG_INFO = "info"; + private static final String ARG_TEST = "test"; + private static final String ARG_IMAGE_SIZE = "imagesize"; + + /** + * 所有子指令,Tab 补全用 + */ + public static final String[] SUB_COMMANDS = {ARG_HELP, ARG_INFO, ARG_TEST, ARG_IMAGE_SIZE}; + + /** + * 普通输出 + */ + public static final int STYLE_NORMAL = 0; + /** + * 正常([OK]) + */ + public static final int STYLE_OK = 1; + /** + * 异常([!!]) + */ + public static final int STYLE_ERROR = 2; + + /** + * 指令用法 + * + * @return 用法 + */ + public static String usage() { + return "/" + NAME + " " + ARG_HELP; + } + + /** + * 执行指令 + * + * @param args 参数(不含指令名本身) + * @return 要显示的内容 + */ + public static Result execute(String[] args) { + if (args == null || args.length == 0) { + return help(); + } + + switch (args[0].toLowerCase(Locale.ROOT)) { + case ARG_HELP: + return help(); + case ARG_INFO: + return new Result("AllMusic 客户端信息", new ArrayList<>(AllMusicCore.getInfoLines())); + case ARG_TEST: + return test(); + case ARG_IMAGE_SIZE: + return imageSize(args); + default: + return help(); + } + } + + /** + * 执行指令并把结果发到聊天栏 + *

+ * 各版本的指令壳解析出参数后直接调用这里,输出统一走游戏桥, + * 不用关心各版本聊天 API 的差异 + * + * @param args 参数(不含指令名本身) + * @return Brigadier 需要的返回值 + */ + public static int run(String[] args) { + if (AllMusicCore.bridge == null) { + return 0; + } + + Result result = execute(args); + if (result.title != null) { + AllMusicCore.bridge.sendMessage(result.title); + } + for (String line : result.lines) { + AllMusicCore.bridge.sendMessage(line); + } + + return 1; + } + + /** + * 输出行的样式,方便各版本上色 + * + * @param line 一行内容 + * @return 样式 + */ + public static int styleOf(String line) { + if (line == null) { + return STYLE_NORMAL; + } + if (line.startsWith("[OK]")) { + return STYLE_OK; + } + if (line.startsWith("[!!]")) { + return STYLE_ERROR; + } + return STYLE_NORMAL; + } + + private static Result help() { + List lines = new ArrayList<>(); + + lines.add("/" + NAME + " " + ARG_HELP + " - 显示帮助"); + lines.add("/" + NAME + " " + ARG_INFO + " - 显示客户端状态(图片大小、封面、播放状态等)"); + lines.add("/" + NAME + " " + ARG_TEST + " - 运行客户端自检并输出结果"); + lines.add("/" + NAME + " " + ARG_IMAGE_SIZE + " - 查看当前图片大小"); + lines.add("/" + NAME + " " + ARG_IMAGE_SIZE + " <" + AllMusicCore.MIN_PIC_SIZE + "-" + + AllMusicCore.MAX_PIC_SIZE + "> - 修改图片大小"); + lines.add("当前图片大小: " + AllMusicCore.getPicSize()); + + return new Result("AllMusic 客户端指令", lines); + } + + private static Result test() { + List lines = new ArrayList<>(AllMusicCore.getTestLines()); + + lines.add("自检完成: " + count(lines, "[OK]") + " 项正常, " + count(lines, "[!!]") + " 项异常"); + + return new Result("AllMusic 客户端自检", lines); + } + + private static Result imageSize(String[] args) { + List lines = new ArrayList<>(); + String title = "AllMusic 图片大小"; + + if (args.length != 2) { + if (args.length == 1) { + lines.add("当前图片大小: " + AllMusicCore.getPicSize()); + } else { + lines.add("用法: /" + NAME + " " + ARG_IMAGE_SIZE + " <" + + AllMusicCore.MIN_PIC_SIZE + "-" + AllMusicCore.MAX_PIC_SIZE + ">"); + } + return new Result(title, lines); + } + + int size; + try { + size = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + lines.add("不是有效的数字: " + args[1]); + return new Result(title, lines); + } + + if (!AllMusicCore.setPicSize(size)) { + lines.add("图片大小必须在 " + AllMusicCore.MIN_PIC_SIZE + "-" + + AllMusicCore.MAX_PIC_SIZE + " 之间"); + return new Result(title, lines); + } + + lines.add("图片大小已设置为 " + size + ",正在重新加载封面;没有封面时下一首歌生效"); + lines.add("当前图片大小: " + AllMusicCore.getPicSize()); + + return new Result(title, lines); + } + + private static int count(List lines, String prefix) { + int count = 0; + for (String line : lines) { + if (line.startsWith(prefix)) { + count++; + } + } + return count; + } + + /** + * 指令执行结果 + */ + public static class Result { + /** + * 标题,可为 null + */ + public final String title; + /** + * 内容行 + */ + public final List lines; + + public Result(String title, List lines) { + this.title = title; + this.lines = lines; + } + } +} diff --git a/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicCore.java b/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicCore.java index 94a48859..8d73dcdb 100644 --- a/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicCore.java +++ b/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicCore.java @@ -19,11 +19,13 @@ import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.LoggerConfig; import java.io.*; +import java.lang.reflect.Method; import java.nio.IntBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -33,6 +35,25 @@ import java.util.concurrent.ScheduledExecutorService; */ public class AllMusicCore { public static final CommandType[] types = CommandType.values(); + /** + * 图片大小的最小值 + */ + public static final int MIN_PIC_SIZE = 16; + /** + * 图片大小的最大值 + */ + public static final int MAX_PIC_SIZE = 1024; + /** + * 默认静音的日志 + *

+ * httpclient 的调试输出会刷 debug.log; + * 旅行者地图则是按 debug 等级在屏幕上画调试标签(TileDrawStep 里 isDebugEnabled() 就画), + * 所以一起压到 INFO,避免 debug.log 和屏幕都被刷 + */ + public static final List DEFAULT_LOG_QUIET = Arrays.asList( + "org.apache.hc.client5", + "org.apache.hc.core5", + "journeymap"); private static final Gson gson = new Gson(); /** @@ -44,6 +65,10 @@ public class AllMusicCore { */ public static ConfigObj config; public static CloseableHttpClient client; + /** + * 配置文件 + */ + private static File configFile; /** * 音频解码器与播放器 */ @@ -90,7 +115,7 @@ public class AllMusicCore { headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0")); client = HttpClients.custom().setDefaultHeaders(headers).build(); - File configFile = new File(file.toFile(), "allmusic_client.json"); + configFile = new File(file.toFile(), "allmusic_client.json"); if (configFile.exists()) { try { InputStreamReader reader = new InputStreamReader( @@ -108,33 +133,53 @@ public class AllMusicCore { config = new ConfigObj(); config.picSize = 240; config.queueSize = 100; - try { - String data = new GsonBuilder().setPrettyPrinting() - .create() - .toJson(config); - FileOutputStream out = new FileOutputStream(configFile); - OutputStreamWriter write = new OutputStreamWriter(out, StandardCharsets.UTF_8); - write.write(data); - write.close(); - out.close(); - } catch (Exception e) { - e.printStackTrace(); - } } + if (config.logQuiet == null || config.logQuiet.isEmpty()) { + config.logQuiet = new ArrayList<>(DEFAULT_LOG_QUIET); + } + saveConfig(); AllMusicCore.bridge = bridge; player = new AllMusicPlayer(source); - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); +// LoggerContext ctx = (LoggerContext) LogManager.getContext(false); +// Configuration logConfig = ctx.getConfiguration(); +// +// setLoggerLevel(logConfig, "org.apache.hc.client5", Level.INFO); +// setLoggerLevel(logConfig, "org.apache.hc.core5", Level.INFO); +// +// ctx.updateLoggers(logConfig); + } - LoggerConfig loggerConfig = config.getLoggerConfig("org.apache.hc.client5"); - loggerConfig.setLevel(Level.INFO); + /** + * 只调整指定 logger 的等级,不动根 logger + *

+ * {@link Configuration#getLoggerConfig(String)} 找不到同名 logger 时会返回父级或根 logger, + * 直接 setLevel 会顺带把根 logger 的等级改掉,等于把玩家自己的日志配置整个覆盖了。 + * 这里只修改同名 logger;没有就新建一个(additive,日志依旧会输出到根 logger 的 appender) + * + * @param logConfig 日志配置 + * @param name logger 名字 + * @param level 日志等级 + */ + private static void setLoggerLevel(Configuration logConfig, String name, Level level) { + LoggerConfig loggerConfig = logConfig.getLoggerConfig(name); - LoggerConfig coreConfig = config.getLoggerConfig("org.apache.hc.core5"); - coreConfig.setLevel(Level.INFO); + if (name.equals(loggerConfig.getName())) { + loggerConfig.setLevel(level); + return; + } - ctx.updateLoggers(config); + // 没有同名 logger:新建一个挂进配置。 + // Configuration#addLogger 只存在于实现类(1.7.10 自带的 2.0-beta9 里连接口都没有), + // 所以按运行时类型反射调用,避免换版本时 NoSuchMethodError + try { + Method addLogger = logConfig.getClass() + .getMethod("addLogger", String.class, LoggerConfig.class); + addLogger.invoke(logConfig, name, new LoggerConfig(name, level, true)); + } catch (Exception ignored) { + // 实在加不进去就保持原样,绝不去改根 logger + } } public static void stop() { @@ -165,6 +210,120 @@ public class AllMusicCore { hud = new AllMusicHud(config.picSize); } + /** + * 获取图片大小 + * + * @return 图片大小 + */ + public static int getPicSize() { + return config == null ? 0 : config.picSize; + } + + /** + * 设置图片大小 + *

+ * 立即重建图片渲染缓冲;下一次收到图片(比如下一首歌的封面)时就会用新的大小生成。 + * 当前正在显示的封面会重新拉取一次,没有封面时等下一首歌的图片包。 + * 同时写回 allmusic_client.json,重启后依然生效 + * + * @param size 图片大小 + * @return 是否设置成功 + */ + public static boolean setPicSize(int size) { + if (config == null) { + return false; + } + if (size < MIN_PIC_SIZE || size > MAX_PIC_SIZE) { + return false; + } + + config.picSize = size; + saveConfig(); + if (hud != null) { + hud.setPicSize(size); + } + return true; + } + + /** + * 保存配置文件 + */ + public static void saveConfig() { + if (configFile == null || config == null) { + return; + } + try { + String data = new GsonBuilder().setPrettyPrinting() + .create() + .toJson(config); + FileOutputStream out = new FileOutputStream(configFile); + OutputStreamWriter write = new OutputStreamWriter(out, StandardCharsets.UTF_8); + write.write(data); + write.close(); + out.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 客户端信息 + * + * @return 每一行内容 + */ + public static List getInfoLines() { + List list = new ArrayList<>(); + + list.add("配置文件: config/allmusic_client.json"); + list.add("图片大小 picSize: " + getPicSize() + + "(范围 " + MIN_PIC_SIZE + "-" + MAX_PIC_SIZE + ",/music_client imagesize <大小> 修改)"); + list.add("音频队列: " + (config == null ? 0 : config.queueSize)); + list.add("HUD 渲染层: " + (hud == null ? "未初始化" : "已初始化")); + + if (hud != null) { + list.add("HUD 数据: " + (hud.hasHudData() ? "已收到" : "未收到(没进服或者服务端没发)")); + list.add("当前封面: " + (hud.hasImage() ? "有,尺寸 " + hud.getPicSize() + "x" + hud.getPicSize() : "无")); + String url = hud.getLastPicUrl(); + if (url != null && !url.isEmpty()) { + list.add("封面地址: " + url); + } + } + + list.add("播放状态: " + (isPlay() ? "播放中" : "未播放")); + + return list; + } + + /** + * 客户端自检 + * + * @return 每一行结果,[OK] 正常,[!!] 异常 + */ + public static List getTestLines() { + List list = new ArrayList<>(); + + list.add(check(config != null, "核心初始化")); + list.add(check(bridge != null, "游戏桥")); + list.add(check(client != null, "网络客户端")); + list.add(check(player != null, "音频播放器")); + list.add(check(hud != null, "HUD 渲染层")); + + if (bridge != null) { + list.add(" 屏幕大小: " + bridge.getScreenWidth() + "x" + bridge.getScreenHeight()); + list.add(" 字体高度: " + bridge.getFontHeight()); + } + + if (hud != null) { + list.addAll(hud.getTestLines()); + } + + return list; + } + + private static String check(boolean ok, String text) { + return (ok ? "[OK] " : "[!!] ") + text; + } + /** * 退出服务器时 */ diff --git a/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicHud.java b/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicHud.java index f8fb9dad..69811851 100644 --- a/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicHud.java +++ b/client/src/main/java/com/coloryr/allmusic/client/core/AllMusicHud.java @@ -14,6 +14,8 @@ import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import java.util.Queue; import java.util.concurrent.*; @@ -40,11 +42,23 @@ public class AllMusicHud { /** * 图片大小 */ - private final int size; + private volatile int size; /** * 图片渲染 */ - private final PictureFrameBuffer picRender; + private PictureFrameBuffer picRender; + /** + * 新大小的图片渲染,等新图片上传时再替换,避免改大小后当前封面直接消失 + */ + private PictureFrameBuffer pendingPicRender; + /** + * 新渲染缓冲的大小 + */ + private int pendingSize; + /** + * 最后一张图片是用多大的尺寸生成的 + */ + private volatile int loadedSize; /** * 文字渲染 */ @@ -79,8 +93,18 @@ public class AllMusicHud { private int lyricWidth; private final int pgOffset; private final float picScale; - private BufferedImage bg2; + /** + * 原始背景图,改图片大小时用来重新缩放 + */ + private final BufferedImage bg2Source; + private volatile BufferedImage bg2; private boolean isRun; + /** + * 最后一张图片的地址,改图片大小时重新拉取 + *

+ * 由下载线程写入、客户端线程读取,必须 volatile + */ + private volatile String lastPicUrl; /** * 是否有图片 @@ -136,12 +160,17 @@ public class AllMusicHud { offset = AllMusicCore.bridge.readText(PIC_SCALE); picScale = Float.parseFloat(offset); + BufferedImage source = null; try { InputStream stream = AllMusicCore.bridge.readFile(BG2); - bg2 = resizeImage(ImageIO.read(stream), size, size); + source = ImageIO.read(stream); + if (source != null) { + bg2 = resizeImage(source, size, size); + } } catch (Exception e) { e.printStackTrace(); } + bg2Source = source; } public void stop() { @@ -324,6 +353,7 @@ public class AllMusicHud { */ private void loadPic(String picUrl) { haveImg = false; + lastPicUrl = picUrl; try { while (save == null || imageNeedUpload) { Thread.sleep(200); @@ -332,6 +362,9 @@ public class AllMusicHud { return; } + // 固定本次使用的尺寸,避免下载过程中被改掉,生成出一张和缓冲对不上的图 + final int size = this.size; + HttpGet request = new HttpGet(picUrl); BufferedImage image = AllMusicCore.client.execute(request, (response -> { InputStream inputStream = response.getEntity().getContent(); @@ -362,6 +395,7 @@ public class AllMusicHud { rotateImage = outputStream.toByteArray(); request.clear(); + loadedSize = size; imageNeedUpload = true; } catch (Exception e) { e.printStackTrace(); @@ -374,6 +408,23 @@ public class AllMusicHud { * 更新材质 */ private void updateTexture() { + if (pendingPicRender != null) { + if (loadedSize != pendingSize) { + // 这张图是按旧尺寸生成的,缓冲对不上,丢掉重新拉一次 + String url = lastPicUrl; + if (url != null && !url.isEmpty()) { + setImg(url); + } + return; + } + PictureFrameBuffer old = picRender; + picRender = pendingPicRender; + pendingPicRender = null; + // 旧大小的贴图已经用不到了,释放掉 + if (old != null) { + old.dispose(); + } + } picRender.update(sourceImage, rotateImage); haveImg = true; } @@ -433,6 +484,119 @@ public class AllMusicHud { return true; } + /** + * 获取图片大小 + * + * @return 图片大小 + */ + public int getPicSize() { + return size; + } + + /** + * 是否已经收到服务端的 HUD 数据 + * + * @return 是否收到 + */ + public boolean hasHudData() { + return save != null; + } + + /** + * 当前是否有封面可以显示 + * + * @return 是否有封面 + */ + public boolean hasImage() { + return haveImg; + } + + /** + * 最后加载的封面地址 + * + * @return 封面地址 + */ + public String getLastPicUrl() { + return lastPicUrl; + } + + /** + * 客户端自检信息 + * + * @return 每一行结果,[OK] 正常,[!!] 异常 + */ + public List getTestLines() { + List list = new ArrayList<>(); + + list.add(check(size > 0, "图片缓冲: " + size + "x" + size + + (pendingPicRender != null ? "(有 " + pendingSize + " 的新缓冲待替换)" : ""))); + list.add(check(bg1.width > 0 && bg1.height > 0, "底图 bg1.png: " + bg1.width + "x" + bg1.height)); + list.add(check(bg3.width > 0 && bg3.height > 0, "唱臂 bg3.png: " + bg3.width + "x" + bg3.height)); + list.add(check(progress1.width > 0 && progress1.height > 0, + "进度条 pg1.png: " + progress1.width + "x" + progress1.height)); + list.add(check(progress2.width > 0 && progress2.height > 0, + "进度条 pg2.png: " + progress2.width + "x" + progress2.height)); + list.add(check(progress3.width > 0 && progress3.height > 0, + "进度条 pg3.png: " + progress3.width + "x" + progress3.height)); + list.add(check(bg2 != null, "封面圆环 bg2.png: " + + (bg2 == null ? "未加载" : bg2.getWidth() + "x" + bg2.getHeight()))); + list.add(check(save != null, "服务端 HUD 数据: " + (save == null ? "未收到" : "已收到"))); + + if (save != null) { + list.add(" 信息 " + enable(save.info.enable) + " / 歌词 " + enable(save.lyric.enable) + + " / 进度 " + enable(save.state.enable) + " / 封面 " + enable(save.pic.enable)); + list.add(" 封面位置: " + save.pic.x + "," + save.pic.y + " 大小 " + save.pic.size + + " 旋转 " + enable(save.pic.rotate)); + } + + list.add(check(haveImg, "当前封面: " + (haveImg ? "有" : "无"))); + + return list; + } + + private static String check(boolean ok, String text) { + return (ok ? "[OK] " : "[!!] ") + text; + } + + private static String enable(boolean value) { + return value ? "开" : "关"; + } + + /** + * 修改图片大小 + *

+ * 只在客户端本地改,不需要服务端配合。新大小的贴图缓冲会立刻建好, + * 等新图片上传(重新拉取当前封面,或者下一首歌的图片包)时替换掉旧的 + * + * @param size 图片大小 + * @return 是否修改成功 + */ + public boolean setPicSize(int size) { + if (size <= 0 || size == this.size) { + return false; + } + + this.size = size; + + if (bg2Source != null) { + bg2 = resizeImage(bg2Source, size, size); + } + + if (pendingPicRender != null) { + pendingPicRender.dispose(); + } + pendingPicRender = AllMusicCore.bridge.makePictureRender(size); + pendingSize = size; + + // 重新拉一次当前封面,让新大小马上生效;没有封面时就等下一首歌 + String url = lastPicUrl; + if (url != null && !url.isEmpty()) { + setImg(url); + } + + return true; + } + /** * 显示更新 */ diff --git a/client/src/main/java/com/coloryr/allmusic/client/core/objs/ConfigObj.java b/client/src/main/java/com/coloryr/allmusic/client/core/objs/ConfigObj.java index f031750c..ec5c1ecc 100644 --- a/client/src/main/java/com/coloryr/allmusic/client/core/objs/ConfigObj.java +++ b/client/src/main/java/com/coloryr/allmusic/client/core/objs/ConfigObj.java @@ -1,5 +1,7 @@ package com.coloryr.allmusic.client.core.objs; +import java.util.List; + public class ConfigObj { /** * 图片大小 @@ -9,4 +11,8 @@ public class ConfigObj { * 音频队列大小 */ public int queueSize; + /** + * 需要静音(设成 INFO)的日志 + */ + public List logQuiet; } diff --git a/client/src/main/java/com/coloryr/allmusic/client/core/render/PictureFrameBuffer.java b/client/src/main/java/com/coloryr/allmusic/client/core/render/PictureFrameBuffer.java index dedac23b..21bb6b80 100644 --- a/client/src/main/java/com/coloryr/allmusic/client/core/render/PictureFrameBuffer.java +++ b/client/src/main/java/com/coloryr/allmusic/client/core/render/PictureFrameBuffer.java @@ -22,4 +22,12 @@ public abstract class PictureFrameBuffer { * @param alpha 透明度 */ public abstract void draw(boolean rotate, int size, float x, float y, int ang, HudPosType dir, float alpha); + + /** + * 释放图片占用的资源 + *

+ * 修改图片大小时会换掉旧的渲染缓冲,旧的贴图需要释放 + */ + public void dispose() { + } }