Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2974,6 +2974,7 @@ class ZoningOperations(
physSpawnPoint: Option[SpawnPoint]
): Unit = {
log.info(s"${player.Name} will load in zone $zoneId at position $pos in $respawnTime")
player.resetInteractions()
respawnTimer.cancel()
reviveTimer.cancel()
deadState = DeadState.RespawnTime
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/net/psforever/objects/Player.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects

import net.psforever.objects.avatar.interaction.{TriggerOnPlayerRule, WithEntrance, WithGantry, WithLava, WithWater}
import net.psforever.objects.avatar.interaction.{InteractWithSOI, TriggerOnPlayerRule, WithEntrance, WithGantry, WithLava, WithWater}
import net.psforever.objects.avatar.{Avatar, LoadoutManager, SpecialCarry}
import net.psforever.objects.ballistics.InteractWithRadiationClouds
import net.psforever.objects.ce.{Deployable, InteractWithMines, InteractWithTurrets}
Expand Down Expand Up @@ -39,6 +39,7 @@ class Player(var avatar: Avatar)
with InteriorAwareFromInteraction
with AuraContainer
with MountableEntity {
interaction(new InteractWithSOI())
interaction(environment.interaction.InteractWithEnvironment(Seq(
new WithEntrance(),
new WithWater(avatar.name),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) 2025 PSForever
package net.psforever.objects.avatar.interaction

import net.psforever.objects.Player
import net.psforever.objects.serverobject.structures.Building
import net.psforever.objects.zones.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
import net.psforever.objects.zones.blockmap.SectorPopulation
import net.psforever.types.Vector3

case object SOIInteraction extends ZoneInteractionType

/**
* na
*/
class InteractWithSOI()
extends ZoneInteraction {

private var skipTargetCounter: Int = 0
private var occupiedSOIs: List[(String, Building)] = List()

def Type: ZoneInteractionType = SOIInteraction

def range: Float = 0f

/**
* na
* @param sector the portion of the block map being tested
* @param target the fixed element in this test
*/
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
if (skipTargetCounter < 4) {
skipTargetCounter += 1
} else {
skipTargetCounter = 0
val buildings = sector.buildingList
if (occupiedSOIs.nonEmpty || buildings.nonEmpty) {
val targetZone = target.Zone
val targetPosition = target.Position
val targetAsPlayer = target.asInstanceOf[Player]
val key = targetAsPlayer.CharId
val (ongoingOccupancy, nowUnoccupied) = occupiedSOIs.partition { case (_, b) =>
targetZone == b.Zone && Vector3.DistanceSquared(targetPosition, b.Position) < math.pow(b.Definition.SOIRadius, 2).toFloat
}
val (_, targetBuildingsOnly) = ongoingOccupancy.unzip
val (_, newOccupancy) = buildings
.filter { b =>
Vector3.DistanceSquared(b.Position, targetPosition) < math.pow(b.Definition.SOIRadius, 2)
}
.partition { b => targetBuildingsOnly.exists(_.Name.equals(b.Name)) }
occupiedSOIs = ongoingOccupancy ++ newOccupancy.map { building => (building.Name, building) }
nowUnoccupied.map(_._2).foreach { _.RemovePlayersFromSOI(key) }
newOccupancy.foreach { _.AddPlayersInSOI(key, targetAsPlayer) }
}
}
}

def resetInteraction(target: InteractsWithZone): Unit = {
skipTargetCounter = 0
val charId = target.asInstanceOf[Player].CharId
occupiedSOIs.map(_._2).foreach { _.RemovePlayersFromSOI(charId) }
occupiedSOIs = List()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import net.psforever.objects.serverobject.structures.participation.{MajorFacilit
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
import net.psforever.util.Config

import scala.collection.mutable

class Building(
private val name: String,
private val building_guid: Int,
Expand All @@ -31,7 +33,7 @@ class Building(
with BlockMapEntity {

private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private var playersInSOI: List[Player] = List.empty
private var playersInSOI: mutable.HashMap[Long, Player] = mutable.HashMap[Long, Player]()
private var forceDomeActive: Boolean = false
private var participationFunc: ParticipationLogic = NoParticipation
super.Zone_=(zone)
Expand Down Expand Up @@ -69,9 +71,10 @@ class Building(
Faction
}

def PlayersInSOI: List[Player] = playersInSOI
def PlayersInSOI: List[Player] = playersInSOI.values.toList

def PlayersInSOI_=(list: List[Player]): List[Player] = {
//todo
if (playersInSOI.isEmpty && list.nonEmpty) {
Amenities.collect {
case box: Painbox =>
Expand All @@ -83,9 +86,29 @@ class Building(
box.Actor ! Painbox.Stop()
}
}
playersInSOI = list
list.foreach { player =>
playersInSOI.put(player.CharId, player)
}
participationFunc.TryUpdate()
PlayersInSOI
}

def AddPlayersInSOI(player: Player): List[Player] = {
AddPlayersInSOI(player.CharId, player)
}
def AddPlayersInSOI(key: Long, player: Player): List[Player] = {
playersInSOI.put(key, player)
participationFunc.TryUpdate()
PlayersInSOI
}

def RemovePlayersFromSOI(player: Player): List[Player] = {
RemovePlayersFromSOI(player.CharId)
}
def RemovePlayersFromSOI(key: Long): List[Player] = {
playersInSOI.remove(key)
participationFunc.TryUpdate()
playersInSOI
PlayersInSOI
}

// Get all lattice neighbours
Expand Down
10 changes: 5 additions & 5 deletions src/main/scala/net/psforever/objects/zones/Zone.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
var actor: typed.ActorRef[ZoneActor.Command] = Default.typed.Actor

/** Actor that handles SOI related functionality, for example if a player is in an SOI */
private var soi = Default.Actor
//private var soi = Default.Actor

/** The basic support structure for the globally unique number system used by this `Zone`. */
private var guid: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(max = 65536))
Expand Down Expand Up @@ -520,11 +520,11 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
}

def StartPlayerManagementSystems(): Unit = {
soi ! SOI.Start()
//soi ! SOI.Start()
}

def StopPlayerManagementSystems(): Unit = {
soi ! SOI.Stop()
//soi ! SOI.Stop()
}

def Activity: ActorRef = projector
Expand Down Expand Up @@ -1536,7 +1536,7 @@ object Zone {
Props(classOf[ZoneHotSpotDisplay], zone, zone.hotspots, 15 seconds, zone.hotspotHistory, 60 seconds),
s"$id-hotspots"
)
zone.soi = context.actorOf(Props(classOf[SphereOfInfluenceActor], zone), s"$id-soi")
//zone.soi = context.actorOf(Props(classOf[SphereOfInfluenceActor], zone), s"$id-soi")

zone.avatarEvents = context.actorOf(Props(classOf[AvatarService], zone), s"$id-avatar-events")
zone.localEvents = context.actorOf(Props(classOf[LocalService], zone), s"$id-local-events")
Expand Down Expand Up @@ -1647,7 +1647,7 @@ object Zone {
obj.Actor ! Service.Startup()
}
//allocate soi information
zone.soi ! SOI.Build()
//zone.soi ! SOI.Build()
}

private def MakeLattice(zone: Zone): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class ZonePopulationActor(zone: Zone, playerMap: TrieMap[Int, Option[Player]], c
case Zone.Corpse.Remove(player) =>
if (CorpseRemove(player, corpseList)) {
PlayerLeave(player)
player.allowInteraction = false
zone.actor ! ZoneActor.RemoveFromBlockMap(player)
}

Expand Down
Loading