mirror of
https://github.com/ColdeZhang/Dominion.git
synced 2024-10-19 03:26:40 +08:00
重写缓存逻辑、优化在大量领地数据下的检索速度
This commit is contained in:
parent
1c6f9f410f
commit
da10ce05e2
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>cn.lunadeer</groupId>
|
||||
<artifactId>Dominion</artifactId>
|
||||
<version>1.28.12-beta</version>
|
||||
<version>1.29.0-beta</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Dominion</name>
|
||||
|
@ -10,10 +10,7 @@ import de.bluecolored.bluemap.api.markers.MarkerSet;
|
||||
import de.bluecolored.bluemap.api.math.Color;
|
||||
import de.bluecolored.bluemap.api.math.Shape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class BlueMapConnect {
|
||||
public static void render() {
|
||||
@ -22,14 +19,20 @@ public class BlueMapConnect {
|
||||
}
|
||||
try {
|
||||
BlueMapAPI.getInstance().ifPresent(api -> {
|
||||
for (Map.Entry<String, List<Integer>> world_dominions : Cache.instance.getWorldDominions().entrySet()) {
|
||||
api.getWorld(world_dominions.getKey()).ifPresent(world -> {
|
||||
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);
|
||||
}
|
||||
for (Map.Entry<String, List<DominionDTO>> d : world_dominions.entrySet()) {
|
||||
api.getWorld(d.getKey()).ifPresent(world -> {
|
||||
MarkerSet markerSet = MarkerSet.builder()
|
||||
.label("Dominion")
|
||||
.build();
|
||||
|
||||
for (Integer id : world_dominions.getValue()) {
|
||||
DominionDTO dominion = Cache.instance.getDominion(id);
|
||||
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));
|
||||
@ -58,7 +61,7 @@ public class BlueMapConnect {
|
||||
}
|
||||
|
||||
for (BlueMapMap map : world.getMaps()) {
|
||||
map.getMarkerSets().put(world_dominions.getKey() + "-" + markerSet.getLabel(), markerSet);
|
||||
map.getMarkerSets().put(d.getKey() + "-" + markerSet.getLabel(), markerSet);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package cn.lunadeer.dominion;
|
||||
|
||||
import cn.lunadeer.dominion.dtos.DominionDTO;
|
||||
import cn.lunadeer.dominion.dtos.Flag;
|
||||
import cn.lunadeer.dominion.dtos.PlayerDTO;
|
||||
import cn.lunadeer.dominion.dtos.PlayerPrivilegeDTO;
|
||||
import cn.lunadeer.minecraftpluginutils.ParticleRender;
|
||||
import cn.lunadeer.minecraftpluginutils.Scheduler;
|
||||
@ -18,6 +19,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static cn.lunadeer.dominion.DominionNode.getLocInDominionDTO;
|
||||
|
||||
public class Cache {
|
||||
|
||||
public Cache() {
|
||||
@ -49,24 +52,23 @@ public class Cache {
|
||||
|
||||
private void loadDominionsExecution() {
|
||||
id_dominions = new ConcurrentHashMap<>();
|
||||
world_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 (!dominion_children.containsKey(d.getId())) {
|
||||
dominion_children.put(d.getId(), new ArrayList<>());
|
||||
}
|
||||
id_dominions.put(d.getId(), d);
|
||||
if (!world_dominions.containsKey(d.getWorld())) {
|
||||
world_dominions.put(d.getWorld(), new ArrayList<>());
|
||||
}
|
||||
world_dominions.get(d.getWorld()).add(d.getId());
|
||||
if (d.getParentDomId() != -1) {
|
||||
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<>());
|
||||
}
|
||||
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();
|
||||
_last_update_dominion.set(System.currentTimeMillis());
|
||||
@ -117,64 +119,50 @@ public class Cache {
|
||||
* @return 玩家当前所在领地
|
||||
*/
|
||||
public DominionDTO getPlayerCurrentDominion(Player player) {
|
||||
Integer dominion_id = player_current_dominion_id.get(player.getUniqueId());
|
||||
DominionDTO dominion = null;
|
||||
if (dominion_id != null) {
|
||||
dominion = id_dominions.get(dominion_id);
|
||||
Integer last_in_dom_id = player_current_dominion_id.get(player.getUniqueId());
|
||||
DominionDTO last_dominion = null;
|
||||
if (last_in_dom_id != null) {
|
||||
last_dominion = id_dominions.get(last_in_dom_id);
|
||||
}
|
||||
if (dominion != null) {
|
||||
if (!isInDominion(dominion, player)) {
|
||||
if (dominion.isTopDom()) {
|
||||
// Dominion.notification.info(player, "您已离开领地:%s", dominion.getName());
|
||||
player.sendMessage(Component.text(dominion.getLeaveMessage()));
|
||||
dominion = null;
|
||||
} else {
|
||||
// Dominion.notification.info(player, "您已离开子领地:%s", dominion.getName());
|
||||
player.sendMessage(Component.text(dominion.getLeaveMessage()));
|
||||
dominion = id_dominions.get(dominion.getParentDomId());
|
||||
}
|
||||
update_player_current_dominion(player, dominion);
|
||||
} else {
|
||||
// 如果在领地内则检查是否在子领地内
|
||||
List<Integer> children = dominion_children.get(dominion.getId());
|
||||
for (Integer child_id : children) {
|
||||
DominionDTO child = id_dominions.get(child_id);
|
||||
if (isInDominion(child, player)) {
|
||||
dominion = child;
|
||||
// Dominion.notification.info(player, "您正在进入子领地:%s", dominion.getName());
|
||||
player.sendMessage(Component.text(dominion.getJoinMessage()));
|
||||
update_player_current_dominion(player, dominion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_in_dom_id != null && dominion_children.get(last_in_dom_id).isEmpty() && isInDominion(last_dominion, player)) {
|
||||
// 如果玩家仍在领地内,且领地没有子领地,则直接返回
|
||||
return last_dominion;
|
||||
}
|
||||
if (dominion == null) {
|
||||
List<DominionDTO> in_dominions = getDominionsParentAndChildren(player.getLocation());
|
||||
if (in_dominions.size() != 0) {
|
||||
dominion = in_dominions.get(0);
|
||||
// Dominion.notification.info(player, "您正在进入领地:%s", dominion.getName());
|
||||
player.sendMessage(Component.text(dominion.getJoinMessage()));
|
||||
}
|
||||
update_player_current_dominion(player, dominion);
|
||||
DominionDTO current_dominion = getLocInDominionDTO(world_dominion_tree.get(player.getWorld().getName()), player.getLocation());
|
||||
int last_dom_id = last_dominion == null ? -1 : last_dominion.getId();
|
||||
int current_dom_id = current_dominion == null ? -1 : current_dominion.getId();
|
||||
if (last_dom_id == current_dom_id) {
|
||||
return last_dominion;
|
||||
}
|
||||
if (last_dom_id != -1) {
|
||||
// if (last_dominion.getParentDomId() == -1)
|
||||
// Notification.info(player, "您已离开领地:%s", last_dominion.getName());
|
||||
// else
|
||||
// Notification.info(player, "您已离开子领地:%s", last_dominion.getName());
|
||||
player.sendActionBar(Component.text(last_dominion.getLeaveMessage()));
|
||||
}
|
||||
if (current_dom_id != -1) {
|
||||
// if (current_dominion.getParentDomId() == -1)
|
||||
// Notification.info(player, "您正在进入领地:%s", current_dominion.getName());
|
||||
// else
|
||||
// Notification.info(player, "您正在进入子领地:%s", current_dominion.getName());
|
||||
player.sendActionBar(Component.text(current_dominion.getJoinMessage()));
|
||||
}
|
||||
return dominion;
|
||||
}
|
||||
|
||||
private void update_player_current_dominion(Player player, DominionDTO dominion) {
|
||||
lightOrNot(player, dominion); // 发光检查
|
||||
flyOrNot(player, dominion); // 飞行检查
|
||||
if (dominion == null) {
|
||||
lightOrNot(player, current_dominion); // 发光检查
|
||||
flyOrNot(player, current_dominion); // 飞行检查
|
||||
if (current_dominion == null) {
|
||||
player_current_dominion_id.put(player.getUniqueId(), null);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
player_current_dominion_id.put(player.getUniqueId(), dominion.getId());
|
||||
player_current_dominion_id.put(player.getUniqueId(), current_dominion.getId());
|
||||
// show border
|
||||
if (dominion.getFlagValue(Flag.SHOW_BORDER)) {
|
||||
if (current_dominion.getFlagValue(Flag.SHOW_BORDER)) {
|
||||
ParticleRender.showBoxFace(Dominion.instance, player,
|
||||
dominion.getLocation1(),
|
||||
dominion.getLocation2());
|
||||
current_dominion.getLocation1(),
|
||||
current_dominion.getLocation2());
|
||||
}
|
||||
return current_dominion;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -227,29 +215,24 @@ public class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
private List<DominionDTO> getDominionsParentAndChildren(Location loc) {
|
||||
// todo: 可能需要进一步优化性能,考虑将领地按照mca文件分组,减少遍历次数
|
||||
long start = System.currentTimeMillis();
|
||||
String world = loc.getWorld().getName();
|
||||
List<Integer> dominions_id = world_dominions.get(world);
|
||||
List<DominionDTO> in_dominions = new ArrayList<>();
|
||||
if (dominions_id == null) return in_dominions;
|
||||
for (Integer id : dominions_id) {
|
||||
DominionDTO d = id_dominions.get(id);
|
||||
if (isInDominion(d, loc)) {
|
||||
in_dominions.add(d);
|
||||
}
|
||||
}
|
||||
in_dominions.sort(Comparator.comparingInt(DominionDTO::getId));
|
||||
long end = System.currentTimeMillis();
|
||||
// XLogger.debug("getDominionsParentAndChildren: %d ms", end - start);
|
||||
return in_dominions;
|
||||
public DominionDTO getDominion(Location loc) {
|
||||
List<DominionNode> tree = world_dominion_tree.get(loc.getWorld().getName());
|
||||
if (tree == null) return null;
|
||||
return getLocInDominionDTO(tree, loc);
|
||||
}
|
||||
|
||||
public DominionDTO getDominion(Location loc) {
|
||||
List<DominionDTO> in_dominions = getDominionsParentAndChildren(loc);
|
||||
if (in_dominions.size() == 0) return null;
|
||||
return in_dominions.get(in_dominions.size() - 1);
|
||||
public List<DominionNode> getDominionTreeByPlayer(String player_name) {
|
||||
List<DominionNode> dominionTree = new ArrayList<>();
|
||||
PlayerDTO player = PlayerDTO.select(player_name);
|
||||
if (player == null) return dominionTree;
|
||||
for (List<DominionNode> tree : world_dominion_tree.values()) {
|
||||
for (DominionNode node : tree) {
|
||||
if (node.dominion.getOwner().equals(player.getUuid())) {
|
||||
dominionTree.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dominionTree;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -276,21 +259,6 @@ public class Cache {
|
||||
z >= dominion.getZ1() && z <= dominion.getZ2();
|
||||
}
|
||||
|
||||
private static boolean isInDominion(@Nullable DominionDTO dominion, Location location) {
|
||||
if (dominion == null) return false;
|
||||
if (!Objects.equals(dominion.getWorld(), location.getWorld().getName())) return false;
|
||||
double x = location.getX();
|
||||
double y = location.getY();
|
||||
double z = location.getZ();
|
||||
return x >= dominion.getX1() && x <= dominion.getX2() &&
|
||||
y >= dominion.getY1() && y <= dominion.getY2() &&
|
||||
z >= dominion.getZ1() && z <= dominion.getZ2();
|
||||
}
|
||||
|
||||
public Map<String, List<Integer>> getWorldDominions() {
|
||||
return world_dominions;
|
||||
}
|
||||
|
||||
public DominionDTO getDominion(Integer id) {
|
||||
return id_dominions.get(id);
|
||||
}
|
||||
@ -312,7 +280,7 @@ public class Cache {
|
||||
|
||||
public static Cache instance;
|
||||
private ConcurrentHashMap<Integer, DominionDTO> id_dominions;
|
||||
private ConcurrentHashMap<String, List<Integer>> world_dominions; // 所有领地
|
||||
private ConcurrentHashMap<String, List<DominionNode>> world_dominion_tree;
|
||||
private ConcurrentHashMap<UUID, ConcurrentHashMap<Integer, PlayerPrivilegeDTO>> player_uuid_to_privilege; // 玩家所有的特权
|
||||
private final Map<UUID, Integer> player_current_dominion_id; // 玩家当前所在领地
|
||||
private ConcurrentHashMap<Integer, List<Integer>> dominion_children;
|
||||
|
62
src/main/java/cn/lunadeer/dominion/DominionNode.java
Normal file
62
src/main/java/cn/lunadeer/dominion/DominionNode.java
Normal file
@ -0,0 +1,62 @@
|
||||
package cn.lunadeer.dominion;
|
||||
|
||||
import cn.lunadeer.dominion.dtos.DominionDTO;
|
||||
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;
|
||||
|
||||
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<>();
|
||||
for (DominionDTO dominion : dominions) {
|
||||
if (Objects.equals(dominion.getParentDomId(), rootId)) {
|
||||
DominionNode node = new DominionNode();
|
||||
node.dominion = dominion;
|
||||
node.children = BuildNodeTree(dominion.getId(), dominions);
|
||||
dominionTree.add(node);
|
||||
}
|
||||
}
|
||||
return dominionTree;
|
||||
}
|
||||
|
||||
public static DominionNode getLocInDominionNode(@NotNull List<DominionNode> nodes, @NotNull Location loc) {
|
||||
for (DominionNode node : nodes) {
|
||||
if (isInDominion(node.dominion, loc)) {
|
||||
if (node.children.isEmpty()) {
|
||||
return node;
|
||||
} else {
|
||||
DominionNode childDominion = getLocInDominionNode(node.children, loc);
|
||||
if (childDominion == null) {
|
||||
return node;
|
||||
} else {
|
||||
return childDominion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DominionDTO getLocInDominionDTO(@NotNull List<DominionNode> nodes, @NotNull Location loc) {
|
||||
DominionNode dominionNode = getLocInDominionNode(nodes, loc);
|
||||
return dominionNode == null ? null : dominionNode.dominion;
|
||||
}
|
||||
|
||||
private static boolean isInDominion(@Nullable DominionDTO dominion, Location location) {
|
||||
if (dominion == null) return false;
|
||||
if (!Objects.equals(dominion.getWorld(), location.getWorld().getName())) return false;
|
||||
double x = location.getX();
|
||||
double y = location.getY();
|
||||
double z = location.getZ();
|
||||
return x >= dominion.getX1() && x <= dominion.getX2() &&
|
||||
y >= dominion.getY1() && y <= dominion.getY2() &&
|
||||
z >= dominion.getZ1() && z <= dominion.getZ2();
|
||||
}
|
||||
}
|
@ -334,10 +334,6 @@ public class DominionDTO {
|
||||
return parentDomId;
|
||||
}
|
||||
|
||||
public boolean isTopDom() {
|
||||
return parentDomId == -1;
|
||||
}
|
||||
|
||||
public DominionDTO setParentDomId(Integer parentDomId) {
|
||||
this.parentDomId = parentDomId;
|
||||
return update(this);
|
||||
|
@ -1,17 +1,21 @@
|
||||
package cn.lunadeer.dominion.tuis;
|
||||
|
||||
import cn.lunadeer.dominion.Cache;
|
||||
import cn.lunadeer.dominion.DominionNode;
|
||||
import cn.lunadeer.minecraftpluginutils.stui.ListView;
|
||||
import cn.lunadeer.minecraftpluginutils.stui.ViewStyles;
|
||||
import cn.lunadeer.minecraftpluginutils.stui.components.Button;
|
||||
import cn.lunadeer.minecraftpluginutils.stui.components.Line;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.lunadeer.dominion.commands.Apis.playerOnly;
|
||||
import static cn.lunadeer.dominion.commands.Helper.playerAdminDominions;
|
||||
import static cn.lunadeer.dominion.commands.Helper.playerOwnDominions;
|
||||
import static cn.lunadeer.dominion.tuis.Apis.getPage;
|
||||
|
||||
public class ListDominion {
|
||||
@ -20,20 +24,33 @@ public class ListDominion {
|
||||
if (player == null) return;
|
||||
int page = getPage(args);
|
||||
ListView view = ListView.create(10, "/dominion list");
|
||||
List<String> own_dominions = playerOwnDominions(sender);
|
||||
// 根据id从小到大排序
|
||||
List<String> admin_dominions = playerAdminDominions(sender);
|
||||
|
||||
view.title("我的领地列表");
|
||||
view.navigator(Line.create().append(Button.create("主菜单").setExecuteCommand("/dominion menu").build()).append("我的领地"));
|
||||
for (String dominion : own_dominions) {
|
||||
TextComponent manage = Button.createGreen("管理").setExecuteCommand("/dominion manage " + dominion).build();
|
||||
TextComponent delete = Button.createRed("删除").setExecuteCommand("/dominion delete " + dominion).build();
|
||||
view.add(Line.create().append(dominion).append(manage).append(delete));
|
||||
}
|
||||
view.addLines(BuildTreeLines(Cache.instance.getDominionTreeByPlayer(player.getName()), 0));
|
||||
view.add(Line.create().append(Component.text("-= 以下为你拥有管理员权限的领地 =-", ViewStyles.main_color)));
|
||||
for (String dominion : admin_dominions) {
|
||||
TextComponent manage = Button.createGreen("管理").setExecuteCommand("/dominion manage " + dominion).build();
|
||||
view.add(Line.create().append(dominion).append(manage));
|
||||
}
|
||||
view.showOn(player, page);
|
||||
}
|
||||
|
||||
private static List<Line> BuildTreeLines(List<DominionNode> dominionTree, Integer depth) {
|
||||
List<Line> lines = new ArrayList<>();
|
||||
StringBuilder prefix = new StringBuilder();
|
||||
for (int i = 0; i < depth; i++) {
|
||||
prefix.append(" | ");
|
||||
}
|
||||
for (DominionNode node : dominionTree) {
|
||||
TextComponent manage = Button.createGreen("管理").setExecuteCommand("/dominion manage " + node.dominion.getName()).build();
|
||||
TextComponent delete = Button.createRed("删除").setExecuteCommand("/dominion delete " + node.dominion.getName()).build();
|
||||
Line line = Line.create().append(prefix + node.dominion.getName()).append(manage).append(delete);
|
||||
lines.add(line);
|
||||
lines.addAll(BuildTreeLines(node.children, depth + 1));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user