优化成员权限缓存更新加载策略,提高效率

This commit is contained in:
zhangyuheng 2024-06-21 14:33:21 +08:00
parent 2f9c4cd73a
commit 278ce8a686
6 changed files with 194 additions and 160 deletions

View File

@ -6,7 +6,7 @@
<groupId>cn.lunadeer</groupId>
<artifactId>Dominion</artifactId>
<version>1.33.2-mysql-beta</version>
<version>1.33.3-mysql-beta</version>
<packaging>jar</packaging>
<name>Dominion</name>

View File

@ -1,6 +1,7 @@
package cn.lunadeer.dominion;
import cn.lunadeer.dominion.dtos.DominionDTO;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import cn.lunadeer.minecraftpluginutils.XLogger;
import com.flowpowered.math.vector.Vector2d;
import de.bluecolored.bluemap.api.BlueMapAPI;
@ -17,112 +18,116 @@ public class BlueMapConnect {
if (!Dominion.config.getBlueMap()) {
return;
}
try {
BlueMapAPI.getInstance().ifPresent(api -> {
Map<String, List<DominionDTO>> world_dominions = new HashMap<>();
for (DominionDTO dominion : Cache.instance.getDominions()) {
if (!world_dominions.containsKey(dominion.getWorld())) {
world_dominions.put(dominion.getWorld(), new ArrayList<>());
Scheduler.runTaskAsync(() -> {
try {
BlueMapAPI.getInstance().ifPresent(api -> {
Map<String, List<DominionDTO>> world_dominions = new HashMap<>();
for (DominionDTO dominion : Cache.instance.getDominions()) {
if (!world_dominions.containsKey(dominion.getWorld())) {
world_dominions.put(dominion.getWorld(), new ArrayList<>());
}
world_dominions.get(dominion.getWorld()).add(dominion);
}
world_dominions.get(dominion.getWorld()).add(dominion);
}
for (Map.Entry<String, List<DominionDTO>> d : world_dominions.entrySet()) {
api.getWorld(d.getKey()).ifPresent(world -> {
MarkerSet markerSet = MarkerSet.builder()
.label("Dominion")
.build();
for (DominionDTO dominion : d.getValue()) {
Collection<Vector2d> vectors = new ArrayList<>();
vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ1() + 0.001));
vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ1() + 0.001));
vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ2() - 0.001));
vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ2() - 0.001));
Shape shape = new Shape(vectors);
double x = vectors.iterator().next().getX();
double z = vectors.iterator().next().getY();
double y = dominion.getY1();
int r = dominion.getColorR();
int g = dominion.getColorG();
int b = dominion.getColorB();
Color line = new Color(r, g, b, 0.8F);
Color fill = new Color(r, g, b, 0.2F);
ExtrudeMarker marker = ExtrudeMarker.builder()
.label(dominion.getName())
.position(x, y, z)
.shape(shape, dominion.getY1() + 0.001f, dominion.getY2() - 0.001f)
.lineColor(line)
.fillColor(fill)
for (Map.Entry<String, List<DominionDTO>> d : world_dominions.entrySet()) {
api.getWorld(d.getKey()).ifPresent(world -> {
MarkerSet markerSet = MarkerSet.builder()
.label("Dominion")
.build();
markerSet.getMarkers()
.put(dominion.getName(), marker);
}
for (BlueMapMap map : world.getMaps()) {
map.getMarkerSets().put(d.getKey() + "-" + markerSet.getLabel(), markerSet);
}
});
}
});
} catch (NoClassDefFoundError e) {
XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。");
XLogger.err(e.getMessage());
}
for (DominionDTO dominion : d.getValue()) {
Collection<Vector2d> vectors = new ArrayList<>();
vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ1() + 0.001));
vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ1() + 0.001));
vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ2() - 0.001));
vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ2() - 0.001));
Shape shape = new Shape(vectors);
double x = vectors.iterator().next().getX();
double z = vectors.iterator().next().getY();
double y = dominion.getY1();
int r = dominion.getColorR();
int g = dominion.getColorG();
int b = dominion.getColorB();
Color line = new Color(r, g, b, 0.8F);
Color fill = new Color(r, g, b, 0.2F);
ExtrudeMarker marker = ExtrudeMarker.builder()
.label(dominion.getName())
.position(x, y, z)
.shape(shape, dominion.getY1() + 0.001f, dominion.getY2() - 0.001f)
.lineColor(line)
.fillColor(fill)
.build();
markerSet.getMarkers()
.put(dominion.getName(), marker);
}
for (BlueMapMap map : world.getMaps()) {
map.getMarkerSets().put(d.getKey() + "-" + markerSet.getLabel(), markerSet);
}
});
}
});
} catch (NoClassDefFoundError e) {
XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。");
XLogger.err(e.getMessage());
}
});
}
public static void renderMCA(Map<String, List<String>> mca_files) {
if (!Dominion.config.getBlueMap()) {
return;
}
try {
BlueMapAPI.getInstance().ifPresent(api -> {
for (String world : mca_files.keySet()) {
api.getWorld(world).ifPresent(bmWorld -> {
MarkerSet markerSet = MarkerSet.builder()
.label("MCA")
.defaultHidden(true)
.build();
for (String file : mca_files.get(world)) {
// r.-1.-1.mca
int mca_x = Integer.parseInt(file.split("\\.")[1]);
int mca_z = Integer.parseInt(file.split("\\.")[2]);
int world_x1 = mca_x * 512;
int world_x2 = (mca_x + 1) * 512;
int world_z1 = mca_z * 512;
int world_z2 = (mca_z + 1) * 512;
Collection<Vector2d> vectors = new ArrayList<>();
vectors.add(new Vector2d(world_x1 + 0.001, world_z1 + 0.001));
vectors.add(new Vector2d(world_x2 - 0.001, world_z1 + 0.001));
vectors.add(new Vector2d(world_x2 - 0.001, world_z2 - 0.001));
vectors.add(new Vector2d(world_x1 + 0.001, world_z2 - 0.001));
Shape shape = new Shape(vectors);
double x = vectors.iterator().next().getX();
double z = vectors.iterator().next().getY();
double y = -64;
Color line = new Color(0, 204, 0, 0.8F);
Color fill = new Color(0, 204, 0, 0.2F);
ExtrudeMarker marker = ExtrudeMarker.builder()
.label(file)
.position(x, y, z)
.shape(shape, -64, 320)
.lineColor(line)
.fillColor(fill)
Scheduler.runTaskAsync(() -> {
try {
BlueMapAPI.getInstance().ifPresent(api -> {
for (String world : mca_files.keySet()) {
api.getWorld(world).ifPresent(bmWorld -> {
MarkerSet markerSet = MarkerSet.builder()
.label("MCA")
.defaultHidden(true)
.build();
markerSet.getMarkers()
.put(file, marker);
}
for (BlueMapMap map : bmWorld.getMaps()) {
map.getMarkerSets().put(world + "-" + markerSet.getLabel(), markerSet);
}
});
}
});
} catch (NoClassDefFoundError e) {
XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。");
XLogger.err(e.getMessage());
}
for (String file : mca_files.get(world)) {
// r.-1.-1.mca
int mca_x = Integer.parseInt(file.split("\\.")[1]);
int mca_z = Integer.parseInt(file.split("\\.")[2]);
int world_x1 = mca_x * 512;
int world_x2 = (mca_x + 1) * 512;
int world_z1 = mca_z * 512;
int world_z2 = (mca_z + 1) * 512;
Collection<Vector2d> vectors = new ArrayList<>();
vectors.add(new Vector2d(world_x1 + 0.001, world_z1 + 0.001));
vectors.add(new Vector2d(world_x2 - 0.001, world_z1 + 0.001));
vectors.add(new Vector2d(world_x2 - 0.001, world_z2 - 0.001));
vectors.add(new Vector2d(world_x1 + 0.001, world_z2 - 0.001));
Shape shape = new Shape(vectors);
double x = vectors.iterator().next().getX();
double z = vectors.iterator().next().getY();
double y = -64;
Color line = new Color(0, 204, 0, 0.8F);
Color fill = new Color(0, 204, 0, 0.2F);
ExtrudeMarker marker = ExtrudeMarker.builder()
.label(file)
.position(x, y, z)
.shape(shape, -64, 320)
.lineColor(line)
.fillColor(fill)
.build();
markerSet.getMarkers()
.put(file, marker);
}
for (BlueMapMap map : bmWorld.getMaps()) {
map.getMarkerSets().put(world + "-" + markerSet.getLabel(), markerSet);
}
});
}
});
} catch (NoClassDefFoundError e) {
XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。");
XLogger.err(e.getMessage());
}
});
}
}

View File

@ -51,68 +51,85 @@ public class Cache {
}
private void loadDominionsExecution() {
long start = System.currentTimeMillis();
id_dominions = new ConcurrentHashMap<>();
world_dominion_tree = new ConcurrentHashMap<>();
dominion_children = new ConcurrentHashMap<>();
List<DominionDTO> dominions = DominionDTO.selectAll();
Map<String, List<DominionDTO>> world_dominions = new HashMap<>();
for (DominionDTO d : dominions) {
if (!world_dominions.containsKey(d.getWorld())) {
world_dominions.put(d.getWorld(), new ArrayList<>());
Scheduler.runTaskAsync(() -> {
long start = System.currentTimeMillis();
id_dominions = new ConcurrentHashMap<>();
world_dominion_tree = new ConcurrentHashMap<>();
dominion_children = new ConcurrentHashMap<>();
List<DominionDTO> dominions = DominionDTO.selectAll();
Map<String, List<DominionDTO>> world_dominions = new HashMap<>();
for (DominionDTO d : dominions) {
if (!world_dominions.containsKey(d.getWorld())) {
world_dominions.put(d.getWorld(), new ArrayList<>());
}
world_dominions.get(d.getWorld()).add(d);
id_dominions.put(d.getId(), d);
if (!dominion_children.containsKey(d.getParentDomId())) {
dominion_children.put(d.getParentDomId(), new ArrayList<>());
}
dominion_children.get(d.getParentDomId()).add(d.getId());
}
world_dominions.get(d.getWorld()).add(d);
id_dominions.put(d.getId(), d);
if (!dominion_children.containsKey(d.getParentDomId())) {
dominion_children.put(d.getParentDomId(), new ArrayList<>());
for (Map.Entry<String, List<DominionDTO>> entry : world_dominions.entrySet()) {
world_dominion_tree.put(entry.getKey(), DominionNode.BuildNodeTree(-1, entry.getValue()));
}
dominion_children.get(d.getParentDomId()).add(d.getId());
}
for (Map.Entry<String, List<DominionDTO>> entry : world_dominions.entrySet()) {
world_dominion_tree.put(entry.getKey(), DominionNode.BuildNodeTree(-1, entry.getValue()));
}
BlueMapConnect.render();
recheckPlayerState = true;
_last_update_dominion.set(System.currentTimeMillis());
XLogger.debug("loadDominionsExecution cost: %d ms", System.currentTimeMillis() - start);
BlueMapConnect.render();
recheckPlayerState = true;
_last_update_dominion.set(System.currentTimeMillis());
XLogger.debug("loadDominionsExecution cost: %d ms for %d dominions"
, System.currentTimeMillis() - start, dominions.size());
});
}
/**
* 从数据库加载所有玩家特权
* 如果player_uuid为null则加载所有玩家的特权
*
* @param player_uuid 玩家UUID
*/
public void loadPlayerPrivileges() {
public void loadPlayerPrivileges(UUID player_uuid) {
if (_last_update_privilege.get() + UPDATE_INTERVAL < System.currentTimeMillis()) {
loadPlayerPrivilegesExecution();
XLogger.debug("run loadPlayerPrivilegesExecution directly");
loadPlayerPrivilegesExecution(player_uuid);
} else {
if (_update_privilege_is_scheduled.get()) return;
XLogger.debug("schedule loadPlayerPrivilegesExecution");
_update_privilege_is_scheduled.set(true);
long delay_tick = (UPDATE_INTERVAL - (System.currentTimeMillis() - _last_update_dominion.get())) / 1000 * 20L;
long delay_tick = (UPDATE_INTERVAL - (System.currentTimeMillis() - _last_update_privilege.get())) / 1000 * 20L;
Scheduler.runTaskLaterAsync(() -> {
loadPlayerPrivilegesExecution();
XLogger.debug("run loadPlayerPrivilegesExecution scheduled");
loadPlayerPrivilegesExecution(player_uuid);
_update_privilege_is_scheduled.set(false);
},
delay_tick);
}
}
private void loadPlayerPrivilegesExecution() {
long start = System.currentTimeMillis();
List<PlayerPrivilegeDTO> all_privileges = PlayerPrivilegeDTO.selectAll();
if (all_privileges == null) {
XLogger.err("加载玩家特权失败");
return;
}
player_uuid_to_privilege = new ConcurrentHashMap<>();
for (PlayerPrivilegeDTO privilege : all_privileges) {
UUID player_uuid = privilege.getPlayerUUID();
if (!player_uuid_to_privilege.containsKey(player_uuid)) {
player_uuid_to_privilege.put(player_uuid, new ConcurrentHashMap<>());
public void loadPlayerPrivileges() {
loadPlayerPrivileges(null);
}
private void loadPlayerPrivilegesExecution(UUID player_to_update) {
Scheduler.runTaskAsync(() -> {
long start = System.currentTimeMillis();
List<PlayerPrivilegeDTO> all_privileges = new ArrayList<>();
if (player_to_update == null) {
all_privileges = PlayerPrivilegeDTO.selectAll();
player_uuid_to_privilege = new ConcurrentHashMap<>();
} else {
all_privileges = PlayerPrivilegeDTO.selectAll(player_to_update);
}
player_uuid_to_privilege.get(player_uuid).put(privilege.getDomID(), privilege);
}
recheckPlayerState = true;
_last_update_privilege.set(System.currentTimeMillis());
XLogger.debug("loadPlayerPrivilegesExecution cost: %d ms", System.currentTimeMillis() - start);
for (PlayerPrivilegeDTO privilege : all_privileges) {
UUID player_uuid = privilege.getPlayerUUID();
if (!player_uuid_to_privilege.containsKey(player_uuid)) {
player_uuid_to_privilege.put(player_uuid, new ConcurrentHashMap<>());
}
player_uuid_to_privilege.get(player_uuid).put(privilege.getDomID(), privilege);
}
recheckPlayerState = true;
_last_update_privilege.set(System.currentTimeMillis());
XLogger.debug("loadPlayerPrivilegesExecution cost: %d ms for %d privileges"
, System.currentTimeMillis() - start, all_privileges.size());
});
}
/**
@ -318,7 +335,7 @@ public class Cache {
private final AtomicBoolean _update_dominion_is_scheduled = new AtomicBoolean(false);
private final AtomicLong _last_update_privilege = new AtomicLong(0);
private final AtomicBoolean _update_privilege_is_scheduled = new AtomicBoolean(false);
private static final long UPDATE_INTERVAL = 1000 * 5;
private static final long UPDATE_INTERVAL = 1000 * 4;
private boolean recheckPlayerState = false; // 是否需要重新检查玩家状态发光飞行
public final Map<UUID, LocalDateTime> NextTimeAllowTeleport = new java.util.HashMap<>();
}

View File

@ -5,24 +5,38 @@ import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.*;
public class DominionNode {
public DominionDTO dominion;
public List<DominionNode> children = new ArrayList<>();
public static List<DominionNode> BuildNodeTree(Integer rootId, List<DominionDTO> dominions) {
List<DominionNode> dominionTree = new ArrayList<>();
// 映射父节点ID到其子节点列表
Map<Integer, List<DominionDTO>> parentToChildrenMap = new HashMap<>();
for (DominionDTO dominion : dominions) {
if (Objects.equals(dominion.getParentDomId(), rootId)) {
parentToChildrenMap
.computeIfAbsent(dominion.getParentDomId(), k -> new ArrayList<>())
.add(dominion);
}
// 递归构建节点树
return buildTree(rootId, parentToChildrenMap);
}
private static List<DominionNode> buildTree(Integer rootId, Map<Integer, List<DominionDTO>> parentToChildrenMap) {
List<DominionNode> dominionTree = new ArrayList<>();
List<DominionDTO> children = parentToChildrenMap.get(rootId);
if (children != null) {
for (DominionDTO dominion : children) {
DominionNode node = new DominionNode();
node.dominion = dominion;
node.children = BuildNodeTree(dominion.getId(), dominions);
node.children = buildTree(dominion.getId(), parentToChildrenMap);
dominionTree.add(node);
}
}
return dominionTree;
}

View File

@ -103,18 +103,17 @@ public class PrivilegeController {
privilege = createPlayerPrivilege(operator, player.getUuid(), dominion);
if (privilege == null) return;
}
if (privilege.getAdmin()) {
if (notOwner(operator, dominion)) {
operator.setResponse(FAIL.addMessage("你不是领地 %s 的拥有者,无法修改其他管理员的权限", dominionName));
return;
}
if (flag.equals("admin")) {
privilege.setAdmin(value);
} else {
if ((flag.equals("admin") || privilege.getAdmin()) && notOwner(operator, dominion)) {
operator.setResponse(FAIL.addMessage("你不是领地 %s 的拥有者,无法修改其他玩家管理员的权限", dominionName));
return;
}
if (flag.equals("admin")) {
privilege.setAdmin(value);
} else {
if (privilege.getAdmin()) {
operator.setResponse(FAIL.addMessage("管理员拥有所有权限,无需单独设置权限"));
return;
}
} else {
Flag f = Flag.getFlag(flag);
if (f == null) {
operator.setResponse(FAIL.addMessage("未知的领地权限 %s", flag));

View File

@ -44,7 +44,7 @@ public class PlayerPrivilegeDTO {
try (ResultSet rs = updateRow.execute()) {
List<PlayerPrivilegeDTO> players = getDTOFromRS(rs);
if (players.size() == 0) return null;
Cache.instance.loadPlayerPrivileges();
Cache.instance.loadPlayerPrivileges(playerUUID);
return players.get(0);
} catch (Exception e) {
DatabaseManager.handleDatabaseError("更新玩家权限失败: ", e, "");
@ -65,7 +65,7 @@ public class PlayerPrivilegeDTO {
insertRow.field(new Field(f.getFlagName(), player.getFlagValue(f)));
}
try (ResultSet rs = insertRow.execute()) {
Cache.instance.loadPlayerPrivileges();
Cache.instance.loadPlayerPrivileges(player.getPlayerUUID());
List<PlayerPrivilegeDTO> players = getDTOFromRS(rs);
if (players.size() == 0) return null;
return players.get(0);
@ -134,7 +134,6 @@ public class PlayerPrivilegeDTO {
flags.put(flag, value);
Field f = new Field(flag.getFlagName(), value);
UpdateRow updateRow = new UpdateRow().field(f);
XLogger.debug("setFlagValue: " + updateRow.toString());
return doUpdate(updateRow);
}