mirror of
https://github.com/CompeyDev/stinky-mod.git
synced 2024-12-12 12:50:39 +00:00
refactor: proper join and leave messages, not just on entity (un)load events
This commit is contained in:
parent
d996d21ced
commit
84729afe54
7 changed files with 104 additions and 40 deletions
|
@ -1,20 +1,15 @@
|
|||
package xyz.devcomp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import xyz.devcomp.config.ConfigHandler;
|
||||
import xyz.devcomp.config.ConfigModel;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
|
||||
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.PlayerChatMessage;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -25,6 +20,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);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
|
@ -33,38 +30,17 @@ public class Stinky implements ModInitializer {
|
|||
// Proceed with mild caution.
|
||||
|
||||
LOGGER.info("Hello from Stinky!");
|
||||
|
||||
// TODO: Cleanup logic with a shared function for both join & leave events
|
||||
// FIXME: Load & Unload events are fired on death and respawn too, not just join and leave
|
||||
|
||||
ServerEntityEvents.ENTITY_LOAD.register((Entity entity, ServerLevel world) -> {
|
||||
ArrayList<String> joinMsgStrings = Stinky.Config.getJoinMessageStrings();
|
||||
String formattedUsername = entity.getName().toString().replaceAll("literal", "").replaceAll("\\{", "")
|
||||
.replaceAll("\\}", "");
|
||||
|
||||
// Get a random join message and display it as a green system message
|
||||
entity.sendSystemMessage(Component.literal(String.format(
|
||||
joinMsgStrings.get((int) (Math.random() * joinMsgStrings.size())), formattedUsername))
|
||||
.setStyle(Style.EMPTY.withColor(43520)));
|
||||
});
|
||||
|
||||
ServerEntityEvents.ENTITY_UNLOAD.register((Entity entity, ServerLevel world) -> {
|
||||
ArrayList<String> leaveMsgStrings = Stinky.Config.getLeaveMessageStrings();
|
||||
String formattedUsername = entity.getName().toString().replaceAll("literal", "").replaceAll("\\{", "")
|
||||
.replaceAll("\\}", "");
|
||||
|
||||
// Get a random leave message and display it as a red system message
|
||||
entity.sendSystemMessage(Component.literal(String.format(
|
||||
leaveMsgStrings.get((int) (Math.random() * leaveMsgStrings.size())), formattedUsername))
|
||||
.setStyle(Style.EMPTY.withColor(11141120)));
|
||||
});
|
||||
|
||||
ServerMessageEvents.CHAT_MESSAGE.register((PlayerChatMessage msg, ServerPlayer plr, ChatType.Bound bound) -> {
|
||||
String msgString = msg.signedContent();
|
||||
|
||||
LOGGER.info("msgString: ", msgString);
|
||||
|
||||
if (msgString == ";ec") {
|
||||
if (msgString == ";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
|
||||
|
||||
// TODO: Play stinky:ping sound
|
||||
plr.setHealth(0);
|
||||
}
|
||||
});
|
||||
|
|
31
src/main/java/xyz/devcomp/mixin/ComponentMixin.java
Normal file
31
src/main/java/xyz/devcomp/mixin/ComponentMixin.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
package xyz.devcomp.mixin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import xyz.devcomp.Stinky;
|
||||
|
||||
@Mixin(Component.class)
|
||||
public interface ComponentMixin {
|
||||
@ModifyVariable(method = "translatable(Ljava/lang/String;[Ljava/lang/Object;)Lnet/minecraft/network/chat/MutableComponent;", at = @At("HEAD"), ordinal = 0)
|
||||
private static String transformLeaveMessage(String string) {
|
||||
// We cannot shadow this as a static member on the Component
|
||||
// class and ComponentMixin is an interface, so we just need to
|
||||
// fetch the messages on every leave. Not ideal, but whatever
|
||||
ArrayList<String> leaveMessages = Stinky.Config.getLeaveMessageStrings();
|
||||
|
||||
// Since ServerGamePacketListenerImpl broadcasts the message without any
|
||||
// intermediate variable for the component, the only thing we can do is
|
||||
// intercept the message in Component#translatable and return a custom message
|
||||
|
||||
if (string == "multiplayer.player.left") {
|
||||
return leaveMessages.get((int) (Math.random() * leaveMessages.size()));
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
}
|
47
src/main/java/xyz/devcomp/mixin/PlayerListMixin.java
Normal file
47
src/main/java/xyz/devcomp/mixin/PlayerListMixin.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
package xyz.devcomp.mixin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import xyz.devcomp.Stinky;
|
||||
|
||||
@Mixin(PlayerList.class)
|
||||
public class PlayerListMixin {
|
||||
private ServerPlayer currentPlayer;
|
||||
private ChatFormatting currentFormattingStyle;
|
||||
private static final ArrayList<String> JoinMessages = Stinky.Config.getJoinMessageStrings();
|
||||
|
||||
@ModifyVariable(method = "placeNewPlayer(Lnet/minecraft/network/Connection;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/server/network/CommonListenerCookie;)V", at = @At("HEAD"), ordinal = 0)
|
||||
private ServerPlayer captureServerPlayer(ServerPlayer plyr) {
|
||||
this.currentPlayer = plyr;
|
||||
return plyr;
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "placeNewPlayer(Lnet/minecraft/network/Connection;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/server/network/CommonListenerCookie;)V", at = @At("STORE"), ordinal = 0)
|
||||
private MutableComponent injectCustomMessage(MutableComponent base) {
|
||||
this.currentFormattingStyle = ChatFormatting.DARK_GREEN;
|
||||
|
||||
return Component.literal(String.format(JoinMessages.get((int) (Math.random() * JoinMessages.size())), this.currentPlayer.getDisplayName().getString()));
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "broadcastSystemMessage(Lnet/minecraft/network/chat/Component;Z)V", at = @At("HEAD"), ordinal = 0)
|
||||
private Component injectCustomBroadcastFormatting(Component component) {
|
||||
ChatFormatting currentChatFormattingStyle = this.currentFormattingStyle;
|
||||
|
||||
// We assume the next call is a disconnect, because we never really
|
||||
// know when a disconnect is initiated. In case it's not a disconnect,
|
||||
// the above injectCustomMessage will reset it back to DARK_GREEN
|
||||
// for connection
|
||||
this.currentFormattingStyle = ChatFormatting.DARK_RED;
|
||||
|
||||
return component.copy().withStyle(currentChatFormattingStyle);
|
||||
}
|
||||
}
|
|
@ -13,13 +13,13 @@ import xyz.devcomp.Stinky;
|
|||
|
||||
@Mixin(ServerStatusPacketListenerImpl.class)
|
||||
public class ServerStatusPacketListenerImplMixin {
|
||||
private static ArrayList<String> MOTDs = Stinky.Config.getMOTDs();
|
||||
private static final ArrayList<String> MOTDs = Stinky.Config.getMOTDs();
|
||||
|
||||
@ModifyVariable(method = "<init>(Lnet/minecraft/network/protocol/status/ServerStatus;Lnet/minecraft/network/Connection;)V", at = @At("HEAD"), ordinal = 0)
|
||||
private static ServerStatus injected(ServerStatus serverStatus) {
|
||||
private static ServerStatus injectCustomMOTD(ServerStatus serverStatus) {
|
||||
return new ServerStatus(
|
||||
Component.literal(ServerStatusPacketListenerImplMixin.MOTDs
|
||||
.get((int) (Math.random() * ServerStatusPacketListenerImplMixin.MOTDs.size()))),
|
||||
Component.literal(MOTDs
|
||||
.get((int) (Math.random() * MOTDs.size()))),
|
||||
serverStatus.players(), serverStatus.version(),
|
||||
serverStatus.favicon(), serverStatus.enforcesSecureChat());
|
||||
}
|
||||
|
|
8
src/main/resources/assets/stinky/sounds.json
Normal file
8
src/main/resources/assets/stinky/sounds.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"my_sound": {
|
||||
"sounds": [
|
||||
"stinky:ping"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
BIN
src/main/resources/assets/stinky/sounds/ping.ogg
Normal file
BIN
src/main/resources/assets/stinky/sounds/ping.ogg
Normal file
Binary file not shown.
|
@ -3,7 +3,9 @@
|
|||
"package": "xyz.devcomp.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"ServerStatusPacketListenerImplMixin"
|
||||
"ServerStatusPacketListenerImplMixin",
|
||||
"ComponentMixin",
|
||||
"PlayerListMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
Loading…
Reference in a new issue