废了,回退

This commit is contained in:
BRanulf 2025-04-28 18:50:46 +08:00
parent 5369823d2b
commit 79a935fd61
7 changed files with 211 additions and 32 deletions

View File

@ -6,7 +6,7 @@ minecraft_version=1.21.4
yarn_mappings=1.21.4+build.8 yarn_mappings=1.21.4+build.8
loader_version=0.16.10 loader_version=0.16.10
# Mod Properties # Mod Properties
mod_version=1.14.514.021 mod_version=1.14.514.022
maven_group=semmiedev maven_group=semmiedev
archives_base_name=disc_jockey_revive archives_base_name=disc_jockey_revive
# Dependencies # Dependencies

View File

@ -20,6 +20,7 @@ import net.minecraft.util.Formatting;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import semmiedev.disc_jockey_revive.gui.SongListWidget;
import semmiedev.disc_jockey_revive.gui.hud.BlocksOverlay; import semmiedev.disc_jockey_revive.gui.hud.BlocksOverlay;
import semmiedev.disc_jockey_revive.gui.screen.DiscJockeyScreen; import semmiedev.disc_jockey_revive.gui.screen.DiscJockeyScreen;
@ -38,6 +39,15 @@ public class Main implements ClientModInitializer {
public static ModConfig config; public static ModConfig config;
public static ConfigHolder<ModConfig> configHolder; public static ConfigHolder<ModConfig> configHolder;
public static KeyBinding nextSongKeyBind;
// public static KeyBinding prevSongKeyBind;
static KeyBinding playStopKeyBind;
public static KeyBinding reloadKeyBind;
private static long lastNextSongPress = 0;
public MinecraftClient client;
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
configHolder = AutoConfig.register(ModConfig.class, JanksonConfigSerializer::new); configHolder = AutoConfig.register(ModConfig.class, JanksonConfigSerializer::new);
@ -48,8 +58,40 @@ public class Main implements ClientModInitializer {
SongLoader.loadSongs(); SongLoader.loadSongs();
// 打开菜单
KeyBinding openScreenKeyBind = KeyBindingHelper.registerKeyBinding(new KeyBinding(MOD_ID+".key_bind.open_screen", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_J, "key.category."+MOD_ID)); KeyBinding openScreenKeyBind = KeyBindingHelper.registerKeyBinding(new KeyBinding(MOD_ID+".key_bind.open_screen", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_J, "key.category."+MOD_ID));
// 下一首和上一首快捷键
nextSongKeyBind = KeyBindingHelper.registerKeyBinding(new KeyBinding(
MOD_ID+".key_bind.next_song",
InputUtil.Type.KEYSYM,
InputUtil.UNKNOWN_KEY.getCode(), // Default to unbound
"key.category."+MOD_ID
));
// 上一首不要了没啥用
// prevSongKeyBind = KeyBindingHelper.registerKeyBinding(new KeyBinding(
// MOD_ID+".key_bind.prev_song",
// InputUtil.Type.KEYSYM,
// InputUtil.UNKNOWN_KEY.getCode(), // Default to unbound
// "key.category."+MOD_ID
// ));
// 停止
playStopKeyBind = KeyBindingHelper.registerKeyBinding(new KeyBinding(
MOD_ID+".key_bind.play_stop",
InputUtil.Type.KEYSYM,
InputUtil.UNKNOWN_KEY.getCode(), // Default unbound
"key.category."+MOD_ID
));
// 重载
reloadKeyBind = KeyBindingHelper.registerKeyBinding(new KeyBinding(
MOD_ID+".key_bind.reload",
InputUtil.Type.KEYSYM,
InputUtil.UNKNOWN_KEY.getCode(), // Default unbound
"key.category."+MOD_ID
));
ClientTickEvents.START_CLIENT_TICK.register(new ClientTickEvents.StartTick() { ClientTickEvents.START_CLIENT_TICK.register(new ClientTickEvents.StartTick() {
private ClientWorld prevWorld; private ClientWorld prevWorld;
@ -69,9 +111,31 @@ public class Main implements ClientModInitializer {
client.setScreen(new DiscJockeyScreen()); client.setScreen(new DiscJockeyScreen());
} }
} }
if (nextSongKeyBind.wasPressed()) {
if (SONG_PLAYER.running) {
SONG_PLAYER.playNextSong();
}
}
// if (prevSongKeyBind.wasPressed()) {
// SONG_PLAYER.playPreviousSong();
// }
if (playStopKeyBind.wasPressed()) {
if (SONG_PLAYER.running) {
SONG_PLAYER.stop();
}
}
if (reloadKeyBind.wasPressed()) {
SongLoader.loadSongs();
if (client.currentScreen instanceof DiscJockeyScreen) {
client.setScreen(new DiscJockeyScreen());
}
}
} }
}); });
ClientTickEvents.START_WORLD_TICK.register(world -> { ClientTickEvents.START_WORLD_TICK.register(world -> {
for (ClientTickEvents.StartWorldTick listener : TICK_LISTENERS) listener.onStartTick(world); for (ClientTickEvents.StartWorldTick listener : TICK_LISTENERS) listener.onStartTick(world);
}); });

View File

@ -2,6 +2,7 @@ package semmiedev.disc_jockey_revive;
import me.shedaniel.autoconfig.ConfigData; import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.annotation.ConfigEntry; import me.shedaniel.autoconfig.annotation.ConfigEntry;
import net.minecraft.text.Text;
import java.util.ArrayList; import java.util.ArrayList;
@ -37,6 +38,29 @@ public class ModConfig implements ConfigData {
} }
} }
public enum ErrorHandlingMode {
STOP_PLAYBACK(Text.translatable(Main.MOD_ID+".config.error_handling.stop")),
PLAY_NEXT(Text.translatable(Main.MOD_ID+".config.error_handling.next"));
private final Text displayText;
ErrorHandlingMode(Text displayText) {
this.displayText = displayText;
}
public Text getDisplayText() {
return displayText;
}
@Override
public String toString() {
return displayText.getString();
}
}
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
public ErrorHandlingMode errorHandlingMode = ErrorHandlingMode.STOP_PLAYBACK;
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
@ConfigEntry.Gui.Tooltip(count = 4) @ConfigEntry.Gui.Tooltip(count = 4)
public ExpectedServerVersion expectedServerVersion = ExpectedServerVersion.All; public ExpectedServerVersion expectedServerVersion = ExpectedServerVersion.All;

View File

@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class SongPlayer implements ClientTickEvents.StartWorldTick { public class SongPlayer implements ClientTickEvents.StartWorldTick {
@ -98,7 +99,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
STOP_AFTER // 播完就停 STOP_AFTER // 播完就停
} }
private PlayMode playMode = PlayMode.STOP_AFTER; public PlayMode playMode = PlayMode.STOP_AFTER;
private boolean isRandomPlaying = false; private boolean isRandomPlaying = false;
private int randomIndex = -1; private int randomIndex = -1;
@ -160,6 +161,27 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
didSongReachEnd = false; // Change after running stop() if actually ended cleanly didSongReachEnd = false; // Change after running stop() if actually ended cleanly
} }
public synchronized void playPreviousSong() {
if (!running || song == null) return;
if (SongLoader.currentFolder == null || SongLoader.currentFolder.songs.isEmpty()) return;
int currentIndex = SongLoader.currentFolder.songs.indexOf(song);
if (currentIndex == -1) return;
if (playMode == PlayMode.RANDOM) {
int newIndex;
do {
newIndex = (int) (Math.random() * SongLoader.currentFolder.songs.size());
} while (newIndex == currentIndex && SongLoader.currentFolder.songs.size() > 1);
start(SongLoader.currentFolder.songs.get(newIndex));
} else {
int prevIndex = (currentIndex - 1 + SongLoader.currentFolder.songs.size()) % SongLoader.currentFolder.songs.size();
start(SongLoader.currentFolder.songs.get(prevIndex));
}
}
public synchronized void tickPlayback() { public synchronized void tickPlayback() {
if (!running) { if (!running) {
lastPlaybackTickAt = -1L; lastPlaybackTickAt = -1L;
@ -197,8 +219,14 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
continue; continue;
} }
if (!canInteractWith(client.player, blockPos)) { if (!canInteractWith(client.player, blockPos)) {
stop(); if (Main.config.errorHandlingMode == ModConfig.ErrorHandlingMode.PLAY_NEXT) {
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.to_far").formatted(Formatting.RED)); playNextSong();
} else {
stop();
if (client.player != null) {
client.player.sendMessage(Text.translatable(Main.MOD_ID+".player.to_far").formatted(Formatting.RED), false);
}
}
return; return;
} }
Vec3d unit = Vec3d.ofCenter(blockPos, 0.5).subtract(client.player.getEyePos()).normalize(); Vec3d unit = Vec3d.ofCenter(blockPos, 0.5).subtract(client.player.getEyePos()).normalize();
@ -256,24 +284,39 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
} }
} }
private void playNextSong() { public synchronized void playNextSong() {
if (SongLoader.currentFolder == null || SongLoader.currentFolder.songs.isEmpty()) return; if (!running || song == null) return;
int currentIndex = SongLoader.currentFolder.songs.indexOf(song); if (SongLoader.currentFolder == null ||
if (currentIndex == -1) return; (SongLoader.currentFolder.songs.isEmpty() && SongLoader.SONGS.isEmpty())) {
return;
}
List<Song> availableSongs = SongLoader.currentFolder != null ?
SongLoader.currentFolder.songs : SongLoader.SONGS;
if (availableSongs.isEmpty()) return;
if (playMode == PlayMode.RANDOM) { if (playMode == PlayMode.RANDOM) {
// 随机播放
int newIndex; int newIndex;
do { do {
newIndex = (int) (Math.random() * SongLoader.currentFolder.songs.size()); newIndex = (int)(Math.random() * availableSongs.size());
} while (newIndex == currentIndex && SongLoader.currentFolder.songs.size() > 1); } while (availableSongs.size() > 1 &&
start(SongLoader.currentFolder.songs.get(newIndex)); availableSongs.get(newIndex).fileName.equals(song.fileName));
} else if (playMode == PlayMode.LIST_LOOP) {
int nextIndex = (currentIndex + 1) % SongLoader.currentFolder.songs.size(); start(availableSongs.get(newIndex));
start(SongLoader.currentFolder.songs.get(nextIndex)); }
else { // 列表循环和单曲循环
int currentIndex = availableSongs.indexOf(song);
if (currentIndex == -1) return;
int nextIndex = (currentIndex + 1) % availableSongs.size();
start(availableSongs.get(nextIndex));
} }
} }
public synchronized void setPlayMode(PlayMode mode) { public synchronized void setPlayMode(PlayMode mode) {
this.playMode = mode; this.playMode = mode;
this.loopSong = mode == PlayMode.SINGLE_LOOP; this.loopSong = mode == PlayMode.SINGLE_LOOP;

View File

@ -9,10 +9,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.text.MutableText; import net.minecraft.text.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import semmiedev.disc_jockey_revive.Main; import semmiedev.disc_jockey_revive.*;
import semmiedev.disc_jockey_revive.Note;
import semmiedev.disc_jockey_revive.Song;
import semmiedev.disc_jockey_revive.SongLoader;
import semmiedev.disc_jockey_revive.gui.SongListWidget; import semmiedev.disc_jockey_revive.gui.SongListWidget;
import semmiedev.disc_jockey_revive.gui.hud.BlocksOverlay; import semmiedev.disc_jockey_revive.gui.hud.BlocksOverlay;
@ -34,26 +31,25 @@ public class DiscJockeyScreen extends Screen {
PLAY_STOP = Text.translatable(Main.MOD_ID+".screen.play.stop"), PLAY_STOP = Text.translatable(Main.MOD_ID+".screen.play.stop"),
PREVIEW = Text.translatable(Main.MOD_ID+".screen.preview"), PREVIEW = Text.translatable(Main.MOD_ID+".screen.preview"),
PREVIEW_STOP = Text.translatable(Main.MOD_ID+".screen.preview.stop"), PREVIEW_STOP = Text.translatable(Main.MOD_ID+".screen.preview.stop"),
DROP_HINT = Text.translatable(Main.MOD_ID+".screen.drop_hint").formatted(Formatting.GRAY) DROP_HINT = Text.translatable(Main.MOD_ID+".screen.drop_hint").formatted(Formatting.GRAY),
;
private SongListWidget songListWidget;
private ButtonWidget playButton, previewButton;
public boolean shouldFilter;
private String query = "";
private static final MutableText
FOLDER_UP = Text.literal(""), FOLDER_UP = Text.literal(""),
CURRENT_FOLDER = Text.translatable(Main.MOD_ID+".screen.current_folder"), CURRENT_FOLDER = Text.translatable(Main.MOD_ID+".screen.current_folder"),
PLAY_MODE = Text.translatable(Main.MOD_ID+".screen.play_mode"), PLAY_MODE = Text.translatable(Main.MOD_ID+".screen.play_mode"),
MODE_SINGLE = Text.translatable(Main.MOD_ID+".screen.mode_single"), MODE_SINGLE = Text.translatable(Main.MOD_ID+".screen.mode_single"),
MODE_LIST = Text.translatable(Main.MOD_ID+".screen.mode_list"), MODE_LIST = Text.translatable(Main.MOD_ID+".screen.mode_list"),
MODE_RANDOM = Text.translatable(Main.MOD_ID+".screen.mode_random"), MODE_RANDOM = Text.translatable(Main.MOD_ID+".screen.mode_random"),
MODE_STOP = Text.translatable(Main.MOD_ID+".screen.mode_stop"); MODE_STOP = Text.translatable(Main.MOD_ID+".screen.mode_stop"),
private static final MutableText
OPEN_FOLDER = Text.translatable(Main.MOD_ID+".screen.open_folder"), OPEN_FOLDER = Text.translatable(Main.MOD_ID+".screen.open_folder"),
RELOAD = Text.translatable(Main.MOD_ID+".screen.reload"); RELOAD = Text.translatable(Main.MOD_ID+".screen.reload"),
NEXT_SONG = Text.translatable(Main.MOD_ID+".screen.next_song"),
PREV_SONG = Text.translatable(Main.MOD_ID+".screen.prev_song");
public SongListWidget songListWidget;
private ButtonWidget playButton, previewButton;
public boolean shouldFilter;
private String query = "";
private ButtonWidget folderUpButton, playModeButton; private ButtonWidget folderUpButton, playModeButton;
public SongFolder currentFolder; public SongFolder currentFolder;
@ -209,6 +205,38 @@ public class DiscJockeyScreen extends Screen {
client.setScreen(null); client.setScreen(null);
}).dimensions(width / 2 + 60, height - 31, 100, 20).build()); }).dimensions(width / 2 + 60, height - 31, 100, 20).build());
// 下一首
addDrawableChild(ButtonWidget.builder(NEXT_SONG, button -> {
SongPlayer player = Main.SONG_PLAYER;
if (player.running) {
player.playNextSong();
} else {
SongListWidget.SongEntry entry = songListWidget.getSelectedSongOrNull();
if (entry != null) {
List<Song> availableSongs = SongLoader.currentFolder != null ?
SongLoader.currentFolder.songs : SongLoader.SONGS;
int currentIndex = availableSongs.indexOf(entry.song);
if (currentIndex != -1) {
int nextIndex;
if (player.playMode == PlayMode.RANDOM) {
// Get random song in menu too
do {
nextIndex = (int)(Math.random() * availableSongs.size());
} while (availableSongs.size() > 1 && nextIndex == currentIndex);
} else {
nextIndex = (currentIndex + 1) % availableSongs.size();
}
songListWidget.setSelected(availableSongs.get(nextIndex).entry);
}
}
}
}).dimensions(width / 2 + 60 + 110 + 5, height - 61, 100, 20).build());
// 搜索框
TextFieldWidget searchBar = new TextFieldWidget(textRenderer, width / 2 - 50, height - 31, 100, 20, Text.translatable(Main.MOD_ID+".screen.search")); TextFieldWidget searchBar = new TextFieldWidget(textRenderer, width / 2 - 50, height - 31, 100, 20, Text.translatable(Main.MOD_ID+".screen.search"));
searchBar.setChangedListener(query -> { searchBar.setChangedListener(query -> {
query = query.toLowerCase().replaceAll("\\s", ""); query = query.toLowerCase().replaceAll("\\s", "");

View File

@ -61,5 +61,15 @@
"disc_jockey_revive.screen.open_folder": "Open Folder", "disc_jockey_revive.screen.open_folder": "Open Folder",
"disc_jockey_revive.screen.open_folder_failed": "Failed to open folder", "disc_jockey_revive.screen.open_folder_failed": "Failed to open folder",
"disc_jockey_revive.screen.reload": "Reload Songs", "disc_jockey_revive.screen.reload": "Reload Songs",
"disc_jockey_revive.screen.reloading": "Reloading songs..." "disc_jockey_revive.screen.reloading": "Reloading songs...",
"disc_jockey_revive.screen.next_song": "Next Song",
"disc_jockey_revive.screen.prev_song": "Previous Song",
"disc_jockey_revive.key_bind.next_song": "Next Song",
"disc_jockey_revive.key_bind.prev_song": "Previous Song",
"text.autoconfig.disc_jockey_revive.option.errorHandlingMode": "Error Handling",
"text.autoconfig.disc_jockey_revive.option.errorHandlingMode.@Tooltip": "What to do when errors occur",
"disc_jockey_revive.config.error_handling.stop": "Stop Playback",
"disc_jockey_revive.config.error_handling.next": "Play Next Song",
"disc_jockey_revive.key_bind.play_stop": "Play/Stop",
"disc_jockey_revive.key_bind.reload": "Reload"
} }

View File

@ -60,5 +60,15 @@
"disc_jockey_revive.screen.mode_stop": "播完停止","disc_jockey_revive.screen.open_folder": "打开文件夹", "disc_jockey_revive.screen.mode_stop": "播完停止","disc_jockey_revive.screen.open_folder": "打开文件夹",
"disc_jockey_revive.screen.open_folder_failed": "无法打开文件夹", "disc_jockey_revive.screen.open_folder_failed": "无法打开文件夹",
"disc_jockey_revive.screen.reload": "重新加载", "disc_jockey_revive.screen.reload": "重新加载",
"disc_jockey_revive.screen.reloading": "正在重新加载..." "disc_jockey_revive.screen.reloading": "正在重新加载...",
"disc_jockey_revive.screen.next_song": "下一首",
"disc_jockey_revive.screen.prev_song": "上一首",
"disc_jockey_revive.key_bind.next_song": "下一首",
"disc_jockey_revive.key_bind.prev_song": "上一首",
"text.autoconfig.disc_jockey_revive.option.errorHandlingMode": "错误处理",
"text.autoconfig.disc_jockey_revive.option.errorHandlingMode.@Tooltip": "播放错误时的处理方式",
"disc_jockey_revive.config.error_handling.stop": "停止播放",
"disc_jockey_revive.config.error_handling.next": "播放下一首",
"disc_jockey_revive.key_bind.play_stop": "播放/停止",
"disc_jockey_revive.key_bind.reload": "重新加载"
} }