Skip to content

Commit 2066dad

Browse files
committed
feat. 加入MusicAgent功能(服务器点歌)
1 parent 216214c commit 2066dad

12 files changed

+394
-27
lines changed

src/main/java/top/gregtao/concerto/ConcertoClient.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public class ConcertoClient implements ClientModInitializer {
3636
// ======================================================
3737
// Server States
3838

39+
public static ClientState clientState = ClientState.LOCAL;
40+
3941
public static boolean serverAvailable = false;
4042

4143
public static List<Playlist> presetRadios = List.of();
@@ -45,6 +47,12 @@ public static boolean isServerAvailable() {
4547
// return serverAvailable; // DEBUG
4648
}
4749

50+
public enum ClientState {
51+
LOCAL,
52+
MUSIC_ROOM,
53+
MUSIC_AGENT
54+
}
55+
4856
// ======================================================
4957

5058
@Override

src/main/java/top/gregtao/concerto/command/ConcertoServerCommand.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import net.minecraft.util.Formatting;
1212
import top.gregtao.concerto.ConcertoServer;
1313
import top.gregtao.concerto.network.MusicDataPacket;
14+
import top.gregtao.concerto.network.ServerMusicAgent;
1415
import top.gregtao.concerto.network.ServerMusicNetworkHandler;
1516
import top.gregtao.concerto.player.MusicPlayer;
1617
import top.gregtao.concerto.util.TextUtil;
@@ -75,10 +76,16 @@ public static void register(CommandDispatcher<ServerCommandSource> dispatcher, C
7576
).then(
7677
CommandManager.literal("fetch-radios")
7778
.requires(source -> source.hasPermissionLevel(0)).executes(context -> {
78-
ServerPlayerEntity player = context.getSource().getPlayer();
79-
if (player != null) ServerMusicNetworkHandler.sendS2CPresetRadiosPacket(player);
80-
return 0;
81-
})
79+
ServerPlayerEntity player = context.getSource().getPlayer();
80+
if (player != null) ServerMusicNetworkHandler.sendS2CPresetRadiosPacket(player);
81+
return 0;
82+
})
83+
).then(
84+
CommandManager.literal("reset-agent")
85+
.requires(source -> source.hasPermissionLevel(2)).executes(context -> {
86+
ServerMusicAgent.INSTANCE.reset();
87+
return 0;
88+
})
8289
)
8390
);
8491
}
@@ -87,11 +94,11 @@ public static Text chatMessageBuilder(UUID uuid, String name, String title) {
8794
return Text.translatable("concerto.audit.message", name, title)
8895
.append(Text.literal(" ["))
8996
.append(Text.translatable("concerto.accept").setStyle(
90-
TextUtil.getRunCommandStyle("/audit " + uuid).withColor(Formatting.GREEN)))
97+
TextUtil.getRunCommandStyle("/concerto-server audit " + uuid).withColor(Formatting.GREEN)))
9198
.append(Text.literal("]"))
9299
.append(Text.literal(" ["))
93100
.append(Text.translatable("concerto.reject").setStyle(
94-
TextUtil.getRunCommandStyle("/audit reject " + uuid).withColor(Formatting.RED)))
101+
TextUtil.getRunCommandStyle("/concerto-server audit reject " + uuid).withColor(Formatting.RED)))
95102
.append(Text.literal("]"));
96103
}
97104
}

src/main/java/top/gregtao/concerto/command/MusicRoomCommand.java

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package top.gregtao.concerto.command;
22

33
import com.mojang.brigadier.CommandDispatcher;
4+
import com.mojang.brigadier.arguments.BoolArgumentType;
45
import com.mojang.brigadier.arguments.StringArgumentType;
56
import com.mojang.brigadier.tree.LiteralCommandNode;
67
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
78
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
9+
import net.minecraft.client.network.ClientPlayerEntity;
810
import net.minecraft.command.CommandRegistryAccess;
911
import net.minecraft.text.Text;
12+
import top.gregtao.concerto.ConcertoClient;
13+
import top.gregtao.concerto.network.ClientMusicNetworkHandler;
1014
import top.gregtao.concerto.network.MusicRoom;
1115

1216
public class MusicRoomCommand {
@@ -15,11 +19,17 @@ public static void register(CommandDispatcher<FabricClientCommandSource> dispatc
1519
LiteralCommandNode<FabricClientCommandSource> node = dispatcher.register(
1620
ClientCommandManager.literal("musicroom")
1721
.then(ClientCommandManager.literal("create").executes(context -> {
18-
MusicRoom.clientCreate();
22+
ClientPlayerEntity player = context.getSource().getPlayer();
23+
if (checkServerAvailable(player) && checkLocal(player)) {
24+
MusicRoom.clientCreate();
25+
}
1926
return 0;
2027
})).then(ClientCommandManager.literal("join").then(
2128
ClientCommandManager.argument("uuid", StringArgumentType.string()).executes(context -> {
22-
MusicRoom.clientJoin(StringArgumentType.getString(context, "uuid"));
29+
ClientPlayerEntity player = context.getSource().getPlayer();
30+
if (checkServerAvailable(player) && checkLocal(player)) {
31+
MusicRoom.clientJoin(StringArgumentType.getString(context, "uuid"));
32+
}
2333
return 0;
2434
})
2535
)).then(ClientCommandManager.literal("quit").executes(context -> {
@@ -38,8 +48,86 @@ public static void register(CommandDispatcher<FabricClientCommandSource> dispatc
3848
MusicRoom.clientSetOp(StringArgumentType.getString(context, "player"));
3949
return 0;
4050
})
41-
))
51+
)).then(
52+
ClientCommandManager.literal("agent").then(
53+
ClientCommandManager.literal("join").executes(context -> {
54+
ClientPlayerEntity player = context.getSource().getPlayer();
55+
if (checkServerAvailable(player) && checkLocal(player)) {
56+
ClientMusicNetworkHandler.musicAgentJoin();
57+
}
58+
return 0;
59+
})
60+
).then(
61+
ClientCommandManager.literal("quit").executes(context -> {
62+
ClientPlayerEntity player = context.getSource().getPlayer();
63+
if (checkServerAvailable(player) && checkAgent(player)) {
64+
ClientMusicNetworkHandler.musicAgentQuit();
65+
}
66+
return 0;
67+
})
68+
).then(
69+
ClientCommandManager.literal("query").executes(context -> {
70+
ClientPlayerEntity player = context.getSource().getPlayer();
71+
if (checkServerAvailable(player) && checkAgent(player)) {
72+
ClientMusicNetworkHandler.musicAgentQuery();
73+
}
74+
return 0;
75+
})
76+
).then(
77+
ClientCommandManager.literal("add").executes(context -> {
78+
ClientPlayerEntity player = context.getSource().getPlayer();
79+
if (checkServerAvailable(player) && checkAgent(player)) {
80+
if (!ClientMusicNetworkHandler.musicAgentAddCurrentMusic()) {
81+
player.sendMessage(Text.translatable("concerto.not_playing_music"), false);
82+
}
83+
}
84+
return 0;
85+
})
86+
).then(
87+
ClientCommandManager.literal("vote").executes(context -> {
88+
ClientPlayerEntity player = context.getSource().getPlayer();
89+
if (checkServerAvailable(player) && checkAgent(player)) {
90+
ClientMusicNetworkHandler.musicAgentNewVote();
91+
}
92+
return 0;
93+
}).then(
94+
ClientCommandManager.argument("vote", BoolArgumentType.bool()).executes(context -> {
95+
ClientPlayerEntity player = context.getSource().getPlayer();
96+
if (checkServerAvailable(player) && checkAgent(player)) {
97+
ClientMusicNetworkHandler.musicAgentVote(BoolArgumentType.getBool(context, "vote"));
98+
}
99+
return 0;
100+
})
101+
)
102+
)
103+
)
42104
);
43105
dispatcher.register(ClientCommandManager.literal("concerto").redirect(node));
44106
}
107+
108+
public static boolean checkServerAvailable(ClientPlayerEntity player) {
109+
if (!ConcertoClient.serverAvailable) {
110+
player.sendMessage(Text.translatable("concerto.not_available"), false);
111+
return false;
112+
}
113+
return true;
114+
}
115+
116+
public static boolean checkLocal(ClientPlayerEntity player) {
117+
if (ConcertoClient.clientState == ConcertoClient.ClientState.LOCAL) {
118+
return true;
119+
} else {
120+
player.sendMessage(Text.translatable("concerto.agent.occupied"), false);
121+
return false;
122+
}
123+
}
124+
125+
public static boolean checkAgent(ClientPlayerEntity player) {
126+
if (ConcertoClient.clientState == ConcertoClient.ClientState.MUSIC_AGENT) {
127+
return true;
128+
} else {
129+
player.sendMessage(Text.translatable("concerto.not_available"), false);
130+
return false;
131+
}
132+
}
45133
}

src/main/java/top/gregtao/concerto/mixin/MinecraftClientMixin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public void disconnectInject(Screen disconnectionScreen, boolean transferring, C
2222
MusicAuditionScreen.WAIT_AUDITION.clear();
2323
MusicPlayer.INSTANCE.pause();
2424
MusicRoom.CLIENT_ROOM = null;
25+
ConcertoClient.clientState = ConcertoClient.ClientState.LOCAL;
2526
ConcertoClient.LOGGER.info("Exited from server. Functions of server side are unavailable now.");
2627
}
2728
}

src/main/java/top/gregtao/concerto/network/ClientMusicNetworkHandler.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public static void generalReceiver(ConcertoPayload payload, ClientPlayNetworking
4444
case AUDITION_SYNC -> auditionDataSyncReceiver(payload, context);
4545
case MUSIC_ROOM -> MusicRoom.clientReceiver(payload, context);
4646
case PRESET_RADIOS -> presetRadiosReceiver(payload, context);
47+
case MUSIC_AGENT -> musicAgentMusicReceiver(payload, context);
4748
}
4849
}
4950

@@ -190,4 +191,48 @@ public static void presetRadiosReceiver(ConcertoPayload payload, ClientPlayNetwo
190191
}
191192
});
192193
}
194+
195+
public static void musicAgentJoin() {
196+
ClientPlayNetworking.send(new ConcertoPayload(ConcertoPayload.Channel.MUSIC_AGENT, "Join"));
197+
ConcertoClient.clientState = ConcertoClient.ClientState.MUSIC_AGENT;
198+
}
199+
200+
public static void musicAgentQuit() {
201+
ClientPlayNetworking.send(new ConcertoPayload(ConcertoPayload.Channel.MUSIC_AGENT, "Quit"));
202+
ConcertoClient.clientState = ConcertoClient.ClientState.LOCAL;
203+
}
204+
205+
public static void musicAgentNewVote() {
206+
ClientPlayNetworking.send(new ConcertoPayload(ConcertoPayload.Channel.MUSIC_AGENT, "Vote:New"));
207+
}
208+
209+
public static void musicAgentQuery() {
210+
ClientPlayNetworking.send(new ConcertoPayload(ConcertoPayload.Channel.MUSIC_AGENT, "Query"));
211+
}
212+
213+
public static void musicAgentVote(boolean vote) {
214+
ClientPlayNetworking.send(new ConcertoPayload(ConcertoPayload.Channel.MUSIC_AGENT, "Vote:" + (vote ? "1" : "0")));
215+
}
216+
217+
public static boolean musicAgentAddCurrentMusic() {
218+
return MusicPlayerHandler.INSTANCE.getCurrentMusic() != null &&
219+
musicAgentAddMusic(MusicPlayerHandler.INSTANCE.getCurrentMusic());
220+
}
221+
222+
public static boolean musicAgentAddMusic(Music music) {
223+
JsonObject object = MusicJsonParsers.to(music);
224+
if (object == null) return false;
225+
ClientPlayNetworking.send(new ConcertoPayload(ConcertoPayload.Channel.MUSIC_AGENT,
226+
"Add:" + TextUtil.toBase64(object.toString())));
227+
return true;
228+
}
229+
230+
public static void musicAgentMusicReceiver(ConcertoPayload payload, ClientPlayNetworking.Context context) {
231+
String[] args = payload.string.split(":");
232+
if (args.length < 2 || ConcertoClient.clientState != ConcertoClient.ClientState.MUSIC_AGENT) return;
233+
MusicPlayer.run(() -> {
234+
Music music = MusicJsonParsers.from(TextUtil.fromBase64(args[0]));
235+
if (music != null) MusicPlayer.INSTANCE.playTempMusic(music);
236+
});
237+
}
193238
}

src/main/java/top/gregtao/concerto/network/ConcertoPayload.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ public enum Channel {
4040
HANDSHAKE('1'),
4141
AUDITION_SYNC('2'),
4242
MUSIC_ROOM('3'),
43-
PRESET_RADIOS('4');
43+
PRESET_RADIOS('4'),
44+
MUSIC_AGENT('5');
4445

4546
public static Channel getById(char id) {
4647
for (Channel channel1 : values()) {

src/main/java/top/gregtao/concerto/network/MusicNetworkChannels.java

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/main/java/top/gregtao/concerto/network/MusicRoom.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ public static void clientReceiver(ConcertoPayload payload, ClientPlayNetworking.
263263
switch (args[0]) {
264264
case "REM": {
265265
CLIENT_ROOM = null;
266+
ConcertoClient.clientState = ConcertoClient.ClientState.LOCAL;
266267
break;
267268
}
268269
case "JOI": {
@@ -287,6 +288,7 @@ public static void clientReceiver(ConcertoPayload payload, ClientPlayNetworking.
287288
if (CLIENT_ROOM.pause) MusicPlayer.INSTANCE.pause();
288289
});
289290
}
291+
ConcertoClient.clientState = ConcertoClient.ClientState.MUSIC_ROOM;
290292
player.sendMessage(Text.translatable("concerto.room.join", uuid1.toString()), false);
291293
} catch (NullPointerException | IllegalArgumentException e) {
292294
ConcertoClient.LOGGER.warn(e.toString());
@@ -299,6 +301,7 @@ public static void clientReceiver(ConcertoPayload payload, ClientPlayNetworking.
299301
try {
300302
UUID uuid1 = UUID.fromString(args[1]);
301303
if (CLIENT_ROOM.uuid.compareTo(uuid1) == 0) CLIENT_ROOM = null;
304+
ConcertoClient.clientState = ConcertoClient.ClientState.LOCAL;
302305
player.sendMessage(Text.translatable("concerto.room.quit", uuid1.toString()), false);
303306
} catch (NullPointerException | IllegalArgumentException e) {
304307
ConcertoClient.LOGGER.warn(e.toString());

0 commit comments

Comments
 (0)