Implemented cursor manager for deduplicated cursor updating

This commit is contained in:
Manuel Frohn
2025-04-30 12:17:48 +02:00
parent 54adc12045
commit aa787b5a25
2 changed files with 106 additions and 14 deletions
@@ -1,27 +1,35 @@
package de.steamwar.bausystem.utils;
package de.steamwar.bausystem.utils.cursor;
import de.steamwar.bausystem.utils.RayTraceUtils;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@Getter
public class RCursor {
private Player owner;
private REntityServer targetServer;
private final REntityServer targetServer;
private final Player owner;
private final Material highlightMaterial;
@Setter
private Material cursorMaterial;
private RFallingBlockEntity cursorEntity;
private Material highlightMaterial;
private Material cursorMaterial;
public RCursor(REntityServer targetServer, Material highlightMaterial, Material cursorMaterial) {
public RCursor(REntityServer targetServer, Player owner, Material highlightMaterial, Material cursorMaterial) {
this.targetServer = targetServer;
this.owner = owner;
this.highlightMaterial = highlightMaterial;
this.cursorMaterial = cursorMaterial;
RCursorManager.getInstance().registerCursor(this);
}
public void render() {
@@ -31,7 +39,8 @@ public class RCursor {
return;
}
REntity hitEntity = rayTraceResult.getHitEntity();
REntity hitEntity = rayTraceResult.getHitEntity() == cursorEntity ? null : rayTraceResult.getHitEntity();
Material activeCursorMaterial = hitEntity == null ? cursorMaterial : highlightMaterial;
Location activeCursorLocation = hitEntity == null ? rayTraceResult.getHitPosition().toLocation(owner.getWorld())
@@ -39,13 +48,19 @@ public class RCursor {
if (cursorEntity == null) {
cursorEntity = new RFallingBlockEntity(targetServer, activeCursorLocation, activeCursorMaterial);
}
else if(cursorEntity.getMaterial() == activeCursorMaterial) {
cursorEntity.setNoGravity(true);
} else if (cursorEntity.getMaterial() == activeCursorMaterial) {
cursorEntity.move(activeCursorLocation);
}
else {
} else {
cursorEntity.die();
cursorEntity = new RFallingBlockEntity(targetServer, activeCursorLocation, activeCursorMaterial);
cursorEntity.setNoGravity(true);
}
}
public void hide() {
if (cursorEntity != null) {
cursorEntity.die();
}
}
}
@@ -0,0 +1,77 @@
package de.steamwar.bausystem.utils.cursor;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.linkage.Linked;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
@Linked
public class RCursorManager {
@Getter
private static RCursorManager instance;
private final Set<Player> calculationActive = new HashSet<>();
private final Map<Player, SoftReference<RCursor>> activeCursors = new HashMap<>();
public RCursorManager() {
if (instance == null) {
instance = this;
}
BiFunction<Player, Object, Object> function = (player, object) -> {
updateCursor(player);
return object;
};
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
Set<Player> playersWithActiveCursor = activeCursors.keySet();
playersWithActiveCursor.forEach(this::updateCursor);
}, 0);
Class<?> positionPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
Class<?> lookPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot");
Class<?> positionLookPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
TinyProtocol.instance.addFilter(positionPacketClass, function);
TinyProtocol.instance.addFilter(lookPacketClass, function);
TinyProtocol.instance.addFilter(positionLookPacketClass, function);
}
public void registerCursor(RCursor cursor) {
activeCursors.put(cursor.getOwner(), new SoftReference<>(cursor));
}
private void updateCursor(Player player) {
synchronized (calculationActive) {
if (calculationActive.contains(player)) {
return;
} else {
calculationActive.add(player);
}
}
SoftReference<RCursor> cursorRef = activeCursors.get(player);
RCursor cursor = cursorRef.get();
if (cursor == null) {
activeCursors.remove(player);
} else {
cursor.render();
}
synchronized (calculationActive) {
calculationActive.remove(player);
}
}
}