9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-29 11:59:11 +00:00

feat(bukkit): 添加限制可视家具数量

This commit is contained in:
jhqwqmc
2025-05-18 00:18:22 +08:00
parent ee10b56090
commit df86e822db
5 changed files with 238 additions and 14 deletions

View File

@@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.network;
import io.netty.channel.Channel;
import net.momirealms.craftengine.core.plugin.Plugin;
import net.momirealms.craftengine.core.util.DynamicPriorityTracker;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.ApiStatus;
@@ -43,6 +44,8 @@ public interface NetWorkUser {
Map<Integer, EntityPacketHandler> entityPacketHandlers();
DynamicPriorityTracker visualFurnitureView();
boolean clientModEnabled();
void setClientModState(boolean enable);

View File

@@ -0,0 +1,161 @@
package net.momirealms.craftengine.core.util;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
public class DynamicPriorityTracker {
public static class Element {
private final int entityId;
private volatile double distance;
private final Object removePacket;
public Element(int entityId, double distance, Object removePacket) {
this.entityId = entityId;
this.distance = distance;
this.removePacket = removePacket;
}
public int entityId() {
return entityId;
}
public double distance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public Object removePacket() {
return removePacket;
}
}
public static class UpdateResult {
private final List<Element> entered = new ArrayList<>();
private final List<Element> exited = new ArrayList<>();
public List<Element> getEntered() {
return entered;
}
public List<Element> getExited() {
return exited;
}
void addEntered(Element e) {
entered.add(e);
}
void addExited(Element e) {
exited.add(e);
}
}
private final int capacity;
private final PriorityQueue<Element> maxHeap;
private final Map<Integer, Element> elementMap = new ConcurrentHashMap<>();
private final Set<Integer> inHeapSet = ConcurrentHashMap.newKeySet();
private final ReentrantLock heapLock = new ReentrantLock();
public DynamicPriorityTracker(int capacity) {
this.capacity = capacity;
this.maxHeap = new PriorityQueue<>((a, b) -> Double.compare(b.distance, a.distance));
}
public UpdateResult addOrUpdateElement(Element newElement) {
UpdateResult result = new UpdateResult();
heapLock.lock();
try {
Element existing = elementMap.get(newElement.entityId);
if (existing != null) {
return handleExistingElement(existing, newElement, result);
} else {
return handleNewElement(newElement, result);
}
} finally {
heapLock.unlock();
}
}
private UpdateResult handleNewElement(Element newElement, UpdateResult result) {
elementMap.put(newElement.entityId, newElement);
if (maxHeap.size() < capacity) {
maxHeap.offer(newElement);
inHeapSet.add(newElement.entityId);
result.addEntered(newElement);
} else if (maxHeap.peek() != null && newElement.distance < maxHeap.peek().distance) {
Element removed = maxHeap.poll();
inHeapSet.remove(removed.entityId);
result.addExited(removed);
maxHeap.offer(newElement);
inHeapSet.add(newElement.entityId);
result.addEntered(newElement);
}
return result;
}
private UpdateResult handleExistingElement(Element existing, Element newElement, UpdateResult result) {
existing.setDistance(newElement.distance);
boolean wasInHeap = inHeapSet.contains(existing.entityId);
boolean nowInHeap = checkIfShouldBeInHeap(existing.distance);
if (wasInHeap) {
maxHeap.remove(existing);
maxHeap.offer(existing);
} else if (nowInHeap) {
if (maxHeap.size() < capacity) {
maxHeap.offer(existing);
inHeapSet.add(existing.entityId);
result.addEntered(existing);
} else if (maxHeap.peek() != null && existing.distance < maxHeap.peek().distance) {
Element removed = maxHeap.poll();
inHeapSet.remove(removed.entityId);
result.addExited(removed);
maxHeap.offer(existing);
inHeapSet.add(existing.entityId);
result.addEntered(existing);
}
}
return result;
}
private boolean checkIfShouldBeInHeap(double distance) {
if (maxHeap.size() < capacity) return true;
return maxHeap.peek() != null && distance < maxHeap.peek().distance;
}
public int getTotalMembers() {
heapLock.lock();
try {
return elementMap.size();
} finally {
heapLock.unlock();
}
}
public List<Element> getAllElements() {
heapLock.lock();
try {
return List.copyOf(elementMap.values());
} finally {
heapLock.unlock();
}
}
public Element removeByEntityId(int entityId) {
heapLock.lock();
try {
Element removed = elementMap.remove(entityId);
if (removed != null) {
maxHeap.remove(removed);
}
return removed;
} finally {
heapLock.unlock();
}
}
}