mirror of
https://github.com/Anime-Game-Servers/Grasscutter-Quests.git
synced 2024-11-23 12:39:49 +00:00
Fix grid loading and use rtree for getNearbyGroups
This commit is contained in:
parent
a7f14a9cd8
commit
e4c46c704e
@ -87,7 +87,7 @@ public class ConfigContainer {
|
|||||||
public String packets = "./packets/";
|
public String packets = "./packets/";
|
||||||
public String scripts = "resources:Scripts/";
|
public String scripts = "resources:Scripts/";
|
||||||
public String plugins = "./plugins/";
|
public String plugins = "./plugins/";
|
||||||
public String cache = "./cache/";
|
public String cache = "./server/cache/";
|
||||||
|
|
||||||
// UNUSED (potentially added later?)
|
// UNUSED (potentially added later?)
|
||||||
// public String dumps = "./dumps/";
|
// public String dumps = "./dumps/";
|
||||||
|
@ -1,49 +1,36 @@
|
|||||||
package emu.grasscutter.data.server;
|
package emu.grasscutter.data.server;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.scripts.SceneIndexManager;
|
||||||
import emu.grasscutter.utils.GridPosition;
|
import emu.grasscutter.utils.GridPosition;
|
||||||
import emu.grasscutter.utils.Position;
|
import emu.grasscutter.utils.Position;
|
||||||
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
|
||||||
|
import com.github.davidmoten.rtreemulti.RTree;
|
||||||
|
import com.github.davidmoten.rtreemulti.geometry.Geometry;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
|
||||||
public class Grid {
|
public class Grid {
|
||||||
public Map<GridPosition, Set<Integer>> grid;
|
public Map<GridPosition, Set<Integer>> grid;
|
||||||
|
|
||||||
public Int2ObjectMap<Int2ObjectMap<Set<Integer>>> gridOptimized;
|
public transient RTree<Entry<GridPosition, Set<Integer>>, Geometry> gridOptimized = null;
|
||||||
|
|
||||||
private HashSet<Integer> nearbyGroups = new HashSet<>(100);
|
private transient HashSet<Integer> nearbyGroups = new HashSet<>(100);
|
||||||
|
|
||||||
private void Optimize() {
|
private void Optimize() {
|
||||||
if(gridOptimized == null) {
|
if(gridOptimized == null) {
|
||||||
gridOptimized = new Int2ObjectOpenHashMap<>();
|
List<Entry<GridPosition, Set<Integer>>> gridValues = new ArrayList<>();
|
||||||
grid.forEach((k, v) -> {
|
grid.forEach((k, v) -> {
|
||||||
int x = k.getX() & 0xFFFF;
|
gridValues.add(new AbstractMap.SimpleEntry<>(k, v));
|
||||||
int z = k.getZ() & 0xFFFF;
|
|
||||||
if(!gridOptimized.containsKey(x)) {
|
|
||||||
gridOptimized.put(x, new Int2ObjectOpenHashMap<>());
|
|
||||||
gridOptimized.get(x).put(z, v);
|
|
||||||
} else {
|
|
||||||
val zG = gridOptimized.get(x);
|
|
||||||
if(!zG.containsKey(z)) {
|
|
||||||
zG.put(z, v);
|
|
||||||
} else {
|
|
||||||
zG.get(z).addAll(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
gridOptimized = SceneIndexManager.buildIndex(2, gridValues, entry -> entry.getKey().toPoint());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> GetGroup(GridPosition pos) {
|
|
||||||
int x = pos.getX() & 0xFFFF;
|
|
||||||
int z = pos.getZ() & 0xFFFF;
|
|
||||||
if(!gridOptimized.containsKey(x)) return new HashSet<>();
|
|
||||||
val xG = gridOptimized.get(x);
|
|
||||||
if(!xG.containsKey(z)) return new HashSet<>();
|
|
||||||
return xG.get(z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Integer> getNearbyGroups(int vision_level, Position position) {
|
public Set<Integer> getNearbyGroups(int vision_level, Position position) {
|
||||||
@ -56,19 +43,18 @@ public class Grid {
|
|||||||
GridPosition pos = new GridPosition(position, width);
|
GridPosition pos = new GridPosition(position, width);
|
||||||
|
|
||||||
nearbyGroups.clear();
|
nearbyGroups.clear();
|
||||||
//construct a nearby pisition list, add 1 more because a player can be in an edge case, this should not affect much the loading
|
//construct a nearby position list, add 1 more because a player can be in an edge case, this should not affect much the loading
|
||||||
for(int x = 0; x < vision_range_grid + 1; x++) {
|
//for(int x = 0; x < vision_range_grid + 1; x++) {
|
||||||
for(int z = 0; z < vision_range_grid + 1; z++) {
|
// for(int z = 0; z < vision_range_grid + 1; z++) {
|
||||||
nearbyGroups.addAll(GetGroup(pos.addClone( x, z)));
|
// //nearbyGroups.addAll(grid.getOrDefault(pos.addClone( x, z), new HashSet<>()));
|
||||||
nearbyGroups.addAll(GetGroup(pos.addClone(-x, z)));
|
// //nearbyGroups.addAll(grid.getOrDefault(pos.addClone(-x, z), new HashSet<>()));
|
||||||
nearbyGroups.addAll(GetGroup(pos.addClone( x, -z)));
|
// //nearbyGroups.addAll(grid.getOrDefault(pos.addClone( x, -z), new HashSet<>()));
|
||||||
nearbyGroups.addAll(GetGroup(pos.addClone(-x, -z)));
|
// //nearbyGroups.addAll(grid.getOrDefault(pos.addClone(-x, -z), new HashSet<>()));
|
||||||
//nearbyGroups.addAll(grid.getOrDefault(pos.addClone( x, z), new HashSet<>()));
|
// }
|
||||||
//nearbyGroups.addAll(grid.getOrDefault(pos.addClone(-x, z), new HashSet<>()));
|
//}
|
||||||
//nearbyGroups.addAll(grid.getOrDefault(pos.addClone( x, -z), new HashSet<>()));
|
|
||||||
//nearbyGroups.addAll(grid.getOrDefault(pos.addClone(-x, -z), new HashSet<>()));
|
//Optimized version
|
||||||
}
|
SceneIndexManager.queryNeighbors(gridOptimized, pos.toDoubleArray(), vision_range_grid + 1).forEach(e -> nearbyGroups.addAll(e.getValue()));
|
||||||
}
|
|
||||||
|
|
||||||
return nearbyGroups;
|
return nearbyGroups;
|
||||||
}
|
}
|
||||||
|
@ -390,16 +390,16 @@ public class SceneScriptManager {
|
|||||||
|
|
||||||
public List<Grid> getGroupGrids() {
|
public List<Grid> getGroupGrids() {
|
||||||
int sceneId = scene.getId();
|
int sceneId = scene.getId();
|
||||||
if (groupGridsCache.containsKey(sceneId)) {
|
if (groupGridsCache.containsKey(sceneId) && groupGridsCache.get(sceneId) != null) {
|
||||||
Grasscutter.getLogger().debug("Hit cache for scene {}",sceneId);
|
Grasscutter.getLogger().debug("Hit cache for scene {}",sceneId);
|
||||||
return groupGridsCache.get(sceneId);
|
return groupGridsCache.get(sceneId);
|
||||||
} else {
|
} else {
|
||||||
var path = FileUtils.getCachePath("Grids/scene" + sceneId + "_grid.json");
|
var path = FileUtils.getCachePath("scene" + sceneId + "_grid.json");
|
||||||
if (path.toFile().isFile() && !Grasscutter.config.server.game.cacheSceneEntitiesEveryRun) {
|
if (path.toFile().isFile() && !Grasscutter.config.server.game.cacheSceneEntitiesEveryRun) {
|
||||||
try {
|
try {
|
||||||
var groupGrids = JsonUtils.loadToList(path, Grid.class);
|
var groupGrids = JsonUtils.loadToList(path, Grid.class);
|
||||||
groupGridsCache.put(sceneId, groupGrids);
|
groupGridsCache.put(sceneId, groupGrids);
|
||||||
return groupGrids;
|
if(groupGrids != null) return groupGrids;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public final class FileUtils {
|
|||||||
private static final Path DATA_USER_PATH = Path.of(Grasscutter.config.folderStructure.data);
|
private static final Path DATA_USER_PATH = Path.of(Grasscutter.config.folderStructure.data);
|
||||||
private static final Path PACKETS_PATH = Path.of(Grasscutter.config.folderStructure.packets);
|
private static final Path PACKETS_PATH = Path.of(Grasscutter.config.folderStructure.packets);
|
||||||
private static final Path PLUGINS_PATH = Path.of(Grasscutter.config.folderStructure.plugins);
|
private static final Path PLUGINS_PATH = Path.of(Grasscutter.config.folderStructure.plugins);
|
||||||
private static final Path CACHE_PATH = Path.of(Grasscutter.config.folderStructure.cache);
|
private static final Path CACHE_PATH;
|
||||||
private static final Path RESOURCES_PATH;
|
private static final Path RESOURCES_PATH;
|
||||||
private static final Path SCRIPTS_PATH;
|
private static final Path SCRIPTS_PATH;
|
||||||
static {
|
static {
|
||||||
@ -87,6 +87,8 @@ public final class FileUtils {
|
|||||||
SCRIPTS_PATH = (scripts.startsWith("resources:"))
|
SCRIPTS_PATH = (scripts.startsWith("resources:"))
|
||||||
? RESOURCES_PATH.resolve(scripts.substring("resources:".length()))
|
? RESOURCES_PATH.resolve(scripts.substring("resources:".length()))
|
||||||
: Path.of(scripts);
|
: Path.of(scripts);
|
||||||
|
|
||||||
|
CACHE_PATH = RESOURCES_PATH.resolve(Grasscutter.config.folderStructure.cache);
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String[] TSJ_JSON_TSV = {"tsj", "json", "tsv"};
|
private static final String[] TSJ_JSON_TSV = {"tsj", "json", "tsv"};
|
||||||
|
@ -4,6 +4,8 @@ import java.io.IOException;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.github.davidmoten.rtreemulti.geometry.Point;
|
||||||
|
|
||||||
import dev.morphia.annotations.Entity;
|
import dev.morphia.annotations.Entity;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -90,10 +92,18 @@ public class GridPosition implements Serializable {
|
|||||||
return new int[]{ x, z, width };
|
return new int[]{ x, z, width };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double[] toDoubleArray() {
|
||||||
|
return new double[]{ x, z };
|
||||||
|
}
|
||||||
|
|
||||||
public int[] toXZIntArray() {
|
public int[] toXZIntArray() {
|
||||||
return new int[]{ x, z };
|
return new int[]{ x, z };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Point toPoint() {
|
||||||
|
return Point.create(x,z);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user