diff --git a/build.gradle b/build.gradle index 6224c3e..6685fe0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,20 @@ plugins { - id "babric-loom" version "1.4.+" - id "java" + id("fabric-loom") version "1.10.0-bta" + id("java") +} + +import org.gradle.internal.os.OperatingSystem +project.ext.lwjglVersion = "3.3.4" + +switch (OperatingSystem.current()) { + case OperatingSystem.LINUX: + project.ext.lwjglNatives = "natives-linux" + break + case OperatingSystem.WINDOWS: + project.ext.lwjglNatives = "natives-windows" + break + case OperatingSystem.MAC_OS: + project.ext.lwjglNatives = "natives-macos" } group = project.mod_group @@ -8,9 +22,8 @@ archivesBaseName = project.mod_name version = project.mod_version loom { - gluedMinecraftJar() noIntermediateMappings() - customMinecraftManifest.set("https://github.com/Turnip-Labs/bta-manifest-repo/releases/download/v${project.bta_version}/${project.bta_version}.json") + customMinecraftMetadata.set("https://downloads.betterthanadventure.net/bta-client/${project.bta_channel}/v${project.bta_version}/manifest.json") accessWidenerPath = file("src/main/resources/proxvc.accesswidener") } @@ -70,6 +83,21 @@ dependencies { implementation "com.google.guava:guava:33.0.0-jre" modRuntimeOnly "ModMenu:ModMenu-bta:${project.mod_menu_version}" + + implementation(platform("org.lwjgl:lwjgl-bom:$lwjglVersion")) + + runtimeOnly("org.lwjgl:lwjgl::$lwjglNatives") + runtimeOnly("org.lwjgl:lwjgl-assimp::$lwjglNatives") + runtimeOnly("org.lwjgl:lwjgl-glfw::$lwjglNatives") + runtimeOnly("org.lwjgl:lwjgl-openal::$lwjglNatives") + runtimeOnly("org.lwjgl:lwjgl-opengl::$lwjglNatives") + runtimeOnly("org.lwjgl:lwjgl-stb::$lwjglNatives") + implementation("org.lwjgl:lwjgl:$lwjglVersion") + implementation("org.lwjgl:lwjgl-assimp:$lwjglVersion") + implementation("org.lwjgl:lwjgl-glfw:$lwjglVersion") + implementation("org.lwjgl:lwjgl-openal:$lwjglVersion") + implementation("org.lwjgl:lwjgl-opengl:$lwjglVersion") + implementation("org.lwjgl:lwjgl-stb:$lwjglVersion") } java { @@ -88,6 +116,11 @@ jar { } } +configurations.configureEach { + // Removes LWJGL2 dependencies. + exclude group: "org.lwjgl.lwjgl" +} + processResources { inputs.property "mod_version", project.mod_version filesMatching("fabric.mod.json") { diff --git a/gradle.properties b/gradle.properties index 180c8ad..de8c053 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,11 @@ org.gradle.jvmargs=-Xmx2G -bta_version=7.2_01 -loader_version=0.15.6-babric.6-bta +bta_version=7.3_01 +loader_version=0.15.6-bta.7 +bta_channel=release -halplibe_version=4.1.3 -mod_menu_version=2.0.6 +halplibe_version=5.2.2 +mod_menu_version=3.0.0 mod_version=1.5.2 mod_group=fiveavian diff --git a/settings.gradle b/settings.gradle index 68b7cc5..d6615a3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,12 +2,20 @@ pluginManagement { repositories { gradlePluginPortal() maven { - name = "Fabric" - url = "https://maven.fabricmc.net/" + name = 'Fabric' + url = 'https://maven.fabricmc.net/' } maven { - name = "Babric" - url = "https://maven.glass-launcher.net/babric" + name = 'Jitpack' + url = 'https://jitpack.io' + } + maven { + name = 'Babric' + url = 'https://maven.glass-launcher.net/babric' + } + maven { + name = 'SignalumMavenInfrastructure' + url = 'https://maven.thesignalumproject.net/infrastructure' } } -} +} \ No newline at end of file diff --git a/src/main/java/fiveavian/proxvc/ProxVCClient.java b/src/main/java/fiveavian/proxvc/ProxVCClient.java index e833935..123d5cc 100644 --- a/src/main/java/fiveavian/proxvc/ProxVCClient.java +++ b/src/main/java/fiveavian/proxvc/ProxVCClient.java @@ -17,11 +17,12 @@ import net.minecraft.client.option.*; import net.minecraft.client.render.tessellator.Tessellator; import net.minecraft.client.render.WorldRenderer; -import net.minecraft.core.block.Block; +import net.minecraft.core.block.Blocks; import net.minecraft.core.entity.Entity; -import net.minecraft.core.entity.player.EntityPlayer; -import net.minecraft.core.net.packet.Packet1Login; -import net.minecraft.core.util.phys.Vec3d; +import net.minecraft.core.entity.player.Player; +import net.minecraft.core.net.packet.PacketLogin; +import net.minecraft.core.util.phys.Vec3; +import net.minecraft.client.render.texture.Texture; import org.lwjgl.input.Keyboard; import org.lwjgl.openal.AL10; import org.lwjgl.openal.AL11; @@ -45,14 +46,15 @@ public class ProxVCClient implements ClientModInitializer { public SocketAddress serverAddress; private Thread inputThread; private Thread outputThread; + public Texture statusIconTexture; public final KeyBinding keyMute = new KeyBinding("key.mute").setDefault(InputDevice.keyboard, Keyboard.KEY_M); public final KeyBinding keyPushToTalk = new KeyBinding("key.push_to_talk").setDefault(InputDevice.keyboard, Keyboard.KEY_V); public final KeyBinding[] keyBindings = {keyMute, keyPushToTalk}; - public FloatOption voiceChatVolume; - public BooleanOption isMuted; - public BooleanOption usePushToTalk; - public StringOption selectedInputDevice; + public OptionFloat voiceChatVolume; + public OptionBoolean isMuted; + public OptionBoolean usePushToTalk; + public OptionString selectedInputDevice; public Option[] options; public Path optionFilePath; private boolean isMutePressed = false; @@ -73,10 +75,11 @@ public void onInitializeClient() { private void start(Minecraft client) { this.client = client; - voiceChatVolume = new FloatOption(client.gameSettings, "sound.voice_chat", 1.0f); - isMuted = new BooleanOption(client.gameSettings, "is_muted", false); - usePushToTalk = new BooleanOption(client.gameSettings, "use_push_to_talk", false); - selectedInputDevice = new StringOption(client.gameSettings, "selected_input_device", null); + statusIconTexture = client.textureManager.loadTexture("/gui/proxvc.png"); + voiceChatVolume = new OptionFloat(client.gameSettings, "sound.voice_chat", 1.0f); + isMuted = new OptionBoolean(client.gameSettings, "is_muted", false); + usePushToTalk = new OptionBoolean(client.gameSettings, "use_push_to_talk", false); + selectedInputDevice = new OptionString(client.gameSettings, "selected_input_device", null); options = new Option[]{voiceChatVolume, isMuted, usePushToTalk, selectedInputDevice}; optionFilePath = FabricLoader.getInstance().getConfigDir().resolve("proxvc_client.properties"); OptionStore.loadOptions(optionFilePath, options, keyBindings); @@ -99,11 +102,12 @@ private void start(Minecraft client) { OptionsCategory controlsCategory = new OptionsCategory("gui.options.page.proxvc.category.controls") .withComponent(new KeyBindingComponent(keyMute)) .withComponent(new KeyBindingComponent(keyPushToTalk)); - OptionsPages.register(new OptionsPage("gui.options.page.proxvc.title", Block.noteblock.getDefaultStack())) + OptionsPages.register(new OptionsPage("gui.options.page.proxvc.title", Blocks.NOTEBLOCK.getDefaultStack())) .withComponent(generalCategory) .withComponent(devicesCategory) .withComponent(controlsCategory); device.open(selectedInputDevice.value); + System.out.println("ProxVC successfully started."); } catch (SocketException ex) { System.out.println("Failed to start the ProxVC client because of an exception."); System.out.println("Continuing without ProxVC."); @@ -139,8 +143,8 @@ private void tick(Minecraft client) { Set toRemove = new HashSet<>(sources.keySet()); Set toAdd = new HashSet<>(); - for (Entity entity : client.theWorld.loadedEntityList) { - if (entity instanceof EntityPlayer && entity.id != client.thePlayer.id) { + for (Entity entity : client.currentWorld.loadedEntityList) { + if (entity instanceof Player && entity.id != client.thePlayer.id) { toRemove.remove(entity.id); toAdd.add(entity.id); } @@ -155,25 +159,27 @@ private void tick(Minecraft client) { } if (client.currentScreen == null) { - if (keyMute.isPressEvent(InputDevice.keyboard)) - isMutePressed = true; - if (keyMute.isReleaseEvent(InputDevice.keyboard) && isMutePressed) { + if (keyMute.isPressed()) { + if (!isMutePressed) { + isMutePressed = true; + isMuted.value = !isMuted.value; + } + } else { isMutePressed = false; - isMuted.value = !isMuted.value; } } - for (Entity entity : client.theWorld.loadedEntityList) { + for (Entity entity : client.currentWorld.loadedEntityList) { StreamingAudioSource source = sources.get(entity.id); if (source == null) { continue; } - Vec3d look = entity.getLookAngle(); + Vec3 look = entity.getLookAngle(); AL10.alDistanceModel(AL11.AL_LINEAR_DISTANCE); AL10.alSourcef(source.source, AL10.AL_MAX_DISTANCE, 32f); AL10.alSourcef(source.source, AL10.AL_REFERENCE_DISTANCE, 16f); AL10.alSource3f(source.source, AL10.AL_POSITION, (float) entity.x, (float) entity.y, (float) entity.z); - AL10.alSource3f(source.source, AL10.AL_DIRECTION, (float) look.xCoord, (float) look.yCoord, (float) look.zCoord); + AL10.alSource3f(source.source, AL10.AL_DIRECTION, (float) look.x, (float) look.y, (float) look.z); AL10.alSource3f(source.source, AL10.AL_VELOCITY, (float) entity.xd, (float) entity.yd, (float) entity.zd); AL10.alSourcef(source.source, AL10.AL_GAIN, voiceChatVolume.value); } @@ -183,24 +189,28 @@ private void render(Minecraft client, WorldRenderer renderer) { if (isDisconnected() || !client.gameSettings.immersiveMode.drawOverlays()) { return; } - GL11.glBindTexture(GL11.GL_TEXTURE_2D, client.renderEngine.getTexture("/proxvc.png")); + statusIconTexture.bind(); GL11.glColor4d(1.0, 1.0, 1.0, 1.0); double u = 0.0; if (isMuted.value) { - u = 0.25; + u = 0.2; } else if (device.isClosed()) { - u = 0.5; + u = 0.4; } else if (usePushToTalk.value && !keyPushToTalk.isPressed()) { - u = 0.75; + u = 0.6; + } else if (device.isClosed()) { + u = 0.2; + } else if (device.isTalking()) { + u = 0.8; } Tessellator.instance.startDrawingQuads(); Tessellator.instance.setColorRGBA_F(1f, 1f, 1f, 0.5f); - Tessellator.instance.drawRectangleWithUV(4, client.resolution.scaledHeight - 24 - 4, 24, 24, u, 0.0, 0.25, 1.0); + Tessellator.instance.drawRectangleWithUV(4, client.resolution.getScaledHeightScreenCoords() - 24 - 4, 24, 24, u, 0.0, 0.20, 1.0); Tessellator.instance.draw(); } - private void login(Minecraft client, Packet1Login packet) { - Socket socket = client.getSendQueue().netManager.networkSocket; + private void login(Minecraft client, PacketLogin packet) { + Socket socket = (Socket) client.getSendQueue().netManager.socket; serverAddress = socket.getRemoteSocketAddress(); } diff --git a/src/main/java/fiveavian/proxvc/api/ClientEvents.java b/src/main/java/fiveavian/proxvc/api/ClientEvents.java index 9a25ad7..40165db 100644 --- a/src/main/java/fiveavian/proxvc/api/ClientEvents.java +++ b/src/main/java/fiveavian/proxvc/api/ClientEvents.java @@ -2,7 +2,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.render.WorldRenderer; -import net.minecraft.core.net.packet.Packet1Login; +import net.minecraft.core.net.packet.PacketLogin; import java.util.ArrayList; import java.util.List; @@ -15,6 +15,6 @@ public class ClientEvents { public static final List> TICK = new ArrayList<>(); public static final List> RENDER = new ArrayList<>(); - public static final List> LOGIN = new ArrayList<>(); + public static final List> LOGIN = new ArrayList<>(); public static final List> DISCONNECT = new ArrayList<>(); } diff --git a/src/main/java/fiveavian/proxvc/gui/MicrophoneListComponent.java b/src/main/java/fiveavian/proxvc/gui/MicrophoneListComponent.java index 56dab6e..c393cc3 100644 --- a/src/main/java/fiveavian/proxvc/gui/MicrophoneListComponent.java +++ b/src/main/java/fiveavian/proxvc/gui/MicrophoneListComponent.java @@ -3,26 +3,29 @@ import fiveavian.proxvc.vc.AudioInputDevice; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.options.components.OptionsComponent; -import net.minecraft.client.option.StringOption; -import net.minecraft.client.render.FontRenderer; +import net.minecraft.client.option.OptionString; +import net.minecraft.client.render.Font; import net.minecraft.client.render.tessellator.Tessellator; import net.minecraft.core.lang.I18n; import org.lwjgl.opengl.GL11; import java.util.Objects; +import java.util.regex.Pattern; public class MicrophoneListComponent implements OptionsComponent { private static final int MARGIN = 3; private static final int BUTTON_HEIGHT = 16; private static final int BUTTON_HEIGHT_WITH_MARGIN = BUTTON_HEIGHT + MARGIN; + // I ended up using a negative look ahead at the end plus the end modifier to prevent replacing entire string with blank + private static final Pattern SPECIFIER_PATTERN = Pattern.compile("OpenAL Soft on\\s+(?!($|\\s+$))"); private final AudioInputDevice device; - private final StringOption specifierOption; + private final OptionString specifierOption; private Minecraft mc; private String[] specifiers; private int updateTickCount = 0; - public MicrophoneListComponent(AudioInputDevice device, StringOption specifierOption) { + public MicrophoneListComponent(AudioInputDevice device, OptionString specifierOption) { this.device = device; this.specifierOption = specifierOption; } @@ -71,10 +74,10 @@ public int getHeight() { @Override public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) { Tessellator tessellator = Tessellator.instance; - FontRenderer fontRenderer = mc.fontRenderer; + Font font = mc.font; I18n i18n = I18n.getInstance(); if (specifiers.length == 0) { - fontRenderer.drawCenteredString(i18n.translateKey("gui.options.page.proxvc.label.no_devices"), x + width / 2, y + 4, 0x5F7F7F7F); + font.drawCenteredString(i18n.translateKey("gui.options.page.proxvc.label.no_devices"), x + width / 2, y + 4, 0x5F7F7F7F); return; } y += MARGIN; @@ -98,7 +101,7 @@ public void render(int x, int y, int width, int relativeMouseX, int relativeMous tessellator.draw(); GL11.glEnable(GL11.GL_TEXTURE_2D); } - fontRenderer.drawString(specifier, x + 1, y + 4, 0xFFFFFF); + font.drawString(SPECIFIER_PATTERN.matcher(specifier).replaceFirst(""), x + 1, y + 4, 0xFFFFFF); y += BUTTON_HEIGHT_WITH_MARGIN; } } diff --git a/src/main/java/fiveavian/proxvc/mixin/client/ALC10Mixin.java b/src/main/java/fiveavian/proxvc/mixin/client/ALC10Mixin.java index ea54145..53baab0 100644 --- a/src/main/java/fiveavian/proxvc/mixin/client/ALC10Mixin.java +++ b/src/main/java/fiveavian/proxvc/mixin/client/ALC10Mixin.java @@ -2,6 +2,7 @@ import org.lwjgl.openal.ALC10; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -12,6 +13,7 @@ /** * Ensures that Minecraft doesn't crash on certain devices. */ +@Pseudo @Mixin(value = ALC10.class, remap = false) public class ALC10Mixin { @Unique @@ -19,7 +21,7 @@ public class ALC10Mixin { .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); - @Redirect(method = "alcGetString", at = @At(value = "INVOKE", target = "Lorg/lwjgl/MemoryUtil;decodeUTF8(Ljava/nio/ByteBuffer;)Ljava/lang/String;")) + @Redirect(method = "alcGetString", at = @At(value = "INVOKE", target = "Lorg/lwjgl/MemoryUtil;decodeUTF8(Ljava/nio/ByteBuffer;)Ljava/lang/String;"), require = 0) private static String decodeUTF8(ByteBuffer buffer) { if (buffer == null) { return null; @@ -31,4 +33,4 @@ private static String decodeUTF8(ByteBuffer buffer) { throw new RuntimeException(ex); } } -} +} \ No newline at end of file diff --git a/src/main/java/fiveavian/proxvc/mixin/client/NetClientHandlerMixin.java b/src/main/java/fiveavian/proxvc/mixin/client/PacketHandlerClientMixin.java similarity index 70% rename from src/main/java/fiveavian/proxvc/mixin/client/NetClientHandlerMixin.java rename to src/main/java/fiveavian/proxvc/mixin/client/PacketHandlerClientMixin.java index 571db35..577f662 100644 --- a/src/main/java/fiveavian/proxvc/mixin/client/NetClientHandlerMixin.java +++ b/src/main/java/fiveavian/proxvc/mixin/client/PacketHandlerClientMixin.java @@ -2,9 +2,9 @@ import fiveavian.proxvc.api.ClientEvents; import net.minecraft.client.Minecraft; -import net.minecraft.client.net.handler.NetClientHandler; -import net.minecraft.core.net.packet.Packet1Login; -import net.minecraft.core.net.packet.Packet255KickDisconnect; +import net.minecraft.client.net.handler.PacketHandlerClient; +import net.minecraft.core.net.packet.PacketDisconnect; +import net.minecraft.core.net.packet.PacketLogin; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -15,8 +15,8 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -@Mixin(value = NetClientHandler.class, remap = false) -public class NetClientHandlerMixin { +@Mixin(value = PacketHandlerClient.class, remap = false) +public class PacketHandlerClientMixin { @Shadow @Final private Minecraft mc; @@ -24,14 +24,14 @@ public class NetClientHandlerMixin { private boolean disconnected; @Inject(method = "handleLogin", at = @At("TAIL")) - public void handleLogin(Packet1Login packet, CallbackInfo ci) { - for (BiConsumer listener : ClientEvents.LOGIN) { + public void handleLogin(PacketLogin packet, CallbackInfo ci) { + for (BiConsumer listener : ClientEvents.LOGIN) { listener.accept(mc, packet); } } @Inject(method = "handleKickDisconnect", at = @At("HEAD")) - public void handleKickDisconnect(Packet255KickDisconnect packet, CallbackInfo ci) { + public void handleKickDisconnect(PacketDisconnect packet, CallbackInfo ci) { for (Consumer listener : ClientEvents.DISCONNECT) { listener.accept(mc); } diff --git a/src/main/java/fiveavian/proxvc/mixin/client/SoundManagerMixin.java b/src/main/java/fiveavian/proxvc/mixin/client/SoundEngineMixin.java similarity index 55% rename from src/main/java/fiveavian/proxvc/mixin/client/SoundManagerMixin.java rename to src/main/java/fiveavian/proxvc/mixin/client/SoundEngineMixin.java index 4a8ee4b..9b8b363 100644 --- a/src/main/java/fiveavian/proxvc/mixin/client/SoundManagerMixin.java +++ b/src/main/java/fiveavian/proxvc/mixin/client/SoundEngineMixin.java @@ -1,7 +1,7 @@ package fiveavian.proxvc.mixin.client; import net.minecraft.client.option.GameSettings; -import net.minecraft.client.sound.SoundManager; +import net.minecraft.client.sound.SoundEngine; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -10,10 +10,10 @@ * Ensures that Minecraft doesn't crash * when starting the game with no volume. */ -@Mixin(value = SoundManager.class, remap = false) -public class SoundManagerMixin { - @Redirect(method = "loadSoundSettings", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/sound/SoundCategoryHelper;isAnyEnabled(Lnet/minecraft/client/option/GameSettings;)Z")) +@Mixin(value = SoundEngine.class, remap = false) +public class SoundEngineMixin { + @Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/sound/SoundCategoryHelper;isAnyEnabled(Lnet/minecraft/client/option/GameSettings;)Z")) public boolean isAnyEnabled(GameSettings category) { return true; } -} +} \ No newline at end of file diff --git a/src/main/java/fiveavian/proxvc/vc/AudioInputDevice.java b/src/main/java/fiveavian/proxvc/vc/AudioInputDevice.java index cba247e..8ca5460 100644 --- a/src/main/java/fiveavian/proxvc/vc/AudioInputDevice.java +++ b/src/main/java/fiveavian/proxvc/vc/AudioInputDevice.java @@ -5,36 +5,43 @@ import java.nio.ByteBuffer; import java.nio.IntBuffer; +import java.util.List; public class AudioInputDevice implements AutoCloseable { private static final int NUM_DEVICE_BUFFERS = 8; private final ByteBuffer samples = BufferUtils.createByteBuffer(VCProtocol.BUFFER_SIZE); private final IntBuffer ints = BufferUtils.createIntBuffer(1); - private ALCdevice device = null; + private Long device = null; + private boolean isTalking = false; public static String[] getSpecifiers() { - String result = null; + List result = null; try { - result = ALC10.alcGetString(null, ALC11.ALC_CAPTURE_DEVICE_SPECIFIER); - } catch (OpenALException ex) { + result = ALUtil.getStringList(0, ALC11.ALC_CAPTURE_DEVICE_SPECIFIER); + } catch (Exception ex) { ex.printStackTrace(); } - return result == null ? new String[0] : result.split("\0"); + return result == null ? new String[0] : result.toArray(new String[0]); } public synchronized void open(String deviceName) { close(); - if (deviceName == null) { + if (deviceName == null || deviceName.isEmpty()) { device = null; } else { - device = ALC11.alcCaptureOpenDevice( - deviceName, - VCProtocol.SAMPLE_RATE, - AL10.AL_FORMAT_MONO16, - VCProtocol.SAMPLE_COUNT * NUM_DEVICE_BUFFERS - ); - ALC11.alcCaptureStart(device); + try { + device = ALC11.alcCaptureOpenDevice( + deviceName, + VCProtocol.SAMPLE_RATE, + AL10.AL_FORMAT_MONO16, + VCProtocol.SAMPLE_COUNT * NUM_DEVICE_BUFFERS + ); + ALC11.alcCaptureStart(device); + } catch (Exception ex) { + ex.printStackTrace(); + device = null; + } } } @@ -47,15 +54,36 @@ public synchronized ByteBuffer pollSamples() { return null; } ints.rewind(); - ALC10.alcGetInteger(device, ALC11.ALC_CAPTURE_SAMPLES, ints); + ALC11.alcGetIntegerv(device, ALC11.ALC_CAPTURE_SAMPLES, ints); if (ints.get(0) < VCProtocol.SAMPLE_COUNT) { return null; } samples.rewind(); ALC11.alcCaptureSamples(device, samples, VCProtocol.SAMPLE_COUNT); + isTalking = !isSilent(samples); return samples; } + public synchronized boolean isTalking() { + if (isClosed()) { + return false; + } + return isTalking; + } + + private boolean isSilent(ByteBuffer samples) { + if (samples.remaining() < 2) { // Assuming 16-bit samples (2 bytes) + return true; // Not enough data to determine silence + } + for (int i = 0; i < samples.remaining(); i += 2) { + short sample = samples.getShort(i); // Read 16-bit sample + if (Math.abs(sample) > 1) { + return false; // Found a sample above the silence threshold + } + } + return true; // All samples are below the threshold + } + @Override public synchronized void close() { if (isClosed()) diff --git a/src/main/java/fiveavian/proxvc/vc/StreamingAudioSource.java b/src/main/java/fiveavian/proxvc/vc/StreamingAudioSource.java index 3090ae9..64cbcb6 100644 --- a/src/main/java/fiveavian/proxvc/vc/StreamingAudioSource.java +++ b/src/main/java/fiveavian/proxvc/vc/StreamingAudioSource.java @@ -10,12 +10,17 @@ public class StreamingAudioSource implements AutoCloseable { private static final int NUM_BUFFERS = 8; - public final int source = AL10.alGenSources(); + public final int source; private final IntBuffer buffers = BufferUtils.createIntBuffer(NUM_BUFFERS); private int bufferIndex = 0; private int numBuffersAvailable = NUM_BUFFERS; public StreamingAudioSource() { + try { + source = AL10.alGenSources(); + } catch (Exception e) { + throw new RuntimeException("Failed to generate OpenAL source. Something terrible happened, report it to our github! https://github.com/5Avian/proxvc/issues", e); + } AL10.alGenBuffers(buffers); AL10.alDistanceModel(AL11.AL_LINEAR_DISTANCE); AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 32f); diff --git a/src/main/java/fiveavian/proxvc/vc/client/VCInputClient.java b/src/main/java/fiveavian/proxvc/vc/client/VCInputClient.java index d989460..fe70c94 100644 --- a/src/main/java/fiveavian/proxvc/vc/client/VCInputClient.java +++ b/src/main/java/fiveavian/proxvc/vc/client/VCInputClient.java @@ -53,7 +53,7 @@ public void run() { } private void sendNextPacket() throws Exception { - if (sources.isEmpty()) { + if (sources.isEmpty() || client.thePlayer == null) { return; } ByteBuffer samples = device.pollSamples(); diff --git a/src/main/java/fiveavian/proxvc/vc/server/VCRelayServer.java b/src/main/java/fiveavian/proxvc/vc/server/VCRelayServer.java index 4b41b7f..c70b585 100644 --- a/src/main/java/fiveavian/proxvc/vc/server/VCRelayServer.java +++ b/src/main/java/fiveavian/proxvc/vc/server/VCRelayServer.java @@ -6,7 +6,7 @@ import fiveavian.proxvc.vc.VCProtocol; import net.minecraft.core.util.helper.AES; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.entity.player.EntityPlayerMP; +import net.minecraft.server.entity.player.PlayerServer; import java.net.DatagramSocket; import java.net.SocketAddress; @@ -20,7 +20,7 @@ public class VCRelayServer implements Runnable { private final DatagramSocket socket; private final DatagramPacketWrapper packet; - private final HashMap connections = new HashMap<>(); + private final HashMap connections = new HashMap<>(); private final ByteBuffer samples = ByteBuffer.allocate(VCProtocol.BUFFER_SIZE + 16); public VCRelayServer(ProxVCServer vcServer) { @@ -47,7 +47,7 @@ private void handleNextPacket() throws Exception { packet.receive(); SocketAddress address = packet.packet.getSocketAddress(); int entityId = packet.buffer.getInt(); - EntityPlayerMP player = getPlayerById(entityId); + PlayerServer player = getPlayerById(entityId); if (player == null) { return; } @@ -63,8 +63,8 @@ private void handleNextPacket() throws Exception { } } - private EntityPlayerMP getPlayerById(int id) { - for (EntityPlayerMP player : server.playerList.playerEntities) { + private PlayerServer getPlayerById(int id) { + for (PlayerServer player : server.playerList.playerEntities) { if (player.id == id) { return player; } @@ -72,11 +72,11 @@ private EntityPlayerMP getPlayerById(int id) { return null; } - private boolean isConnectionOffline(Map.Entry entry) { + private boolean isConnectionOffline(Map.Entry entry) { return getPlayerById(entry.getValue().id) == null; } - private void shareSamples(SocketAddress sourceAddress, EntityPlayerMP sourcePlayer, SocketAddress address, EntityPlayerMP player) throws Exception { + private void shareSamples(SocketAddress sourceAddress, PlayerServer sourcePlayer, SocketAddress address, PlayerServer player) throws Exception { if (sourceAddress.equals(address) || sourcePlayer.id == player.id || sourcePlayer.distanceTo(player) > 32f) { return; } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0338f18..de60557 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -24,8 +24,8 @@ ], "accessWidener": "proxvc.accesswidener", "depends": { - "minecraft": "~7.2", - "fabricloader": ">=0.15.5", - "halplibe": ">=3.5.4" + "minecraft": "~7.3", + "fabricloader": ">=0.15.6-bta.7", + "halplibe": ">=5.2.2" } } diff --git a/src/main/resources/gui/proxvc.png b/src/main/resources/gui/proxvc.png new file mode 100644 index 0000000..e29ed97 Binary files /dev/null and b/src/main/resources/gui/proxvc.png differ diff --git a/src/main/resources/proxvc.accesswidener b/src/main/resources/proxvc.accesswidener index fe76733..f7ecb82 100644 --- a/src/main/resources/proxvc.accesswidener +++ b/src/main/resources/proxvc.accesswidener @@ -1,8 +1,8 @@ accessWidener v2 named -accessible field net/minecraft/server/net/handler/NetServerHandler mcServer Lnet/minecraft/server/MinecraftServer; -accessible field net/minecraft/server/net/handler/NetServerHandler playerEntity Lnet/minecraft/server/entity/player/EntityPlayerMP; -accessible field net/minecraft/server/entity/EntityTracker trackedEntityHashTable Lnet/minecraft/core/world/pathfinder/IdHashMap; -accessible field net/minecraft/client/net/handler/NetClientHandler netManager Lnet/minecraft/core/net/NetworkManager; -accessible field net/minecraft/core/net/NetworkManager networkSocket Ljava/net/Socket; +accessible field net/minecraft/server/net/handler/PacketHandlerServer mcServer Lnet/minecraft/server/MinecraftServer; +accessible field net/minecraft/server/net/handler/PacketHandlerServer playerEntity Lnet/minecraft/server/entity/player/PlayerServer; +accessible field net/minecraft/server/entity/EntityTrackerImpl trackedEntityHashTable Lnet/minecraft/core/util/collection/IntHashMap; +accessible field net/minecraft/client/net/handler/PacketHandlerClient netManager Lnet/minecraft/core/net/NetworkManager; +accessible field net/minecraft/core/net/NetworkManager socket Ljava/net/Socket; accessible field net/minecraft/client/Minecraft mcDataDir Ljava/io/File; diff --git a/src/main/resources/proxvc.mixins.json b/src/main/resources/proxvc.mixins.json index 1f47755..8e5ba45 100644 --- a/src/main/resources/proxvc.mixins.json +++ b/src/main/resources/proxvc.mixins.json @@ -4,11 +4,11 @@ "package": "fiveavian.proxvc.mixin", "compatibilityLevel": "JAVA_8", "client": [ - "client.ALC10Mixin", "client.MinecraftMixin", - "client.NetClientHandlerMixin", + "client.PacketHandlerClientMixin", "client.WorldRendererMixin", - "client.SoundManagerMixin" + "client.SoundEngineMixin", + "client.ALC10Mixin" ], "server": [ "server.MinecraftServerMixin" diff --git a/src/main/resources/proxvc.png b/src/main/resources/proxvc.png deleted file mode 100644 index 1645e9b..0000000 Binary files a/src/main/resources/proxvc.png and /dev/null differ