Skip to content

Commit

Permalink
Merge pull request #132
Browse files Browse the repository at this point in the history
Fix Fabric hurt sounds requiring the mod server-side
  • Loading branch information
WildfireRomeo authored Jul 24, 2023
2 parents 9d2b637 + ce11e6b commit d74aefd
Show file tree
Hide file tree
Showing 15 changed files with 120 additions and 185 deletions.
20 changes: 13 additions & 7 deletions src/main/java/com/wildfire/main/GenderPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import com.wildfire.main.config.ConfigKey;
import com.wildfire.main.config.Configuration;
import com.wildfire.physics.BreastPhysics;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;

import javax.annotation.Nullable;
import java.util.UUID;
import java.util.function.Consumer;

Expand Down Expand Up @@ -257,26 +259,30 @@ public enum SyncStatus {
}

public enum Gender {
FEMALE(Text.translatable("wildfire_gender.label.female").formatted(Formatting.LIGHT_PURPLE)),
MALE(Text.translatable("wildfire_gender.label.male").formatted(Formatting.BLUE)),
OTHER(Text.translatable("wildfire_gender.label.other").formatted(Formatting.GREEN));
FEMALE(Text.translatable("wildfire_gender.label.female").formatted(Formatting.LIGHT_PURPLE), true, WildfireSounds.FEMALE_HURT),
MALE(Text.translatable("wildfire_gender.label.male").formatted(Formatting.BLUE), false, null),
OTHER(Text.translatable("wildfire_gender.label.other").formatted(Formatting.GREEN), true, WildfireSounds.FEMALE_HURT);

private final Text name;
private final boolean canHaveBreasts;
private final @Nullable SoundEvent hurtSound;

Gender(Text name) {
Gender(Text name, boolean canHaveBreasts, @Nullable SoundEvent hurtSound) {
this.name = name;
this.canHaveBreasts = canHaveBreasts;
this.hurtSound = hurtSound;
}

public Text getDisplayName() {
return name;
}

public boolean hasFemaleHurtSounds() {
return this == FEMALE || this == OTHER;
public @Nullable SoundEvent getHurtSound() {
return hurtSound;
}

public boolean canHaveBreasts() {
return this != MALE;
return canHaveBreasts;
}
}
}
70 changes: 0 additions & 70 deletions src/main/java/com/wildfire/main/WildfireEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
import com.wildfire.main.networking.PacketSendGenderInfo;
import com.wildfire.main.networking.PacketSync;

import java.util.Random;
import java.util.Set;
import java.util.UUID;

import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
Expand All @@ -34,12 +32,7 @@
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.sound.EntityTrackingSoundInstance;
import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;

Expand Down Expand Up @@ -112,72 +105,9 @@ public static void registerClientEvents() {
}
});

//Receive hurt

ClientPlayNetworking.registerGlobalReceiver(new Identifier(WildfireGender.MODID, "hurt"),
(client, handler, buf, responseSender) -> {
UUID uuid = buf.readUuid();
GenderPlayer.Gender gender = buf.readEnumConstant(GenderPlayer.Gender.class);
boolean hurtSounds = buf.readBoolean();

//Vector3d pos = new Vector3d(buf.readDouble(), buf.readDouble(), buf.readDouble());

SoundEvent hurtSound = null;
if(gender == GenderPlayer.Gender.FEMALE) {
hurtSound = Math.random() > 0.5f ? WildfireSounds.FEMALE_HURT1 : WildfireSounds.FEMALE_HURT2;
}
if(hurtSound == null) return;

if(hurtSounds) {
PlayerEntity ent = MinecraftClient.getInstance().world.getPlayerByUuid(uuid);
if (ent != null) {
long randomLong = new Random().nextLong(0L,1L);
final SoundEvent hurtSound2 = hurtSound;
// ensures it's executed in the main thread
client.execute(() -> {
client.getSoundManager().play(new EntityTrackingSoundInstance(hurtSound2, SoundCategory.PLAYERS, 1f, 1f, ent, randomLong));
});
}
}
});

ClientPlayNetworking.registerGlobalReceiver(new Identifier(WildfireGender.MODID, "sync"),
(client, handler, buf, responseSender) -> {
PacketSync.handle(client, handler, buf, responseSender);
});
}

//TODO: Eventually we may want to replace this with a map or something and replace things like drowning sounds with other drowning sounds
private final Set<SoundEvent> playerHurtSounds = Set.of(SoundEvents.ENTITY_PLAYER_HURT,
SoundEvents.ENTITY_PLAYER_HURT_DROWN,
SoundEvents.ENTITY_PLAYER_HURT_FREEZE,
SoundEvents.ENTITY_PLAYER_HURT_ON_FIRE,
SoundEvents.ENTITY_PLAYER_HURT_SWEET_BERRY_BUSH
);
/*
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onPlaySound(PlaySoundAtEntityEvent event) {
if (playerHurtSounds.contains(event.getSound()) && event.getEntity() instanceof Player p && p.level.isClientSide) {
//Cancel as we handle all hurt sounds manually so that we can
event.setCanceled(true);
SoundEvent soundEvent = event.getSound();
if (p.hurtTime == p.hurtDuration && p.hurtTime > 0) {
//Note: We check hurtTime == hurtDuration and hurtTime > 0 or otherwise when the server sends a hurt sound to the client
// and the client will check itself instead of the player who was damaged.
GenderPlayer plr = WildfireGender.getPlayerById(p.getUUID());
if (plr != null && plr.hasHurtSounds() && plr.getGender().hasFemaleHurtSounds()) {
//If the player who produced the hurt sound is a female sound replace it
soundEvent = Math.random() > 0.5f ? WildfireSounds.FEMALE_HURT1 : WildfireSounds.FEMALE_HURT2;
}
} else if (p.getUUID().equals(Minecraft.getInstance().player.getUUID())) {
//Skip playing remote hurt sounds. Note: sounds played via /playsound will not be intercepted
// as they are played directly
//Note: This might behave slightly strangely if a mod is manually firing a player damage sound
// only on the server and not also on the client
//TODO: Ideally we would fix that edge case but I find it highly unlikely it will ever actually occur
return;
}
p.level.playLocalSound(p.getX(), p.getY(), p.getZ(), soundEvent, event.getCategory(), event.getVolume(), event.getPitch(), false);
}
}*/
}
1 change: 0 additions & 1 deletion src/main/java/com/wildfire/main/WildfireGender.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public class WildfireGender implements ClientModInitializer {
@Override
public void onInitializeClient() {
WildfireEventHandler.registerClientEvents();
WildfireSounds.register();
}

@Nullable
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/wildfire/main/WildfireGenderServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class WildfireGenderServer implements ModInitializer {

@Override
public void onInitialize() {
// while this class is named 'Server', this is actually a common code path,
// so we can safely register here for both sides.
WildfireSounds.register();
ServerPlayNetworking.registerGlobalReceiver(new Identifier(WildfireGender.MODID, "send_gender_info"),
(server, playerEntity, handler, buf, responseSender) -> {
PacketSendGenderInfo.handle(server, playerEntity, handler, buf, responseSender);
Expand Down
11 changes: 3 additions & 8 deletions src/main/java/com/wildfire/main/WildfireSounds.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,9 @@
import net.minecraft.util.Identifier;

public class WildfireSounds {
private static Identifier SND1 = new Identifier(WildfireGender.MODID, "female_hurt1");
public static SoundEvent FEMALE_HURT1 = SoundEvent.of(SND1);
public static final SoundEvent FEMALE_HURT = SoundEvent.of(new Identifier(WildfireGender.MODID, "female_hurt"));

private static Identifier SND2 = new Identifier(WildfireGender.MODID, "female_hurt2");
public static SoundEvent FEMALE_HURT2 = SoundEvent.of(SND2);

public static void register() {
Registry.register(Registries.SOUND_EVENT, SND1, FEMALE_HURT1);
Registry.register(Registries.SOUND_EVENT, SND2, FEMALE_HURT2);
protected static void register() {
Registry.register(Registries.SOUND_EVENT, FEMALE_HURT.getId(), FEMALE_HURT);
}
}
98 changes: 98 additions & 0 deletions src/main/java/com/wildfire/mixins/LivingEntityMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
Wildfire's Female Gender Mod is a female gender mod created for Minecraft.
Copyright (C) 2023 WildfireRomeo
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.wildfire.mixins;

import com.wildfire.main.GenderPlayer;
import com.wildfire.main.WildfireGender;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

/*
* A note on why this implementation in particular was chosen:
*
* While this could be reduced down to one mixin (the `#onDamaged(DamageSource)` one in particular), and forego any sort
* of server-side handling, this is being done as (at least as of when this is being written,) the mod fails to ever
* perform an initial sync upon a player joining a dedicated server; as such, we're using client- *and* server-side mixins
* to provide some level of consistency, even if syncing isn't consistent.
*
* We're additionally playing *alongside* the vanilla hurt sound, largely for the sake of accessibility, as the vanilla
* hurt sound may provide important context as for why a player is taking damage, which could prove especially helpful
* for players with poor/no eyesight.
*
* Additionally, completely replacing the hurt sound server-side would essentially require the mod client-side as well
* to hear *any* hurt sounds from players with this setting enabled, which rules out mixins to methods such as
* `PlayerEntity#getHurtSound(DamageSource)`.
*/
@Mixin(LivingEntity.class)
public class LivingEntityMixin {
@Environment(EnvType.CLIENT)
@Inject(
method = "onDamaged",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/LivingEntity;playSound(Lnet/minecraft/sound/SoundEvent;FF)V"
)
)
public void clientGenderHurtSound(DamageSource damageSource, CallbackInfo ci) {
MinecraftClient client = MinecraftClient.getInstance();
if(client.player == null || client.world == null) return;

if((LivingEntity)(Object)this instanceof PlayerEntity player) {
if(player.getWorld().isClient() && player.getUuid().equals(client.player.getUuid())) {
this.playGenderHurtSound(player);
}
}
}

@Inject(
method = "damage",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/LivingEntity;playHurtSound(Lnet/minecraft/entity/damage/DamageSource;)V"
)
)
public void serverGenderHurtSound(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
if((LivingEntity)(Object)this instanceof PlayerEntity player) {
if(!player.getWorld().isClient()) this.playGenderHurtSound(player);
}
}

@Unique
private void playGenderHurtSound(PlayerEntity player) {
GenderPlayer genderPlayer = WildfireGender.getPlayerById(player.getUuid());
if(genderPlayer == null || !genderPlayer.hasHurtSounds()) return;

SoundEvent hurtSound = genderPlayer.getGender().getHurtSound();
if(hurtSound != null) {
float pitch = (player.getRandom().nextFloat() - player.getRandom().nextFloat()) * 0.2F + 1.0F;
player.playSound(hurtSound, 1f, pitch);
}
}
}
77 changes: 0 additions & 77 deletions src/main/java/com/wildfire/mixins/PlayerEntityServerMixin.java

This file was deleted.

2 changes: 0 additions & 2 deletions src/main/resources/assets/wildfire_gender/lang/cs_cz.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"category.wildfire_gender.generic": "Wildfire's Female Gender Mod",
"key.wildfire_gender.gender_menu": "Menu ženského pohlaví",

"wildfire_gender.hurt.female": "Zranění ženského hráče",

"wildfire_gender.player_list.title": "Female Gender Mod",
"wildfire_gender.player_list.settings_button": "Nastavení",
"wildfire_gender.player_list.sync_status": "Status synchronizace",
Expand Down
2 changes: 0 additions & 2 deletions src/main/resources/assets/wildfire_gender/lang/de_ch.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"category.wildfire_gender.generic": "Wildfire's Wiiblicher Geschlects Mod",
"key.wildfire_gender.gender_menu": "Geschlechtsmenu",

"wildfire_gender.hurt.female": "Spielerin nimmt schade",

"wildfire_gender.player_list.title": "Wiiblicher Geschlechts Mod",
"wildfire_gender.player_list.settings_button": "Iistellige",
"wildfire_gender.player_list.sync_status": "Synchronisierigsstatus",
Expand Down
2 changes: 0 additions & 2 deletions src/main/resources/assets/wildfire_gender/lang/de_de.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"category.wildfire_gender.generic": "Wildfire's Weibliche Geschlechtsmod",
"key.wildfire_gender.gender_menu": "Geschlechtsmenü",

"wildfire_gender.hurt.female": "Spielerin nimmt schaden",

"wildfire_gender.player_list.title": "Weibliche Geschlechts Mod",
"wildfire_gender.player_list.settings_button": "Einstellungen",
"wildfire_gender.player_list.sync_status": "Synchronisierungsstatus",
Expand Down
2 changes: 0 additions & 2 deletions src/main/resources/assets/wildfire_gender/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
"key.wildfire_gender.gender_menu": "Female Gender Menu",
"toast.wildfire_gender.get_started": "Press '%s' to get started!",

"wildfire_gender.hurt.female": "Female Player Hurt",

"wildfire_gender.player_list.title": "Female Gender Mod",
"wildfire_gender.player_list.settings_button": "Settings",
"wildfire_gender.player_list.sync_status": "Sync Status",
Expand Down
Loading

0 comments on commit d74aefd

Please sign in to comment.