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.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user