From 8783c4cb9533b72256a3ec99d88b205d9fc2b83c Mon Sep 17 00:00:00 2001 From: Andrew <109876401+andrewdotdev@users.noreply.github.com> Date: Thu, 3 Apr 2025 21:23:39 +0200 Subject: [PATCH 1/3] feat: Functional use of the walkie-talkie and added README --- README.md | 28 +++++- build.gradle | 4 +- .../andrewdotdev/mbwalkie/MumbleWalkie.java | 4 + .../mbwalkie/MumbleWalkieClient.java | 5 +- .../mbwalkie/client/ClientEvents.java | 73 ++++++++++++++ .../mbwalkie/client/Keybinds.java | 19 ++++ .../mbwalkie/commands/WalkieCommands.java | 36 +++++++ .../mbwalkie/config/ConfigManager.java | 47 +++++++++ .../mbwalkie/config/mbwalkie_config.json | 4 + .../mbwalkie/mumble/MumbleClient.java | 89 ++++++++++++++++++ .../mbwalkie/models/item/walkie_talkie.json | 2 +- .../resources/assets/mbwalkie/sounds.json | 11 +++ .../assets/mbwalkie/sounds/walkie_end.ogg | Bin 0 -> 6746 bytes .../assets/mbwalkie/sounds/walkie_start.ogg | Bin 0 -> 6122 bytes .../assets/mbwalkie/sounds/walkie_static.ogg | Bin 0 -> 14437 bytes 15 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java create mode 100644 src/main/java/com/andrewdotdev/mbwalkie/client/Keybinds.java create mode 100644 src/main/java/com/andrewdotdev/mbwalkie/commands/WalkieCommands.java create mode 100644 src/main/java/com/andrewdotdev/mbwalkie/config/ConfigManager.java create mode 100644 src/main/java/com/andrewdotdev/mbwalkie/config/mbwalkie_config.json create mode 100644 src/main/java/com/andrewdotdev/mbwalkie/mumble/MumbleClient.java create mode 100644 src/main/resources/assets/mbwalkie/sounds.json create mode 100644 src/main/resources/assets/mbwalkie/sounds/walkie_end.ogg create mode 100644 src/main/resources/assets/mbwalkie/sounds/walkie_start.ogg create mode 100644 src/main/resources/assets/mbwalkie/sounds/walkie_static.ogg diff --git a/README.md b/README.md index 3b29a46..65f0981 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,25 @@ -# Mumble Walkie - -In development +# Mumble Walkie (in development) + +Mumble Walkie is a Minecraft Modification for Fabric that brings real-time voice communication to the game. This mod integrates with Mumble, a voice chat platform, allowing players to communicate via a virtual radio channel. + +### Key Features: +- **Walkie-Talkie Item:** A custom item that players can hold in their hands to communicate with others. +- **Real-time Voice Chat:** Integrates with Mumble to enable voice chat between players within the proximity of the radio signal. +- **Sound Effects:** Realistic radio sound effects such as static, tuning, and voice transmission when interacting with the radio. +- **Mumble Server Configuration:** Players can configure the Mumble server directly from within Minecraft. +- **Voice Proximity:** Volume and voice distance are adjusted based on the player's position in the game world. +- **Interference Sounds:** When there is a storm, rain, or snow, players will hear radio interference to add to the immersion. +- **Easy Setup:** Configure your Mumble server and connection settings with ease, allowing for a smooth and intuitive setup. + +### Installation +1. Download and install Fabric mod loader. +2. Download the Mumble Walkie mod and place it in the `mods` folder. +3. Configure the Mumble server through the in-game settings or edit the `mbradio_config.json` file in the `config` folder. + +### Usage +- Equip the Walkie-Talkie item and hold the configured key ("V" key is default) to start speaking. +- Adjust the Mumble server settings if needed from the in-game menu or through the `mbradio_config.json` file. + +### Compatibility +- Compatible with other Minecraft mods and supports integration with additional communication tools or systems. +- Designed to work seamlessly on both client and server-side. diff --git a/build.gradle b/build.gradle index a41f396..d67e44d 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,9 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - + + modImplementation "net.java.dev.jna:jna:5.17.0" + } processResources { diff --git a/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkie.java b/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkie.java index 58f00a1..724f139 100644 --- a/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkie.java +++ b/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkie.java @@ -1,5 +1,7 @@ package com.andrewdotdev.mbwalkie; +import com.andrewdotdev.mbwalkie.commands.WalkieCommands; +import com.andrewdotdev.mbwalkie.config.ConfigManager; import com.andrewdotdev.mbwalkie.item.ModItems; import net.fabricmc.api.ModInitializer; import org.slf4j.Logger; @@ -11,6 +13,8 @@ public class MumbleWalkie implements ModInitializer { @Override public void onInitialize() { + ConfigManager.loadConfig(); + WalkieCommands.register(); ModItems.registerModItems(); LOGGER.info("Mumble Walkie initialized!"); } diff --git a/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkieClient.java b/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkieClient.java index 8c4fd22..00808d4 100644 --- a/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkieClient.java +++ b/src/main/java/com/andrewdotdev/mbwalkie/MumbleWalkieClient.java @@ -1,10 +1,13 @@ package com.andrewdotdev.mbwalkie; +import com.andrewdotdev.mbwalkie.client.ClientEvents; +import com.andrewdotdev.mbwalkie.client.Keybinds; import net.fabricmc.api.ClientModInitializer; public class MumbleWalkieClient implements ClientModInitializer { @Override public void onInitializeClient() { - + Keybinds.register(); + ClientEvents.register(); } } diff --git a/src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java b/src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java new file mode 100644 index 0000000..2b5c664 --- /dev/null +++ b/src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java @@ -0,0 +1,73 @@ +package com.andrewdotdev.mbwalkie.client; + +import com.andrewdotdev.mbwalkie.mumble.MumbleClient; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.Registry; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.Identifier; + +import java.util.Optional; + +import static com.andrewdotdev.mbwalkie.item.ModItems.WALKIE_TALKIE; + +public class ClientEvents { + private static boolean isTalking = false; + + public static void register() { + + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> MumbleClient.connect()); + + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (hasWalkieTalkie(client)) { + if (Keybinds.radioKey.isPressed() && !isTalking) { + startTalking(client); + isTalking = true; + } else if (!Keybinds.radioKey.isPressed() && isTalking) { + stopTalking(client); + isTalking = false; + } + } else if (!hasWalkieTalkie(client) && isTalking) { + stopTalking(client); + isTalking = false; + } + }); + } + + private static boolean hasWalkieTalkie(MinecraftClient client) { + if (client.player == null) return false; + + ItemStack mainHand = client.player.getMainHandStack(); + ItemStack offHand = client.player.getOffHandStack(); + + return mainHand.isOf(WALKIE_TALKIE) || offHand.isOf(WALKIE_TALKIE); + } + + private static void startTalking(MinecraftClient client) { + playSound(client, "mbwalkie:walkie_start"); + MumbleClient.startTalking(); + System.out.println("🎙️ Started Talking..."); + // Aquí deberías conectarlo con Mumble o el sistema de voz + } + + private static void stopTalking(MinecraftClient client) { + playSound(client, "mbwalkie:walkie_end"); + MumbleClient.stopTalking(); + System.out.println("📻 Stopped Talking."); + // Aquí desconectas el audio + } + + private static void playSound(MinecraftClient client, String soundId) { + if (client.player == null) return; + + SoundEvent soundEvent = new SoundEvent(Identifier.of(soundId), Optional.of(8F)); + if (soundEvent != null) { + client.getSoundManager().play( + PositionedSoundInstance.master(soundEvent, 1.0F) + ); + } + } +} diff --git a/src/main/java/com/andrewdotdev/mbwalkie/client/Keybinds.java b/src/main/java/com/andrewdotdev/mbwalkie/client/Keybinds.java new file mode 100644 index 0000000..b33e05a --- /dev/null +++ b/src/main/java/com/andrewdotdev/mbwalkie/client/Keybinds.java @@ -0,0 +1,19 @@ +package com.andrewdotdev.mbwalkie.client; + +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import org.lwjgl.glfw.GLFW; + +public class Keybinds { + public static KeyBinding radioKey; + + public static void register() { + radioKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "Talk", // Nombre en el archivo de traducción + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_V, // Tecla por defecto (puede cambiarse en ajustes) + "Mumble Walkie Talkie" // Categoría en los controles + )); + } +} diff --git a/src/main/java/com/andrewdotdev/mbwalkie/commands/WalkieCommands.java b/src/main/java/com/andrewdotdev/mbwalkie/commands/WalkieCommands.java new file mode 100644 index 0000000..9e6cdf8 --- /dev/null +++ b/src/main/java/com/andrewdotdev/mbwalkie/commands/WalkieCommands.java @@ -0,0 +1,36 @@ +package com.andrewdotdev.mbwalkie.commands; + +import com.andrewdotdev.mbwalkie.config.ConfigManager; +import com.andrewdotdev.mbwalkie.mumble.MumbleClient; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; + +import java.util.function.Supplier; + +public class WalkieCommands { + public static void register() { + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + dispatcher.register(CommandManager.literal("reconnect") + .executes(context -> { + reconnectToMumble(context.getSource()); + return Command.SINGLE_SUCCESS; + }) + ); + }); + } + + private static void reconnectToMumble(ServerCommandSource source) { + source.sendFeedback(() -> Text.literal("🔄 Reconectando a Mumble..."), false); + + // Desconectar y recargar la configuración + MumbleClient.disconnect(); + ConfigManager.loadConfig(); + MumbleClient.connect(); + + source.sendFeedback(() -> Text.literal("✅ Reconectado a " + ConfigManager.getMumbleIP() + ":" + ConfigManager.getMumblePort()), false); + } +} diff --git a/src/main/java/com/andrewdotdev/mbwalkie/config/ConfigManager.java b/src/main/java/com/andrewdotdev/mbwalkie/config/ConfigManager.java new file mode 100644 index 0000000..6cc9e07 --- /dev/null +++ b/src/main/java/com/andrewdotdev/mbwalkie/config/ConfigManager.java @@ -0,0 +1,47 @@ +package com.andrewdotdev.mbwalkie.config; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +public class ConfigManager { + private static final File CONFIG_FILE = new File("config/mbwalkie_config.json"); + private static JsonObject configData; + private static final Gson GSON = new Gson(); + + public static void loadConfig() { + if (!CONFIG_FILE.exists()) { + saveDefaultConfig(); + } + + try (FileReader reader = new FileReader(CONFIG_FILE)) { + configData = GSON.fromJson(reader, JsonObject.class); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static void saveDefaultConfig() { + JsonObject defaultConfig = new JsonObject(); + defaultConfig.addProperty("mumble_ip", "127.0.0.1"); + defaultConfig.addProperty("mumble_port", 64738); + + try (FileWriter writer = new FileWriter(CONFIG_FILE)) { + GSON.toJson(defaultConfig, writer); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String getMumbleIP() { + return configData.get("mumble_ip").getAsString(); + } + + public static int getMumblePort() { + return configData.get("mumble_port").getAsInt(); + } +} diff --git a/src/main/java/com/andrewdotdev/mbwalkie/config/mbwalkie_config.json b/src/main/java/com/andrewdotdev/mbwalkie/config/mbwalkie_config.json new file mode 100644 index 0000000..069d57d --- /dev/null +++ b/src/main/java/com/andrewdotdev/mbwalkie/config/mbwalkie_config.json @@ -0,0 +1,4 @@ +{ + "mumble_ip": "127.0.0.1", + "mumble_port": 64738 +} \ No newline at end of file diff --git a/src/main/java/com/andrewdotdev/mbwalkie/mumble/MumbleClient.java b/src/main/java/com/andrewdotdev/mbwalkie/mumble/MumbleClient.java new file mode 100644 index 0000000..7d21c18 --- /dev/null +++ b/src/main/java/com/andrewdotdev/mbwalkie/mumble/MumbleClient.java @@ -0,0 +1,89 @@ +package com.andrewdotdev.mbwalkie.mumble; + +import com.andrewdotdev.mbwalkie.config.ConfigManager; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.Identifier; + +import java.io.IOException; +import java.net.Socket; +import java.util.Optional; + +public class MumbleClient { + private static Socket socket; + private static boolean connected = false; + private static final double MAX_RANGE = 50.0; + private static boolean transmitting = false; + + public static void startTalking() { + transmitting = true; + updateVolume(); + System.out.println("🎙 Transmitiendo voz..."); + } + + public static void stopTalking() { + transmitting = false; + System.out.println("🔇 Voz detenida."); + } + + private static void updateVolume() { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.player == null) return; + + assert client.world != null; + boolean isStormy = client.world.isThundering() || client.world.isRaining(); + + for (PlayerEntity otherPlayer : client.world.getPlayers()) { + if (otherPlayer == client.player) continue; + + double distance = client.player.getPos().distanceTo(otherPlayer.getPos()); + float volume = calculateVolume(distance); + + if (isStormy || distance > 30) { + playInterferenceSound(); + } + + System.out.println("🔊 Ajustando volumen para " + otherPlayer.getName().getString() + ": " + volume); + } + } + + private static void playInterferenceSound() { + MinecraftClient client = MinecraftClient.getInstance(); + assert client.player != null; + client.player.playSound(new SoundEvent(Identifier.of("mbwalkie:walkie_static"), Optional.of(8F)), 1.0f, 1.0f); + } + + private static float calculateVolume(double distance) { + if (distance > MAX_RANGE) return 0.0f; + return 1.0f - (float) (distance / MAX_RANGE); + } + + + public static void connect() { + if (connected) return; + + try { + String ip = ConfigManager.getMumbleIP(); + int port = ConfigManager.getMumblePort(); + + socket = new Socket(ip, port); + connected = true; + System.out.println("✅ Connected in " + ip + ":" + port); + } catch (IOException e) { + System.err.println("❌ Error while trying to connect Mumble: " + e.getMessage()); + } + } + + public static void disconnect() { + if (!connected) return; + + try { + socket.close(); + connected = false; + System.out.println("🔴 Mumble Disconnected"); + } catch (IOException e) { + System.err.println("⚠️ Error while trying to disconnect Mumble: " + e.getMessage()); + } + } +} diff --git a/src/main/resources/assets/mbwalkie/models/item/walkie_talkie.json b/src/main/resources/assets/mbwalkie/models/item/walkie_talkie.json index b90e27c..d59d170 100644 --- a/src/main/resources/assets/mbwalkie/models/item/walkie_talkie.json +++ b/src/main/resources/assets/mbwalkie/models/item/walkie_talkie.json @@ -1,5 +1,5 @@ { - "credit": "Made with Blockbench", + "credit": "Made by @andrewdotdev", "texture_size": [64, 64], "textures": { "0": "mbwalkie:item/walkie_talkie", diff --git a/src/main/resources/assets/mbwalkie/sounds.json b/src/main/resources/assets/mbwalkie/sounds.json new file mode 100644 index 0000000..7768262 --- /dev/null +++ b/src/main/resources/assets/mbwalkie/sounds.json @@ -0,0 +1,11 @@ +{ + "walkie_start": { + "sounds": ["mbwalkie:walkie_start"] + }, + "walkie_end": { + "sounds": ["mbwalkie:walkie_end"] + }, + "walkie_static": { + "sounds": ["mbwalkie:walkie_static"] + } +} diff --git a/src/main/resources/assets/mbwalkie/sounds/walkie_end.ogg b/src/main/resources/assets/mbwalkie/sounds/walkie_end.ogg new file mode 100644 index 0000000000000000000000000000000000000000..932c874cbda701f93e8021b1ddc339efc4c738e1 GIT binary patch literal 6746 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 M)~1v#K1|eq0f|NDWB>pF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/mbwalkie/sounds/walkie_start.ogg b/src/main/resources/assets/mbwalkie/sounds/walkie_start.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1996e7b7a40b487aba1c323499874bebceb4dc8f GIT binary patch literal 6122 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/mbwalkie/sounds/walkie_static.ogg b/src/main/resources/assets/mbwalkie/sounds/walkie_static.ogg new file mode 100644 index 0000000000000000000000000000000000000000..c4126d955ace2241211208f0fedf334c0c24df32 GIT binary patch literal 14437 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 E0IB19U;qFB literal 0 HcmV?d00001 From 473a62d1cae35d6f3c80c5807d02b562bc0693fb Mon Sep 17 00:00:00 2001 From: Andrew <109876401+andrewdotdev@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:41:46 +0200 Subject: [PATCH 2/3] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 65f0981..52d99f9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ Mumble Walkie is a Minecraft Modification for Fabric that brings real-time voice - **Walkie-Talkie Item:** A custom item that players can hold in their hands to communicate with others. - **Real-time Voice Chat:** Integrates with Mumble to enable voice chat between players within the proximity of the radio signal. - **Sound Effects:** Realistic radio sound effects such as static, tuning, and voice transmission when interacting with the radio. -- **Mumble Server Configuration:** Players can configure the Mumble server directly from within Minecraft. - **Voice Proximity:** Volume and voice distance are adjusted based on the player's position in the game world. - **Interference Sounds:** When there is a storm, rain, or snow, players will hear radio interference to add to the immersion. - **Easy Setup:** Configure your Mumble server and connection settings with ease, allowing for a smooth and intuitive setup. From 511fbe84438f43b666792989ab0f0c670cc35f13 Mon Sep 17 00:00:00 2001 From: Andrew <109876401+andrewdotdev@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:44:27 +0200 Subject: [PATCH 3/3] Update ClientEvents.java --- .../java/com/andrewdotdev/mbwalkie/client/ClientEvents.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java b/src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java index 2b5c664..cd7fb3f 100644 --- a/src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java +++ b/src/main/java/com/andrewdotdev/mbwalkie/client/ClientEvents.java @@ -50,14 +50,12 @@ private static void startTalking(MinecraftClient client) { playSound(client, "mbwalkie:walkie_start"); MumbleClient.startTalking(); System.out.println("🎙️ Started Talking..."); - // Aquí deberías conectarlo con Mumble o el sistema de voz } private static void stopTalking(MinecraftClient client) { playSound(client, "mbwalkie:walkie_end"); MumbleClient.stopTalking(); System.out.println("📻 Stopped Talking."); - // Aquí desconectas el audio } private static void playSound(MinecraftClient client, String soundId) {