Files
fdgdfg/src/client/java/ru/nevetime/clientirc/MiddleClickHandler.java
arkonsadter c25e394d50 Add friends, markers, HUD overlays, tab complete
- FriendsManager persists a per-user friend list at config/clientirc-friends.json.
- MarkerManager holds one ephemeral marker per owner (5 min expiry).
- IRC protocol extended with marker_set / marker_remove; server relays them.
- IrcService DisplayLine replaced with sealed IrcEvent (Chat / System / MarkerSet / MarkerRemove); chat formatting moved into the client.
- ClientIrcMod handles .friends add/remove/list, .marker remove, .help; chat lines from friends are prefixed with a green dot; marker events from non-friends are ignored.
- OverlayHud draws a top-center compass strip and a top-left watermark (nick / FPS / ping) via HudLayerRegistrationCallback.
- WorldOverlayRenderer draws green crosses above friends and magenta beams + base cubes at active markers via WorldRenderEvents.AFTER_ENTITIES.
- MiddleClickHandler binds MMB via KeyMapping, raycasts a block or 20-block look ray, stores locally and sends marker_set on a daemon executor.
- ChatScreenMixin completes . prefix commands on Tab; first mixin in the project, plumbed through clientirc.client.mixins.json and fabric.mod.json.
2026-06-21 21:16:32 +06:00

73 lines
2.8 KiB
Java

package ru.nevetime.clientirc;
import com.mojang.blaze3d.platform.InputConstants;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import org.lwjgl.glfw.GLFW;
public final class MiddleClickHandler {
private static final ExecutorService IO_EXECUTOR =
Executors.newSingleThreadExecutor(runnable -> {
Thread t = new Thread(runnable, "clientirc-marker-io");
t.setDaemon(true);
return t;
});
private static KeyMapping markerKey;
private MiddleClickHandler() {}
public static void init(Supplier<IrcService> serviceSupplier, Supplier<String> playerNameSupplier) {
markerKey = new KeyMapping(
"key.clientirc.marker",
InputConstants.Type.MOUSE,
GLFW.GLFW_MOUSE_BUTTON_MIDDLE,
"category.clientirc"
);
KeyBindingHelper.registerKeyBinding(markerKey);
ClientTickEvents.END_CLIENT_TICK.register(client -> {
while (markerKey.consumeClick()) {
if (client.player == null || client.level == null) break;
Vec3 target;
if (client.hitResult instanceof BlockHitResult br && br.getType() != HitResult.Type.MISS) {
target = br.getBlockPos().getCenter();
} else {
Vec3 eye = client.player.getEyePosition();
Vec3 look = client.player.getViewVector(1.0f);
target = eye.add(look.scale(20.0));
}
String dimId = client.level.dimension().location().toString();
String playerName = playerNameSupplier.get();
double tx = target.x, ty = target.y, tz = target.z;
MarkerManager.set(new MarkerManager.Marker(playerName, dimId, tx, ty, tz, System.currentTimeMillis()));
IO_EXECUTOR.execute(() -> {
IrcService service = serviceSupplier.get();
if (service != null) service.sendMarkerSet(playerName, dimId, tx, ty, tz);
});
}
});
}
public static void removeOwnMarker(Supplier<IrcService> serviceSupplier, Supplier<String> playerNameSupplier) {
String name = playerNameSupplier.get();
MarkerManager.remove(name);
IO_EXECUTOR.execute(() -> {
IrcService service = serviceSupplier.get();
if (service != null) service.sendMarkerRemove(name);
});
}
}