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 scripts = "resources:Scripts/";
|
||||
public String plugins = "./plugins/";
|
||||
public String cache = "./cache/";
|
||||
public String cache = "./server/cache/";
|
||||
|
||||
// UNUSED (potentially added later?)
|
||||
// public String dumps = "./dumps/";
|
||||
|
@ -1,49 +1,36 @@
|
||||
package emu.grasscutter.data.server;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.scripts.SceneIndexManager;
|
||||
import emu.grasscutter.utils.GridPosition;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import com.github.davidmoten.rtreemulti.RTree;
|
||||
import com.github.davidmoten.rtreemulti.geometry.Geometry;
|
||||
import lombok.val;
|
||||
|
||||
public class 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() {
|
||||
if(gridOptimized == null) {
|
||||
gridOptimized = new Int2ObjectOpenHashMap<>();
|
||||
List<Entry<GridPosition, Set<Integer>>> gridValues = new ArrayList<>();
|
||||
grid.forEach((k, v) -> {
|
||||
int x = k.getX() & 0xFFFF;
|
||||
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);
|
||||
}
|
||||
}
|
||||
gridValues.add(new AbstractMap.SimpleEntry<>(k, 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) {
|
||||
@ -56,19 +43,18 @@ public class Grid {
|
||||
GridPosition pos = new GridPosition(position, width);
|
||||
|
||||
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
|
||||
for(int x = 0; x < vision_range_grid + 1; x++) {
|
||||
for(int z = 0; z < vision_range_grid + 1; z++) {
|
||||
nearbyGroups.addAll(GetGroup(pos.addClone( x, z)));
|
||||
nearbyGroups.addAll(GetGroup(pos.addClone(-x, z)));
|
||||
nearbyGroups.addAll(GetGroup(pos.addClone( x, -z)));
|
||||
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<>()));
|
||||
}
|
||||
}
|
||||
//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 z = 0; z < vision_range_grid + 1; 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<>()));
|
||||
// }
|
||||
//}
|
||||
|
||||
//Optimized version
|
||||
SceneIndexManager.queryNeighbors(gridOptimized, pos.toDoubleArray(), vision_range_grid + 1).forEach(e -> nearbyGroups.addAll(e.getValue()));
|
||||
|
||||
return nearbyGroups;
|
||||
}
|
||||
|
@ -390,16 +390,16 @@ public class SceneScriptManager {
|
||||
|
||||
public List<Grid> getGroupGrids() {
|
||||
int sceneId = scene.getId();
|
||||
if (groupGridsCache.containsKey(sceneId)) {
|
||||
if (groupGridsCache.containsKey(sceneId) && groupGridsCache.get(sceneId) != null) {
|
||||
Grasscutter.getLogger().debug("Hit cache for scene {}",sceneId);
|
||||
return groupGridsCache.get(sceneId);
|
||||
} 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) {
|
||||
try {
|
||||
var groupGrids = JsonUtils.loadToList(path, Grid.class);
|
||||
groupGridsCache.put(sceneId, groupGrids);
|
||||
return groupGrids;
|
||||
if(groupGrids != null) return groupGrids;
|
||||
} catch (IOException e) {
|
||||
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 PACKETS_PATH = Path.of(Grasscutter.config.folderStructure.packets);
|
||||
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 SCRIPTS_PATH;
|
||||
static {
|
||||
@ -87,6 +87,8 @@ public final class FileUtils {
|
||||
SCRIPTS_PATH = (scripts.startsWith("resources:"))
|
||||
? RESOURCES_PATH.resolve(scripts.substring("resources:".length()))
|
||||
: Path.of(scripts);
|
||||
|
||||
CACHE_PATH = RESOURCES_PATH.resolve(Grasscutter.config.folderStructure.cache);
|
||||
};
|
||||
|
||||
private static final String[] TSJ_JSON_TSV = {"tsj", "json", "tsv"};
|
||||
|
@ -4,6 +4,8 @@ import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.davidmoten.rtreemulti.geometry.Point;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -90,10 +92,18 @@ public class GridPosition implements Serializable {
|
||||
return new int[]{ x, z, width };
|
||||
}
|
||||
|
||||
public double[] toDoubleArray() {
|
||||
return new double[]{ x, z };
|
||||
}
|
||||
|
||||
public int[] toXZIntArray() {
|
||||
return new int[]{ x, z };
|
||||
}
|
||||
|
||||
public Point toPoint() {
|
||||
return Point.create(x,z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user