Skip to content

Commit 451697b

Browse files
committed
feat. 完善服务器点歌功能
1 parent b8fec69 commit 451697b

File tree

7 files changed

+93
-17
lines changed

7 files changed

+93
-17
lines changed

src/main/java/top/gregtao/concerto/config/ClientConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public static class ClientConfigOptions {
4545
public boolean printRequestResults = false;
4646
public int maxCacheSize = 1000 * 1000 * 100;
4747
public boolean displayLyrics = true;
48+
public boolean joinAgentWhenInvited = false;
4849
public String lyricsPosition = "0.5,1-70";
4950
public TextAlignment lyricsAlignment = TextAlignment.CENTER;
5051
public boolean displaySubLyrics = true;

src/main/java/top/gregtao/concerto/config/ServerConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public void writeOptions() {
2424

2525
public static class ServerConfigOptions {
2626
public boolean auditionRequired = true;
27+
public boolean serverMusicAgent = true;
28+
public boolean agentInviteWhenJoin = true;
2729
public int musicRoomCommandPermission = 2;
2830
}
2931
}

src/main/java/top/gregtao/concerto/http/HttpURLInputStream.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.io.IOException;
77
import java.io.InputStream;
88
import java.net.HttpURLConnection;
9+
import java.net.MalformedURLException;
910
import java.net.URI;
1011
import java.net.URL;
1112
import java.util.function.Supplier;
@@ -45,6 +46,24 @@ public HttpURLInputStream(URL url) throws IOException {
4546
this(url, 0, null);
4647
}
4748

49+
public static int getTotalBytes(URL url) {
50+
try(HttpURLInputStream stream = new HttpURLInputStream(url)) {
51+
return stream.szBytes;
52+
} catch (IOException e) {
53+
ConcertoClient.LOGGER.error(e.getMessage());
54+
return 0;
55+
}
56+
}
57+
58+
public static int getTotalBytes(String url) {
59+
try {
60+
return getTotalBytes(URI.create(url).toURL());
61+
} catch (MalformedURLException e) {
62+
ConcertoClient.LOGGER.error(e.getMessage());
63+
return 0;
64+
}
65+
}
66+
4867
private HttpURLConnection openNewConnection() throws IOException {
4968
HttpURLConnection conn = (HttpURLConnection) this.url.openConnection();
5069
conn.setConnectTimeout(5000);

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import net.minecraft.client.network.ClientPlayerEntity;
77
import net.minecraft.entity.player.PlayerEntity;
88
import net.minecraft.server.MinecraftServer;
9+
import net.minecraft.text.Style;
910
import net.minecraft.text.Text;
11+
import net.minecraft.util.Formatting;
1012
import top.gregtao.concerto.ConcertoClient;
1113
import top.gregtao.concerto.api.MusicJsonParsers;
1214
import top.gregtao.concerto.command.ShareMusicCommand;
@@ -161,6 +163,19 @@ public static void playerJoinHandshake(ConcertoPayload payload, ClientPlayNetwor
161163
if (player != null && playerName.equals(player.getName().getString())) {
162164
ConcertoClient.serverAvailable = true;
163165
ConcertoClient.LOGGER.info("Concerto has been installed in this server");
166+
if (args.length > 3 && args[3].equals("Invite")) {
167+
if (ClientConfig.INSTANCE.options.joinAgentWhenInvited) {
168+
player.networkHandler.sendChatCommand("/musicroom agent join");
169+
} else {
170+
player.sendMessage(TextUtil.PAGE_SPLIT, false);
171+
player.sendMessage(Text.translatable("concerto.agent.invite")
172+
.append(Text.literal(" ["))
173+
.append(Text.translatable("concerto.accept").setStyle(
174+
TextUtil.getRunCommandStyle("/musicroom agent join").withColor(Formatting.GREEN)))
175+
.append(Text.literal("]")), false);
176+
player.sendMessage(TextUtil.PAGE_SPLIT, false);
177+
}
178+
}
164179
}
165180
}
166181
}

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

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import net.minecraft.server.network.ServerPlayerEntity;
44
import net.minecraft.text.Text;
55
import top.gregtao.concerto.ConcertoServer;
6+
import top.gregtao.concerto.api.DynamicPath;
7+
import top.gregtao.concerto.http.HttpURLInputStream;
68
import top.gregtao.concerto.music.Music;
9+
import top.gregtao.concerto.music.SharedMusic;
10+
import top.gregtao.concerto.player.MusicPlayer;
711

812
import java.util.ArrayList;
913
import java.util.List;
@@ -28,6 +32,9 @@ public class ServerMusicAgent {
2832
private ScheduledFuture<?> playNextFuture;
2933
private final ConcurrentLinkedQueue<Music> musicQueue = new ConcurrentLinkedQueue<>();
3034
private Music currentMusic = null;
35+
private Music currentSharedMusic = null;
36+
private int totalBytes = 0;
37+
private long playTime = 0;
3138

3239
private final AtomicBoolean isPlaying = new AtomicBoolean(false);
3340

@@ -84,42 +91,68 @@ private synchronized void endVoting() {
8491
ConcertoServer.LOGGER.info("Vote: Keep current music");
8592
}
8693
Text text = success ? Text.translatable("concerto.agent.vote.success") : Text.translatable("concerto.agent.vote.failed");
87-
this.members.forEach(player -> player.sendMessage(text, false));
94+
this.broadcast(text);
8895

8996
this.isVoting = false;
9097
}
9198

9299
private synchronized void playNextMusic() {
93100
this.currentMusic = this.musicQueue.poll();
101+
this.currentSharedMusic = null;
102+
this.totalBytes = 0;
103+
this.playTime = 0;
94104
if (this.currentMusic == null) {
95105
ConcertoServer.LOGGER.info("Music agent paused");
96106
this.isPlaying.set(false);
97107
} else {
98108
ConcertoServer.LOGGER.info("Start playing music {}", this.currentMusic.getMeta().title());
109+
if (this.currentMusic instanceof DynamicPath dynamicPath) {
110+
String path = dynamicPath.getLastRawPath();
111+
if (path != null) this.totalBytes = HttpURLInputStream.getTotalBytes(path);
112+
else {
113+
ConcertoServer.LOGGER.warn("Cannot play music {}", this.currentMusic.getMeta().title());
114+
this.broadcast(Text.translatable("concerto.agent.play.failed"));
115+
this.playNextFuture = this.musicScheduler.schedule(this::playNextMusic, 1, TimeUnit.SECONDS);
116+
return;
117+
}
118+
this.currentSharedMusic = new SharedMusic(path, this.currentMusic.getMeta(),
119+
dynamicPath.getLastLyrics(), dynamicPath.getLastSubLyrics());
120+
} else {
121+
this.currentSharedMusic = this.currentMusic;
122+
}
99123
this.isPlaying.set(true);
100-
ServerMusicNetworkHandler.musicAgentSendMusic(this.members, this.currentMusic, 0);
124+
this.playTime = System.currentTimeMillis();
125+
ServerMusicNetworkHandler.musicAgentSendMusic(this.members, this.currentSharedMusic, 0);
101126
this.playNextFuture = this.musicScheduler.schedule(this::playNextMusic,
102127
this.currentMusic.getMeta().getDuration().asSeconds(), TimeUnit.SECONDS);
103128
}
104129
}
105130

131+
public void broadcast(Text text) {
132+
this.members.forEach(player -> player.sendMessage(text, false));
133+
}
134+
106135
public synchronized boolean isMember(ServerPlayerEntity player) {
107136
return this.members.contains(player);
108137
}
109138

110139
public synchronized void addMusic(Music music) {
111-
ConcertoServer.LOGGER.info("Added music {}", music.getMeta().title());
112-
this.musicQueue.offer(music);
113-
if (!this.isPlaying.get()) {
114-
this.playNextFuture = this.musicScheduler.schedule(this::playNextMusic, 1, TimeUnit.SECONDS);
115-
}
140+
MusicPlayer.run(() -> {
141+
ConcertoServer.LOGGER.info("Added music {}", music.getMeta().title());
142+
this.musicQueue.offer(music);
143+
if (!this.isPlaying.get()) {
144+
this.playNextFuture = this.musicScheduler.schedule(this::playNextMusic, 1, TimeUnit.SECONDS);
145+
}
146+
});
116147
}
117148

118149
public synchronized void playerJoin(ServerPlayerEntity player) {
119150
ConcertoServer.LOGGER.info("Player {} joined music agent", player.getName().getString());
120151
this.members.add(player);
121-
if (this.isPlaying.get() && this.currentMusic != null) {
122-
ServerMusicNetworkHandler.musicAgentSendMusic(this.members, this.currentMusic, 0);
152+
if (this.isPlaying.get() && this.currentSharedMusic != null) {
153+
ServerMusicNetworkHandler.musicAgentSendMusic(player, this.currentSharedMusic,
154+
this.totalBytes * (System.currentTimeMillis() - this.playTime) /
155+
this.currentMusic.getMeta().getDuration().asMilliseconds());
123156
}
124157
}
125158

@@ -141,7 +174,9 @@ public synchronized void reset() {
141174
this.playNextFuture.cancel(false);
142175
}
143176
this.musicQueue.clear();
144-
this.currentMusic = null;
177+
this.currentMusic = this.currentSharedMusic = null;
178+
this.totalBytes = 0;
179+
this.playTime = 0;
145180
this.isPlaying.set(false);
146181

147182
ConcertoServer.LOGGER.info("Reset server music agent");

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ public static void musicDataReceiver(ConcertoPayload payload, ServerPlayNetworki
204204

205205
public static void playerJoinHandshake(ServerPlayerEntity player) {
206206
ConcertoPayload payload = new ConcertoPayload(ConcertoPayload.Channel.HANDSHAKE,
207-
ConcertoNetworking.HANDSHAKE_STRING + "CallJoin:" + player.getName().getString());
207+
ConcertoNetworking.HANDSHAKE_STRING + "CallJoin:" + player.getName().getString()
208+
+ (ServerConfig.INSTANCE.options.agentInviteWhenJoin ? ":Invite" : ""));
208209
ServerPlayNetworking.send(player, payload);
209210
sendS2CAllAuditionData(player);
210211
sendS2CPresetRadiosPacket(player);
@@ -233,6 +234,10 @@ public static void musicAgentSendMusic(List<ServerPlayerEntity> players, Music m
233234
}
234235

235236
public static void musicAgentReceiver(ConcertoPayload payload, ServerPlayNetworking.Context context) {
237+
if (!ServerConfig.INSTANCE.options.serverMusicAgent) {
238+
context.player().sendMessage(Text.translatable("concerto.agent.not_available"));
239+
return;
240+
}
236241
String[] args = payload.string.split(":");
237242
if (args[0].equals("Join")) {
238243
ServerMusicAgent.INSTANCE.playerJoin(context.player());
@@ -243,7 +248,8 @@ public static void musicAgentReceiver(ConcertoPayload payload, ServerPlayNetwork
243248
} else if (args[0].equals("Query")) {
244249
List<Music> list = ServerMusicAgent.INSTANCE.getMusicQueue();
245250
context.player().sendMessage(TextUtil.PAGE_SPLIT);
246-
list.forEach(music -> context.player().sendMessage(Text.literal(music.getMeta().title())));
251+
list.forEach(music -> context.player().sendMessage(Text.literal(
252+
music.getMeta().title() + " - " + music.getMeta().author())));
247253
context.player().sendMessage(TextUtil.PAGE_SPLIT);
248254
} else if (args.length < 2 || !ServerMusicAgent.INSTANCE.isMember(context.player())) {
249255
context.player().sendMessage(Text.translatable("concerto.agent.error"));
@@ -260,8 +266,8 @@ public static void musicAgentReceiver(ConcertoPayload payload, ServerPlayNetwork
260266
context.player().sendMessage(Text.translatable("concerto.agent.error"));
261267
}
262268
} else if (args[0].equals("Add")) {
263-
Music music = MusicJsonParsers.from(TextUtil.fromBase64(args[1]));
264-
if (music != null && music.isLoaded()) {
269+
Music music = MusicJsonParsers.from(TextUtil.fromBase64(args[1]), false);
270+
if (music != null) {
265271
ServerMusicAgent.INSTANCE.addMusic(music);
266272
} else {
267273
context.player().sendMessage(Text.translatable("concerto.agent.error"));

src/main/java/top/gregtao/concerto/player/MusicPlayerHandler.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import top.gregtao.concerto.api.CacheableMusic;
77
import top.gregtao.concerto.api.LazyLoadable;
88
import top.gregtao.concerto.api.MusicJsonParsers;
9-
import top.gregtao.concerto.music.SharedMusic;
109
import top.gregtao.concerto.music.lyrics.Lyrics;
1110
import top.gregtao.concerto.music.meta.music.MusicMetaData;
1211
import top.gregtao.concerto.enums.OrderType;
@@ -154,8 +153,7 @@ private void removeMusic(int size) {
154153
public void updateDisplayTexts() {
155154
if (this.currentMeta != null) {
156155
this.displayTexts[2] = TextUtil.cutIfTooLong(this.currentMeta.title(), 50) + " | " +
157-
TextUtil.cutIfTooLong(this.currentMeta.author(), 40) + " | " + this.currentMeta.getSource() +
158-
(this.currentMusic instanceof SharedMusic ? ", " + Text.translatable("concerto.room").getString() : "");
156+
TextUtil.cutIfTooLong(this.currentMeta.author(), 40) + " | " + this.currentMeta.getSource();
159157
MusicTimestamp timestamp = this.currentMeta.getDuration();
160158
this.timeFormat = "%s" + (timestamp == null ? "" : " ".repeat(30) + this.currentMeta.getDuration().toShortString());
161159
} else {

0 commit comments

Comments
 (0)