From bb89768cf0515f4fbbbd32e22047d177bdace166 Mon Sep 17 00:00:00 2001
From: Erica Marigold <hi@devcomp.xyz>
Date: Mon, 1 Jan 2024 11:27:10 +0530
Subject: [PATCH] feat: proper ;ec & initial death msg impl

---
 src/main/java/xyz/devcomp/Stinky.java         | 13 +--
 .../devcomp/mixin/LivingEntityMixin.java.bak  | 22 +++++
 .../xyz/devcomp/mixin/PlayerListMixin.java    |  2 +-
 .../xyz/devcomp/mixin/ServerPlayerMixin.java  | 99 +++++++++++++++++++
 src/main/java/xyz/devcomp/util/Strings.java   |  1 +
 src/main/resources/stinky.mixins.json         |  3 +-
 6 files changed, 132 insertions(+), 8 deletions(-)
 create mode 100644 src/main/java/xyz/devcomp/mixin/LivingEntityMixin.java.bak
 create mode 100644 src/main/java/xyz/devcomp/mixin/ServerPlayerMixin.java

diff --git a/src/main/java/xyz/devcomp/Stinky.java b/src/main/java/xyz/devcomp/Stinky.java
index e46ef92..2c0d1bc 100644
--- a/src/main/java/xyz/devcomp/Stinky.java
+++ b/src/main/java/xyz/devcomp/Stinky.java
@@ -7,9 +7,7 @@ import net.fabricmc.api.ModInitializer;
 import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
 import net.minecraft.network.chat.ChatType;
 import net.minecraft.network.chat.PlayerChatMessage;
-import net.minecraft.resources.ResourceLocation;
 import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.sounds.SoundEvent;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -20,8 +18,8 @@ public class Stinky implements ModInitializer {
 	// That way, it's clear which mod wrote info, warnings, and errors.
 	public static final Logger LOGGER = LoggerFactory.getLogger("stinky");
 	public static final ConfigModel Config = new ConfigHandler().getConfig();
-	public static final ResourceLocation EC_SOUND_ID = new ResourceLocation("stinky:ping");
-    public static SoundEvent EC_SOUND_EVENT = SoundEvent.createVariableRangeEvent(EC_SOUND_ID);
+	// public static final ResourceLocation EC_SOUND_ID = new ResourceLocation("stinky:ping");
+    // public static SoundEvent EC_SOUND_EVENT = SoundEvent.createVariableRangeEvent(EC_SOUND_ID);
 
 	@Override
 	public void onInitialize() {
@@ -32,10 +30,10 @@ public class Stinky implements ModInitializer {
 		LOGGER.info("Hello from Stinky!");
 		
 		ServerMessageEvents.CHAT_MESSAGE.register((PlayerChatMessage msg, ServerPlayer plr, ChatType.Bound bound) -> {
+			// NOTE: This makes this command dysfunctional on offline mode servers
 			String msgString = msg.signedContent();
 			
-			if (msgString == ";ec") {				
-
+			if (msgString.trim().equalsIgnoreCase(";ec")) {
 				// We're setting the health to 0, instead of plr.kill(), because this 
 				// abuses a flaw in the graves VanillaTweaks datapack to make the player
 				// respawn without creating a grave or losing their items
@@ -44,5 +42,8 @@ public class Stinky implements ModInitializer {
 				plr.setHealth(0);
 			}
 		});
+
+
+		
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/xyz/devcomp/mixin/LivingEntityMixin.java.bak b/src/main/java/xyz/devcomp/mixin/LivingEntityMixin.java.bak
new file mode 100644
index 0000000..9ba0146
--- /dev/null
+++ b/src/main/java/xyz/devcomp/mixin/LivingEntityMixin.java.bak
@@ -0,0 +1,22 @@
+package xyz.devcomp.mixin;
+
+import org.spongepowered.asm.mixin.Mixin;
+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.LocalCapture;
+
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.LivingEntity;
+
+@Mixin(LivingEntity.class)
+public class LivingEntityMixin {
+    @Inject(method = "die(Lnet/minecraft/world/damagesource/DamageSource;)V", at = @At(value = "INVOKE", target = "createWitherRose(Lnet/minecraft/world/entity/LivingEntity;)V"), locals = LocalCapture.CAPTURE_FAILHARD)
+    private void broadcastCustomDeathMessage(DamageSource source, CallbackInfo ci, Entity entity) {
+        if (entity instanceof ServerPlayer) {
+            
+        }
+    } 
+}
diff --git a/src/main/java/xyz/devcomp/mixin/PlayerListMixin.java b/src/main/java/xyz/devcomp/mixin/PlayerListMixin.java
index 6ef707e..034bccb 100644
--- a/src/main/java/xyz/devcomp/mixin/PlayerListMixin.java
+++ b/src/main/java/xyz/devcomp/mixin/PlayerListMixin.java
@@ -42,6 +42,6 @@ public class PlayerListMixin {
         // for connection
         this.currentFormattingStyle = ChatFormatting.DARK_RED; 
 
-        return component.copy().withStyle(currentChatFormattingStyle);
+        return component.copy();
     }
 }
diff --git a/src/main/java/xyz/devcomp/mixin/ServerPlayerMixin.java b/src/main/java/xyz/devcomp/mixin/ServerPlayerMixin.java
new file mode 100644
index 0000000..3db7280
--- /dev/null
+++ b/src/main/java/xyz/devcomp/mixin/ServerPlayerMixin.java
@@ -0,0 +1,99 @@
+package xyz.devcomp.mixin;
+
+import java.util.Map;
+
+import xyz.devcomp.Stinky;
+import xyz.devcomp.util.Strings.DeathStrings;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import com.mojang.authlib.GameProfile;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.damagesource.DamageType;
+import net.minecraft.world.damagesource.DamageTypes;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.level.Level;
+
+@Mixin(ServerPlayer.class)
+public abstract class ServerPlayerMixin extends Player {
+    public ServerPlayerMixin(Level level, BlockPos blockPos, float f, GameProfile gameProfile) {
+        super(level, blockPos, f, gameProfile);
+    }
+
+    @Inject(method = "die(Lnet/minecraft/world/damagesource/DamageSource;)V", at = @At("TAIL"))
+    private void broadcastDeathMessage(DamageSource damageSource, CallbackInfo ci) {
+        ServerPlayer victim = (ServerPlayer) (Object) this;
+        MinecraftServer server = this.getServer();
+
+        if (damageSource.getDirectEntity() instanceof ServerPlayer aggressor) {
+            if (aggressor == victim) {
+                // suicide balls
+
+                server.sendSystemMessage(
+                        Component.literal(DeathStrings.Suicide[(int) (Math.random() * DeathStrings.Suicide.length)]));
+
+                return;
+            }
+
+            Map<ResourceKey<DamageType>, String[]> relevantTypes = Map.of(
+                    DamageTypes.ARROW, DeathStrings.Arrow,
+                    DamageTypes.PLAYER_ATTACK, DeathStrings.Melee,
+                    DamageTypes.MAGIC, DeathStrings.Potion,
+                    DamageTypes.PLAYER_EXPLOSION, DeathStrings.Explosion);
+
+            for (Map.Entry<ResourceKey<DamageType>, String[]> type : relevantTypes.entrySet()) {
+                ResourceKey<DamageType> damageType = type.getKey();
+                String[] msgs = type.getValue();
+
+                if (damageSource.is(damageType)) {
+                    server.getPlayerList().broadcastSystemMessage(Component.literal(msgs[(int) (Math.random() * msgs.length)]
+                            .replace("player", victim.getDisplayName().getString())
+                            .replace("killer", aggressor.getDisplayName().getString()) // check if null
+                            .replace("weapon", (damageSource.getDirectEntity().getName() == null ? "" : damageSource.getDirectEntity().getName().getString()))), false);
+                }
+            }
+            ;
+        } else {
+            // these death msgs dont work :(
+            Stinky.LOGGER.info("killer: {}, weapon: {}", damageSource.getDirectEntity().getName().getString(), damageSource.getEntity().getName().getString());
+
+            Map<ResourceKey<DamageType>, String[]> messageMappings = Map.ofEntries(
+                    Map.entry(DamageTypes.FALL, DeathStrings.FallDamage),
+                    Map.entry(DamageTypes.ON_FIRE, DeathStrings.Burned),
+                    Map.entry(DamageTypes.IN_FIRE, DeathStrings.Burned),
+                    Map.entry(DamageTypes.DROWN, DeathStrings.Drowned),
+                    Map.entry(DamageTypes.IN_WALL, DeathStrings.Suffocation),
+                    Map.entry(DamageTypes.MOB_ATTACK, DeathStrings.Mob),
+                    Map.entry(DamageTypes.MOB_PROJECTILE, DeathStrings.Mob),
+                    Map.entry(DamageTypes.MOB_ATTACK_NO_AGGRO, DeathStrings.Mob),
+                    Map.entry(DamageTypes.GENERIC, DeathStrings.Wildcard),
+                    Map.entry(DamageTypes.EXPLOSION, DeathStrings.Explosion),
+                    Map.entry(DamageTypes.STARVE, DeathStrings.Starved));
+
+            for (Map.Entry<ResourceKey<DamageType>, String[]> type : messageMappings.entrySet()) {
+                ResourceKey<DamageType> damageType = type.getKey();
+                String[] msgs = type.getValue();
+
+                int idx = (int) (Math.random() * msgs.length);
+
+                if (damageSource.is(damageType)) {
+                    server.getPlayerList().broadcastSystemMessage(Component.literal(
+                            msgs[idx]
+                                    .replace("player", victim.getDisplayName().getString())
+                                    .replace("killer", damageSource.getEntity().getName().getString())
+                                    .replace("weapon", damageSource.getDirectEntity().getName().getString())), false);
+                }
+            }
+            ;
+        }
+    }
+}
diff --git a/src/main/java/xyz/devcomp/util/Strings.java b/src/main/java/xyz/devcomp/util/Strings.java
index e723c49..e4f7dfa 100644
--- a/src/main/java/xyz/devcomp/util/Strings.java
+++ b/src/main/java/xyz/devcomp/util/Strings.java
@@ -51,6 +51,7 @@ public class Strings {
                 "&cplayer&7? &cplayer&7?? &cplayer&7!!!!!"
         };
         public static String[] Explosion = {
+               "&cplayer&7 was blown by &ckiller",
                 "&cplayer&7 blew up",
                 "&cplayer&7 exploded",
         };
diff --git a/src/main/resources/stinky.mixins.json b/src/main/resources/stinky.mixins.json
index 6d3df01..a327e69 100644
--- a/src/main/resources/stinky.mixins.json
+++ b/src/main/resources/stinky.mixins.json
@@ -5,7 +5,8 @@
 	"mixins": [
 		"ServerStatusPacketListenerImplMixin",
 		"ComponentMixin",
-		"PlayerListMixin"
+		"PlayerListMixin",
+		"ServerPlayerMixin"
 	],
 	"injectors": {
 		"defaultRequire": 1