Skip to content
Snippets Groups Projects
Commit 67ac0d70 authored by Akka's avatar Akka Committed by Melledy
Browse files

add region entity

parent 1c6c5813
Branches
Tags
No related merge requests found
package emu.grasscutter.game.entity;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass;
import emu.grasscutter.scripts.data.SceneRegion;
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import lombok.Getter;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Getter
public class EntityRegion extends GameEntity{
private final Position position;
private boolean hasNewEntities;
private final Set<Integer> entities; // Ids of entities inside this region
private final SceneRegion metaRegion;
public EntityRegion(Scene scene, SceneRegion region) {
super(scene);
this.id = getScene().getWorld().getNextEntityId(EntityIdType.REGION);
setGroupId(region.group.id);
setBlockId(region.group.block_id);
setConfigId(region.config_id);
this.position = region.pos.clone();
this.entities = ConcurrentHashMap.newKeySet();
this.metaRegion = region;
}
public void addEntity(GameEntity entity) {
if (this.getEntities().contains(entity.getId())) {
return;
}
this.getEntities().add(entity.getId());
this.hasNewEntities = true;
}
public boolean hasNewEntities() {
return hasNewEntities;
}
public void resetNewEntities() {
hasNewEntities = false;
}
public void removeEntity(GameEntity entity) {
this.getEntities().remove(entity.getId());
}
@Override
public Int2FloatOpenHashMap getFightProperties() {
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public Position getRotation() {
return null;
}
@Override
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
/**
* The Region Entity would not be sent to client.
*/
return null;
}
}
...@@ -5,10 +5,11 @@ public enum EntityIdType { ...@@ -5,10 +5,11 @@ public enum EntityIdType {
MONSTER (0x02), MONSTER (0x02),
NPC (0x03), NPC (0x03),
GADGET (0x04), GADGET (0x04),
WEAPON (0x06), REGION (0x05),
WEAPON (0x06),
TEAM (0x09), TEAM (0x09),
MPLEVEL (0x0b); MPLEVEL (0x0b);
private final int id; private final int id;
private EntityIdType(int id) { private EntityIdType(int id) {
......
...@@ -30,24 +30,25 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ...@@ -30,24 +30,25 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.danilopianini.util.SpatialIndex; import org.danilopianini.util.SpatialIndex;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class Scene { public class Scene {
private final World world; private final World world;
private final SceneData sceneData; private final SceneData sceneData;
private final List<Player> players; private final List<Player> players;
private final Int2ObjectMap<GameEntity> entities; private final Map<Integer, GameEntity> entities;
private final Set<SpawnDataEntry> spawnedEntities; private final Set<SpawnDataEntry> spawnedEntities;
private final Set<SpawnDataEntry> deadSpawnedEntities; private final Set<SpawnDataEntry> deadSpawnedEntities;
private final Set<SceneBlock> loadedBlocks; private final Set<SceneBlock> loadedBlocks;
private boolean dontDestroyWhenEmpty; private boolean dontDestroyWhenEmpty;
private int autoCloseTime; private int autoCloseTime;
private int time; private int time;
private ClimateType climate; private ClimateType climate;
private int weather; private int weather;
private SceneScriptManager scriptManager; private SceneScriptManager scriptManager;
private WorldChallenge challenge; private WorldChallenge challenge;
private List<DungeonSettleListener> dungeonSettleListeners; private List<DungeonSettleListener> dungeonSettleListeners;
...@@ -57,19 +58,19 @@ public class Scene { ...@@ -57,19 +58,19 @@ public class Scene {
public Scene(World world, SceneData sceneData) { public Scene(World world, SceneData sceneData) {
this.world = world; this.world = world;
this.sceneData = sceneData; this.sceneData = sceneData;
this.players = Collections.synchronizedList(new ArrayList<>()); this.players = new CopyOnWriteArrayList<>();
this.entities = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>()); this.entities = new ConcurrentHashMap<>();
this.time = 8 * 60; this.time = 8 * 60;
this.climate = ClimateType.CLIMATE_SUNNY; this.climate = ClimateType.CLIMATE_SUNNY;
this.prevScene = 3; this.prevScene = 3;
this.spawnedEntities = new HashSet<>(); this.spawnedEntities = ConcurrentHashMap.newKeySet();
this.deadSpawnedEntities = new HashSet<>(); this.deadSpawnedEntities = ConcurrentHashMap.newKeySet();
this.loadedBlocks = new HashSet<>(); this.loadedBlocks = ConcurrentHashMap.newKeySet();
this.scriptManager = new SceneScriptManager(this); this.scriptManager = new SceneScriptManager(this);
} }
public int getId() { public int getId() {
return sceneData.getId(); return sceneData.getId();
} }
...@@ -89,15 +90,15 @@ public class Scene { ...@@ -89,15 +90,15 @@ public class Scene {
public List<Player> getPlayers() { public List<Player> getPlayers() {
return players; return players;
} }
public int getPlayerCount() { public int getPlayerCount() {
return this.getPlayers().size(); return this.getPlayers().size();
} }
public Int2ObjectMap<GameEntity> getEntities() { public Map<Integer, GameEntity> getEntities() {
return entities; return entities;
} }
public GameEntity getEntityById(int id) { public GameEntity getEntityById(int id) {
return this.entities.get(id); return this.entities.get(id);
} }
...@@ -629,15 +630,10 @@ public class Scene { ...@@ -629,15 +630,10 @@ public class Scene {
var suiteData = group.getSuiteByIndex(suite); var suiteData = group.getSuiteByIndex(suite);
suiteData.sceneTriggers.forEach(getScriptManager()::registerTrigger); suiteData.sceneTriggers.forEach(getScriptManager()::registerTrigger);
entities.addAll(suiteData.sceneGadgets.stream() entities.addAll(scriptManager.getGadgetsInGroupSuite(group, suiteData));
.map(g -> scriptManager.createGadget(group.id, group.block_id, g)) entities.addAll(scriptManager.getMonstersInGroupSuite(group, suiteData));
.filter(Objects::nonNull)
.toList());
entities.addAll(suiteData.sceneMonsters.stream()
.map(mob -> scriptManager.createMonster(group.id, group.block_id, mob))
.filter(Objects::nonNull)
.toList());
scriptManager.registerRegionInGroupSuite(group, suiteData);
} }
scriptManager.meetEntities(entities); scriptManager.meetEntities(entities);
...@@ -654,19 +650,18 @@ public class Scene { ...@@ -654,19 +650,18 @@ public class Scene {
toRemove.forEach(this::removeEntityDirectly); toRemove.forEach(this::removeEntityDirectly);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE));
} }
for (SceneGroup group : block.groups.values()) { for (SceneGroup group : block.groups.values()) {
if(group.triggers != null){ if(group.triggers != null){
group.triggers.values().forEach(getScriptManager()::deregisterTrigger); group.triggers.values().forEach(getScriptManager()::deregisterTrigger);
} }
if(group.regions != null){ if(group.regions != null){
group.regions.forEach(getScriptManager()::deregisterRegion); group.regions.values().forEach(getScriptManager()::deregisterRegion);
} }
} }
scriptManager.getLoadedGroupSetPerBlock().remove(block.id); scriptManager.getLoadedGroupSetPerBlock().remove(block.id);
Grasscutter.getLogger().info("Scene {} Block {} is unloaded.", this.getId(), block.id); Grasscutter.getLogger().info("Scene {} Block {} is unloaded.", this.getId(), block.id);
} }
// Gadgets // Gadgets
public void onPlayerCreateGadget(EntityClientGadget gadget) { public void onPlayerCreateGadget(EntityClientGadget gadget) {
......
...@@ -6,10 +6,7 @@ import emu.grasscutter.Grasscutter; ...@@ -6,10 +6,7 @@ import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.MonsterData; import emu.grasscutter.data.excels.MonsterData;
import emu.grasscutter.data.excels.WorldLevelData; import emu.grasscutter.data.excels.WorldLevelData;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.EntityNPC;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.net.proto.VisionTypeOuterClass; import emu.grasscutter.net.proto.VisionTypeOuterClass;
import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.constants.EventType;
...@@ -17,17 +14,12 @@ import emu.grasscutter.scripts.data.*; ...@@ -17,17 +14,12 @@ import emu.grasscutter.scripts.data.*;
import emu.grasscutter.scripts.service.ScriptMonsterSpawnService; import emu.grasscutter.scripts.service.ScriptMonsterSpawnService;
import emu.grasscutter.scripts.service.ScriptMonsterTideService; import emu.grasscutter.scripts.service.ScriptMonsterTideService;
import io.netty.util.concurrent.FastThreadLocalThread; import io.netty.util.concurrent.FastThreadLocalThread;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.CoerceJavaToLua; import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import java.util.*; import java.util.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.*;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SceneScriptManager { public class SceneScriptManager {
...@@ -38,15 +30,15 @@ public class SceneScriptManager { ...@@ -38,15 +30,15 @@ public class SceneScriptManager {
/** /**
* current triggers controlled by RefreshGroup * current triggers controlled by RefreshGroup
*/ */
private final Int2ObjectOpenHashMap<Set<SceneTrigger>> currentTriggers; private final Map<Integer, Set<SceneTrigger>> currentTriggers;
private final Int2ObjectOpenHashMap<SceneRegion> regions; private final Map<Integer, EntityRegion> regions; // <EntityId-Region>
private Map<Integer,SceneGroup> sceneGroups; private final Map<Integer,SceneGroup> sceneGroups;
private ScriptMonsterTideService scriptMonsterTideService; private ScriptMonsterTideService scriptMonsterTideService;
private ScriptMonsterSpawnService scriptMonsterSpawnService; private ScriptMonsterSpawnService scriptMonsterSpawnService;
/** /**
* blockid - loaded groupSet * blockid - loaded groupSet
*/ */
private Int2ObjectMap<Set<SceneGroup>> loadedGroupSetPerBlock; private final Map<Integer, Set<SceneGroup>> loadedGroupSetPerBlock;
public static final ExecutorService eventExecutor; public static final ExecutorService eventExecutor;
static { static {
eventExecutor = new ThreadPoolExecutor(4, 4, eventExecutor = new ThreadPoolExecutor(4, 4,
...@@ -55,23 +47,23 @@ public class SceneScriptManager { ...@@ -55,23 +47,23 @@ public class SceneScriptManager {
} }
public SceneScriptManager(Scene scene) { public SceneScriptManager(Scene scene) {
this.scene = scene; this.scene = scene;
this.currentTriggers = new Int2ObjectOpenHashMap<>(); this.currentTriggers = new ConcurrentHashMap<>();
this.regions = new Int2ObjectOpenHashMap<>(); this.regions = new ConcurrentHashMap<>();
this.variables = new HashMap<>(); this.variables = new ConcurrentHashMap<>();
this.sceneGroups = new HashMap<>(); this.sceneGroups = new ConcurrentHashMap<>();
this.scriptMonsterSpawnService = new ScriptMonsterSpawnService(this); this.scriptMonsterSpawnService = new ScriptMonsterSpawnService(this);
this.loadedGroupSetPerBlock = new Int2ObjectOpenHashMap<>(); this.loadedGroupSetPerBlock = new ConcurrentHashMap<>();
// TEMPORARY // TEMPORARY
if (this.getScene().getId() < 10 && !Grasscutter.getConfig().server.game.enableScriptInBigWorld) { if (this.getScene().getId() < 10 && !Grasscutter.getConfig().server.game.enableScriptInBigWorld) {
return; return;
} }
// Create // Create
this.init(); this.init();
} }
public Scene getScene() { public Scene getScene() {
return scene; return scene;
} }
...@@ -123,19 +115,25 @@ public class SceneScriptManager { ...@@ -123,19 +115,25 @@ public class SceneScriptManager {
spawnMonstersInGroup(group, suite); spawnMonstersInGroup(group, suite);
spawnGadgetsInGroup(group, suite); spawnGadgetsInGroup(group, suite);
} }
public SceneRegion getRegionById(int id) { public EntityRegion getRegionById(int id) {
return regions.get(id); return regions.get(id);
} }
public void registerRegion(SceneRegion region) { public void registerRegion(EntityRegion region) {
regions.put(region.config_id, region); regions.put(region.getId(), region);
} }
public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite){
public void deregisterRegion(SceneRegion region) { suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region))
regions.remove(region.config_id); .forEach(this::registerRegion);
}
public synchronized void deregisterRegion(SceneRegion region) {
var instance = regions.values().stream()
.filter(r -> r.getConfigId() == region.config_id)
.findFirst();
instance.ifPresent(entityRegion -> regions.remove(entityRegion.getId()));
} }
public Int2ObjectMap<Set<SceneGroup>> getLoadedGroupSetPerBlock() { public Map<Integer, Set<SceneGroup>> getLoadedGroupSetPerBlock() {
return loadedGroupSetPerBlock; return loadedGroupSetPerBlock;
} }
...@@ -182,53 +180,61 @@ public class SceneScriptManager { ...@@ -182,53 +180,61 @@ public class SceneScriptManager {
} }
this.sceneGroups.put(group.id, group); this.sceneGroups.put(group.id, group);
if(group.regions != null){
group.regions.forEach(this::registerRegion);
}
} }
public void checkRegions() { public void checkRegions() {
if (this.regions.size() == 0) { if (this.regions.size() == 0) {
return; return;
} }
for (SceneRegion region : this.regions.values()) { for (var region : this.regions.values()) {
getScene().getEntities().values() getScene().getEntities().values()
.stream() .stream()
.filter(e -> e.getEntityType() <= 2 && region.contains(e.getPosition())) .filter(e -> e.getEntityType() <= 2 && region.getMetaRegion().contains(e.getPosition()))
.forEach(region::addEntity); .forEach(region::addEntity);
if (region.hasNewEntities()) { if (region.hasNewEntities()) {
// This is not how it works, source_eid should be region entity id, but we dont have an entity for regions yet callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.getConfigId()).setSourceEntityId(region.getId()));
callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.config_id).setSourceEntityId(region.config_id));
region.resetNewEntities(); region.resetNewEntities();
} }
} }
} }
public List<EntityGadget> getGadgetsInGroupSuite(SceneGroup group, SceneSuite suite){
return suite.sceneGadgets.stream()
.map(g -> createGadget(group.id, group.block_id, g))
.filter(Objects::nonNull)
.toList();
}
public List<EntityMonster> getMonstersInGroupSuite(SceneGroup group, SceneSuite suite){
return suite.sceneMonsters.stream()
.map(mob -> createMonster(group.id, group.block_id, mob))
.filter(Objects::nonNull)
.toList();
}
public void addGroupSuite(SceneGroup group, SceneSuite suite){ public void addGroupSuite(SceneGroup group, SceneSuite suite){
spawnMonstersInGroup(group, suite); // we added trigger first
spawnGadgetsInGroup(group, suite); registerTrigger(suite.sceneTriggers);
registerTrigger(suite.sceneTriggers);
var toCreate = new ArrayList<GameEntity>();
toCreate.addAll(getGadgetsInGroupSuite(group, suite));
toCreate.addAll(getMonstersInGroupSuite(group, suite));
addEntities(toCreate);
registerRegionInGroupSuite(group, suite);
} }
public void removeGroupSuite(SceneGroup group, SceneSuite suite){ public void removeGroupSuite(SceneGroup group, SceneSuite suite){
deregisterTrigger(suite.sceneTriggers);
removeMonstersInGroup(group, suite); removeMonstersInGroup(group, suite);
removeGadgetsInGroup(group, suite); removeGadgetsInGroup(group, suite);
deregisterTrigger(suite.sceneTriggers);
} suite.sceneRegions.forEach(this::deregisterRegion);
public void spawnGadgetsInGroup(SceneGroup group, int suiteIndex) {
spawnGadgetsInGroup(group, group.getSuiteByIndex(suiteIndex));
}
public void spawnGadgetsInGroup(SceneGroup group) {
spawnGadgetsInGroup(group, null);
} }
public void spawnGadgetsInGroup(SceneGroup group, SceneSuite suite) { public void spawnGadgetsInGroup(SceneGroup group, SceneSuite suite) {
var gadgets = group.gadgets.values(); var gadgets = group.gadgets.values();
if (suite != null) { if (suite != null) {
gadgets = suite.sceneGadgets; gadgets = suite.sceneGadgets;
} }
...@@ -240,13 +246,6 @@ public class SceneScriptManager { ...@@ -240,13 +246,6 @@ public class SceneScriptManager {
this.addEntities(toCreate); this.addEntities(toCreate);
} }
public void spawnMonstersInGroup(SceneGroup group, int suiteIndex) {
var suite = group.getSuiteByIndex(suiteIndex);
if(suite == null){
return;
}
spawnMonstersInGroup(group, suite);
}
public void spawnMonstersInGroup(SceneGroup group, SceneSuite suite) { public void spawnMonstersInGroup(SceneGroup group, SceneSuite suite) {
if(suite == null || suite.sceneMonsters.size() <= 0){ if(suite == null || suite.sceneMonsters.size() <= 0){
return; return;
...@@ -254,11 +253,6 @@ public class SceneScriptManager { ...@@ -254,11 +253,6 @@ public class SceneScriptManager {
this.addEntities(suite.sceneMonsters.stream() this.addEntities(suite.sceneMonsters.stream()
.map(mob -> createMonster(group.id, group.block_id, mob)).toList()); .map(mob -> createMonster(group.id, group.block_id, mob)).toList());
} }
public void spawnMonstersInGroup(SceneGroup group) {
this.addEntities(group.monsters.values().stream()
.map(mob -> createMonster(group.id, group.block_id, mob)).toList());
}
public void startMonsterTideInGroup(SceneGroup group, Integer[] ordersConfigId, int tideCount, int sceneLimit) { public void startMonsterTideInGroup(SceneGroup group, Integer[] ordersConfigId, int tideCount, int sceneLimit) {
this.scriptMonsterTideService = this.scriptMonsterTideService =
......
...@@ -309,22 +309,22 @@ public class ScriptLib { ...@@ -309,22 +309,22 @@ public class ScriptLib {
return 0; return 0;
} }
public int GetRegionEntityCount(LuaTable table) { public int GetRegionEntityCount(LuaTable table) {
logger.debug("[LUA] Call GetRegionEntityCount with {}", logger.debug("[LUA] Call GetRegionEntityCount with {}",
printTable(table)); printTable(table));
int regionId = table.get("region_eid").toint(); int regionId = table.get("region_eid").toint();
int entityType = table.get("entity_type").toint(); int entityType = table.get("entity_type").toint();
SceneRegion region = this.getSceneScriptManager().getRegionById(regionId); var region = this.getSceneScriptManager().getRegionById(regionId);
if (region == null) { if (region == null) {
return 0; return 0;
} }
return (int) region.getEntities().intStream().filter(e -> e >> 24 == entityType).count(); return (int) region.getEntities().stream().filter(e -> e >> 24 == entityType).count();
} }
public void PrintContextLog(String msg) { public void PrintContextLog(String msg) {
logger.info("[LUA] " + msg); logger.info("[LUA] " + msg);
} }
......
...@@ -34,10 +34,10 @@ public class SceneGroup { ...@@ -34,10 +34,10 @@ public class SceneGroup {
public Map<Integer, SceneGadget> gadgets; // <ConfigId, Gadgets> public Map<Integer, SceneGadget> gadgets; // <ConfigId, Gadgets>
public Map<String, SceneTrigger> triggers; public Map<String, SceneTrigger> triggers;
public Map<Integer, SceneNPC> npc; // <NpcId, NPC> public Map<Integer, SceneNPC> npc; // <NpcId, NPC>
public List<SceneRegion> regions; public Map<Integer, SceneRegion> regions;
public List<SceneSuite> suites; public List<SceneSuite> suites;
public List<SceneVar> variables; public List<SceneVar> variables;
public SceneBusiness business; public SceneBusiness business;
public SceneGarbage garbages; public SceneGarbage garbages;
public SceneInitConfig init_config; public SceneInitConfig init_config;
...@@ -115,9 +115,12 @@ public class SceneGroup { ...@@ -115,9 +115,12 @@ public class SceneGroup {
triggers.values().forEach(t -> t.currentGroup = this); triggers.values().forEach(t -> t.currentGroup = this);
suites = ScriptLoader.getSerializer().toList(SceneSuite.class, bindings.get("suites")); suites = ScriptLoader.getSerializer().toList(SceneSuite.class, bindings.get("suites"));
regions = ScriptLoader.getSerializer().toList(SceneRegion.class, bindings.get("regions")); regions = ScriptLoader.getSerializer().toList(SceneRegion.class, bindings.get("regions")).stream()
.collect(Collectors.toMap(x -> x.config_id, y -> y));
regions.values().forEach(m -> m.group = this);
init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, bindings.get("init_config")); init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, bindings.get("init_config"));
// Garbages TODO fix properly later // Garbages TODO fix properly later
Object garbagesValue = bindings.get("garbages"); Object garbagesValue = bindings.get("garbages");
if (garbagesValue != null && garbagesValue instanceof LuaValue garbagesTable) { if (garbagesValue != null && garbagesValue instanceof LuaValue garbagesTable) {
...@@ -157,12 +160,19 @@ public class SceneGroup { ...@@ -157,12 +160,19 @@ public class SceneGroup {
.map(triggers::get) .map(triggers::get)
.toList() .toList()
); );
suite.sceneRegions = new ArrayList<>(
suite.regions.stream()
.filter(regions::containsKey)
.map(regions::get)
.toList()
);
} }
} catch (ScriptException e) { } catch (ScriptException e) {
Grasscutter.getLogger().error("Error loading group " + id + " in scene " + sceneId, e); Grasscutter.getLogger().error("Error loading group " + id + " in scene " + sceneId, e);
} }
Grasscutter.getLogger().info("group {} in scene {} is loaded successfully.", id, sceneId); Grasscutter.getLogger().info("group {} in scene {} is loaded successfully.", id, sceneId);
return this; return this;
} }
......
package emu.grasscutter.scripts.data; package emu.grasscutter.scripts.data;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.scripts.constants.ScriptRegionShape; import emu.grasscutter.scripts.constants.ScriptRegionShape;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import lombok.Data;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
@ToString
@Setter @Setter
public class SceneRegion { public class SceneRegion {
public int config_id; public int config_id;
public int shape; public int shape;
public Position pos; public Position pos;
// for CUBIC
public Position size; public Position size;
// for SPHERE
private boolean hasNewEntities; public int radius;
private final IntSet entities; // Ids of entities inside this region
public SceneRegion() {
this.entities = new IntOpenHashSet();
}
public IntSet getEntities() {
return entities;
}
public void addEntity(GameEntity entity) { public transient SceneGroup group;
if (this.getEntities().contains(entity.getId())) { public boolean contains(Position position) {
return;
}
this.getEntities().add(entity.getId());
this.hasNewEntities = true;
}
public void removeEntity(GameEntity entity) {
this.getEntities().remove(entity.getId());
}
public boolean contains(Position p) {
switch (shape) { switch (shape) {
case ScriptRegionShape.CUBIC: case ScriptRegionShape.CUBIC:
return (Math.abs(pos.getX() - p.getX()) <= size.getX()) && return (Math.abs(pos.getX() - position.getX()) <= size.getX()) &&
(Math.abs(pos.getZ() - p.getZ()) <= size.getZ()); (Math.abs(pos.getY() - position.getY()) <= size.getY()) &&
(Math.abs(pos.getZ() - position.getZ()) <= size.getZ());
case ScriptRegionShape.SPHERE: case ScriptRegionShape.SPHERE:
return false; var x = Math.pow(pos.getX() - position.getX(), 2);
var y = Math.pow(pos.getY() - position.getY(), 2);
var z = Math.pow(pos.getZ() - position.getZ(), 2);
return x + y + z <= (radius ^ 2);
} }
return false; return false;
} }
public boolean hasNewEntities() {
return hasNewEntities;
}
public void resetNewEntities() {
hasNewEntities = false;
}
} }
...@@ -11,9 +11,12 @@ public class SceneSuite { ...@@ -11,9 +11,12 @@ public class SceneSuite {
public List<Integer> monsters; public List<Integer> monsters;
public List<Integer> gadgets; public List<Integer> gadgets;
public List<String> triggers; public List<String> triggers;
public int rand_weight; public List<Integer> regions;
public int rand_weight;
public transient List<SceneMonster> sceneMonsters; public transient List<SceneMonster> sceneMonsters;
public transient List<SceneGadget> sceneGadgets; public transient List<SceneGadget> sceneGadgets;
public transient List<SceneTrigger> sceneTriggers; public transient List<SceneTrigger> sceneTriggers;
public transient List<SceneRegion> sceneRegions;
} }
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment