private static Vector2D?FindClosestPosition(Vector2D position) { var physicsSpace = ServerWorldService.GetPhysicsSpace(); var collisionGroup = CollisionGroup.Default; if (IsValidPosition( // round position position.ToVector2Ushort().ToVector2D())) { // can teleport right there return(position); } // check nearby tiles var tile = ServerWorldService.GetTile(position.ToVector2Ushort()); foreach (var neighborTile in tile.EightNeighborTiles) { if (!neighborTile.IsValidTile) { continue; } var neighborTilePosition = neighborTile.Position.ToVector2D(); if (IsValidPosition(neighborTilePosition)) { return(neighborTilePosition); } } return(null); // Local function for checking if the position is valid. bool IsValidPosition(Vector2D pos) { using var objectsNearby = physicsSpace.TestRectangle( // include some padding, otherwise the check will include border-objects position: pos + (0.01, 0.01), size: (0.98, 0.98), collisionGroup: collisionGroup, sendDebugEvent: false); if (objectsNearby.Count > 0) { return(false); } var posTile = Server.World.GetTile(pos.ToVector2Ushort()); return(ServerCharacterSpawnHelper.IsValidSpawnTile(posTile, checkNeighborTiles: false)); } }
private static Vector2D FindClosestPosition(Vector2D position) { var physicsSpace = ServerWorldService.GetPhysicsSpace(); var collisionGroup = CollisionGroup.GetDefault(); if (IsValidPosition( // round position position.ToVector2Ushort().ToVector2D())) { // can teleport right there return(position); } // check nearby tiles var tile = ServerWorldService.GetTile(position.ToVector2Ushort()); foreach (var neighborTile in tile.EightNeighborTiles) { if (!neighborTile.IsValidTile) { continue; } var neighborTilePosition = neighborTile.Position.ToVector2D(); if (IsValidPosition(neighborTilePosition)) { return(neighborTilePosition); } } throw new Exception("No empty position available nearby."); // Local function for checking if the position is valid. bool IsValidPosition(Vector2D pos) { using (var objectsNearby = physicsSpace.TestRectangle( // include some padding, otherwise the check will include border-objects position: pos + (0.01, 0.01), size: (0.98, 0.98), collisionGroup: collisionGroup, sendDebugEvent: false)) { return(objectsNearby.Count == 0); } } }
public static bool IsPositionValidForCharacterSpawn( Vector2D position, bool isPlayer) { if (!IsValidSpawnPosition(position)) { return(false); } var physicsSpace = ServerWorldService.GetPhysicsSpace(); foreach (var t in physicsSpace.TestCircle(position, SpawnNoPlayerBuiltStructuresRadius, CollisionGroups.Default, sendDebugEvent: false).EnumerateAndDispose()) { if (t.PhysicsBody.AssociatedWorldObject?.ProtoWorldObject is IProtoObjectStructure) { // some structure nearby return(false); } } if (isPlayer) { // check if mobs nearby foreach (var t in physicsSpace.TestCircle(position, SpawnPlayerNoMobsRadius, CollisionGroups.Default, sendDebugEvent: false).EnumerateAndDispose()) { if (t.PhysicsBody.AssociatedWorldObject is ICharacter otherCharacter && otherCharacter.IsNpc) { // mobs nearby return(false); } } } else // a mob { // check if players nearby foreach (var t in physicsSpace.TestCircle(position, SpawnMobNoPlayersRadius, CollisionGroups.Default, sendDebugEvent: false).EnumerateAndDispose()) { if (t.PhysicsBody.AssociatedWorldObject is ICharacter otherCharacter && !otherCharacter.IsNpc) { // players nearby return(false); } } } // check if any physics object nearby using (var objectsNearby = physicsSpace.TestCircle(position, SpawnNoPhysicsObjectsRadius, CollisionGroups.Default, sendDebugEvent: false)) { if (objectsNearby.Count > 0) { // some physical object nearby return(false); } } return(true); }
public static bool IsPositionValidForCharacterSpawn( Vector2D position, bool isPlayer) { var tile = ServerWorldService.GetTile(position.ToVector2Ushort()); if (!IsValidTile(tile) || tile.EightNeighborTiles.Any(t => !IsValidTile(t))) { // cliff/slope or water nearby return(false); } var physicsSpace = ServerWorldService.GetPhysicsSpace(); using (var objectsNearby = physicsSpace.TestCircle( position, SpawnNoPlayerBuiltStructuresRadius, CollisionGroups.Default, sendDebugEvent: false)) { if (objectsNearby.Any( t => t.PhysicsBody.AssociatedWorldObject?.ProtoWorldObject is IProtoObjectStructure)) { // some structure nearby return(false); } } if (isPlayer) { // check if mobs nearby using (var mobsNearby = physicsSpace.TestCircle( position, SpawnPlayerNoMobsRadius, CollisionGroups.Default, sendDebugEvent: false)) { if (mobsNearby.Any( t => t.PhysicsBody.AssociatedWorldObject is ICharacter otherCharacter && otherCharacter.IsNpc)) { // mobs nearby return(false); } } } else { // check if mobs nearby using (var mobsNearby = physicsSpace.TestCircle( position, SpawnMobNoPlayersRadius, CollisionGroups.Default, sendDebugEvent: false)) { if (mobsNearby.Any( t => t.PhysicsBody.AssociatedWorldObject is ICharacter otherCharacter && !otherCharacter.IsNpc)) { // players nearby return(false); } } } // check if any physics object nearby using (var objectsNearby = physicsSpace.TestCircle( position, SpawnNoPhysicsObjectsRadius, CollisionGroups.Default, sendDebugEvent: false)) { if (objectsNearby.Count > 0) { // some physical object nearby return(false); } } return(true); }