This commit is contained in:
@ -2,23 +2,18 @@ package wtf.hak.survivalfabric;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import wtf.hak.survivalfabric.commands.SpectatorCommand;
|
||||
|
||||
public class SurvivalFabric implements ModInitializer {
|
||||
public static final String MOD_ID = "survivalfabric";
|
||||
|
||||
// This logger is used to write text to the console and the log file.
|
||||
// It is considered best practice to use your mod id as the logger's name.
|
||||
// That way, it's clear which mod wrote info, warnings, and errors.
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
// This code runs as soon as Minecraft is in a mod-load-ready state.
|
||||
// However, some things (like resources) may still be uninitialized.
|
||||
// Proceed with mild caution.
|
||||
|
||||
LOGGER.info("Hello Fabric world!");
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, new String[] { "spectator", "s", "S", "camera", "c", "C", }));
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package wtf.hak.survivalfabric.commands;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.world.GameMode;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class SpectatorCommand {
|
||||
|
||||
public static final Map<ServerPlayerEntity, LocationData> spectating = new HashMap<>();
|
||||
|
||||
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, String... aliases) {
|
||||
for (String str : aliases)
|
||||
dispatcher.register(CommandManager.literal(str) // Ensure correct method name
|
||||
.executes(SpectatorCommand::execute));
|
||||
}
|
||||
|
||||
private static int execute(CommandContext<ServerCommandSource> context) {
|
||||
ServerCommandSource source = context.getSource();
|
||||
if (source.getEntity() == null) { // Ensure correct method name
|
||||
source.sendMessage(Text.literal("Console cannot go into spectator mode!"));
|
||||
return 0;
|
||||
}
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) source.getEntity(); // Ensure correct method name
|
||||
if (spectating.containsKey(player)) {
|
||||
LocationData data = spectating.get(player);
|
||||
player.teleport(data.world, data.x, data.y, data.z, Set.of(), data.yaw, data.pitch, false);
|
||||
player.changeGameMode(GameMode.SURVIVAL);
|
||||
spectating.remove(player);
|
||||
} else {
|
||||
|
||||
spectating.put(player, new LocationData(player
|
||||
.getX(), player
|
||||
.getY(), player
|
||||
.getZ(), player
|
||||
.getYaw(), player
|
||||
.getPitch(), player
|
||||
.getServerWorld()));
|
||||
player.changeGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
public static class LocationData {
|
||||
|
||||
public final double x;
|
||||
|
||||
public final double y;
|
||||
|
||||
public final double z;
|
||||
|
||||
public final float yaw;
|
||||
|
||||
public final float pitch;
|
||||
|
||||
public final ServerWorld world;
|
||||
|
||||
LocationData(double x, double y, double z, float yaw, float pitch, ServerWorld world) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.world = world;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package wtf.hak.survivalfabric.mixin;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
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;
|
||||
|
||||
@Mixin(MinecraftServer.class)
|
||||
public class ExampleMixin {
|
||||
@Inject(at = @At("HEAD"), method = "loadWorld")
|
||||
private void init(CallbackInfo info) {
|
||||
// This code is injected into the start of MinecraftServer.loadWorld()V
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package wtf.hak.survivalfabric.mixin;
|
||||
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.network.message.MessageType;
|
||||
import net.minecraft.network.message.SignedMessage;
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.network.ConnectedClientData;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TextContent;
|
||||
import net.minecraft.world.GameMode;
|
||||
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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import wtf.hak.survivalfabric.commands.SpectatorCommand;
|
||||
import wtf.hak.survivalfabric.utils.Messages;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(PlayerManager.class)
|
||||
public abstract class PlayerManagerMixin {
|
||||
|
||||
@Inject(method = {"onPlayerConnect"}, at = {@At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")})
|
||||
public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) {
|
||||
Text text = Text.literal(String.format(Messages.JOIN_MESSAGE, player.getName().getString()));
|
||||
player.sendMessage(text, false);
|
||||
}
|
||||
|
||||
@ModifyArg(method = {"onPlayerConnect"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V"))
|
||||
private Text onPlayerConnect(Text text) {
|
||||
String name = text.getString().split(" ")[0];
|
||||
return Text.literal(String.format(Messages.JOIN_MESSAGE, name));
|
||||
}
|
||||
|
||||
@Inject(method = {"remove"}, at = {@At("HEAD")})
|
||||
public void onPlayerLeave(ServerPlayerEntity player, CallbackInfo ci) {
|
||||
if(SpectatorCommand.spectating.containsKey(player)) {
|
||||
SpectatorCommand.LocationData loc = SpectatorCommand.spectating.remove(player);
|
||||
player.teleport(loc.world, loc.x,loc.y,loc.z, Set.of(), loc.yaw, loc.pitch, false);
|
||||
player.changeGameMode(GameMode.SURVIVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = {"broadcast(Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V"}, at = {@At("HEAD")}, cancellable = true)
|
||||
private void onBroadcast(SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters parameters, CallbackInfo ci) {
|
||||
if(sender != null) {
|
||||
Text text = Text.literal(String.format(Messages.CHAT_FORMAT, sender.getName().getString(), message.getContent().getString()));
|
||||
sender.getServer().getPlayerManager().broadcast(text, false);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package wtf.hak.survivalfabric.mixin;
|
||||
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import wtf.hak.survivalfabric.utils.Messages;
|
||||
|
||||
@Mixin(ServerPlayNetworkHandler.class)
|
||||
public abstract class ServerPlayNetworkHandlerMixin {
|
||||
|
||||
@ModifyArg(method = {"cleanUp"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V"))
|
||||
private Text quitMessage(Text text) {
|
||||
String name = text.getString().split(" ")[0];
|
||||
return Text.literal(String.format(Messages.QUIT_MESSAGE, name));
|
||||
}
|
||||
}
|
9
src/main/java/wtf/hak/survivalfabric/utils/Messages.java
Normal file
9
src/main/java/wtf/hak/survivalfabric/utils/Messages.java
Normal file
@ -0,0 +1,9 @@
|
||||
package wtf.hak.survivalfabric.utils;
|
||||
|
||||
public class Messages {
|
||||
public static final String JOIN_MESSAGE = "§8[§a+§8] §7%s";
|
||||
|
||||
public static final String QUIT_MESSAGE = "§8[§c-§8] §7%s";
|
||||
|
||||
public static final String CHAT_FORMAT = "§7%s§8:§f %s";
|
||||
}
|
@ -3,7 +3,8 @@
|
||||
"package": "wtf.hak.survivalfabric.mixin",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"mixins": [
|
||||
"ExampleMixin"
|
||||
"PlayerManagerMixin",
|
||||
"ServerPlayNetworkHandlerMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
Reference in New Issue
Block a user