Skip to content

Commit 6ebe34a

Browse files
committed
Optimized CPU/memory usage
1 parent 8beb4b6 commit 6ebe34a

18 files changed

Lines changed: 147 additions & 370 deletions

File tree

src/main/java/com/projectswg/holocore/intents/support/npc/ai/AiIntents.kt

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/main/java/com/projectswg/holocore/resources/support/npc/ai/NavigationPoint.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/***********************************************************************************
2-
* Copyright (c) 2024 /// Project SWG /// www.projectswg.com *
2+
* Copyright (c) 2025 /// Project SWG /// www.projectswg.com *
33
* *
4-
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
4+
* ProjectSWG is an emulation project for Star Wars Galaxies founded on *
55
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
6-
* Our goal is to create an emulator which will provide a server for players to *
7-
* continue playing a game similar to the one they used to play. We are basing *
8-
* it on the final publish of the game prior to end-game events. *
6+
* Our goal is to create one or more emulators which will provide servers for *
7+
* players to continue playing a game similar to the one they used to play. *
98
* *
109
* This file is part of Holocore. *
1110
* *
@@ -37,7 +36,7 @@ import java.util.*
3736
import kotlin.math.atan2
3837
import kotlin.math.floor
3938

40-
class NavigationPoint private constructor(val parent: SWGObject?, val location: Location, val speed: Double) {
39+
class NavigationPoint(val parent: SWGObject?, val location: Location, val speed: Double) {
4140
private val hash = Objects.hash(parent, location)
4241

4342
fun move(obj: SWGObject) {

src/main/java/com/projectswg/holocore/resources/support/npc/ai/NpcCombatMode.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import com.projectswg.common.data.encodables.tangible.Posture
3030
import com.projectswg.common.data.location.Location
3131
import com.projectswg.common.network.packets.swg.zone.object_controller.ShowFlyText
3232
import com.projectswg.holocore.intents.support.global.command.QueueCommandIntent
33-
import com.projectswg.holocore.intents.support.npc.ai.StopNpcMovementIntent
3433
import com.projectswg.holocore.intents.support.objects.MoveObjectIntent
3534
import com.projectswg.holocore.resources.support.color.SWGColor
3635
import com.projectswg.holocore.resources.support.data.server_info.loader.ServerData
@@ -80,7 +79,7 @@ class NpcCombatMode(obj: AIObject, coroutineScope: CoroutineScope) : NpcMode(obj
8079

8180
override suspend fun onModeStart() {
8281
showExclamationMarkAboveNpc()
83-
StopNpcMovementIntent(ai).broadcast()
82+
ai.stopMovement()
8483
returnLocation.set(NavigationPoint.at(ai.parent, ai.location, npcRunSpeed))
8584
startCombatLocation.set(ai.worldLocation)
8685
}

src/main/java/com/projectswg/holocore/resources/support/npc/ai/NpcLoiterMode.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ class NpcLoiterMode(obj: AIObject, private val radius: Double) : NpcMode(obj) {
4444

4545
override suspend fun onModeStart() {
4646
val currentLocation = ai.location
47-
if (mainLocation == null) mainLocation = currentLocation
48-
if (mainLocation!!.distanceTo(currentLocation) >= 1) runTo(mainLocation)
47+
var startingLocation = mainLocation
48+
if (startingLocation == null) startingLocation = currentLocation
49+
if (startingLocation.distanceTo(currentLocation) >= 1) runTo(startingLocation)
50+
mainLocation = startingLocation
4951
}
5052

5153
override suspend fun onModeLoop() {

src/main/java/com/projectswg/holocore/resources/support/npc/ai/NpcPatrolMode.kt

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
***********************************************************************************/
2626
package com.projectswg.holocore.resources.support.npc.ai
2727

28-
import com.projectswg.holocore.intents.support.npc.ai.CompileNpcMovementIntent
28+
import com.projectswg.common.data.location.Location
2929
import com.projectswg.holocore.resources.support.data.server_info.loader.npc.NpcPatrolRouteLoader.PatrolType
3030
import com.projectswg.holocore.resources.support.data.server_info.loader.npc.NpcStaticSpawnLoader
3131
import com.projectswg.holocore.resources.support.npc.spawn.Spawner.ResolvedPatrolWaypoint
@@ -51,23 +51,36 @@ class NpcPatrolMode(obj: AIObject, waypoints: List<ResolvedPatrolWaypoint>) : Np
5151
waypointBuilder.add(waypointBuilder[0])
5252
}
5353

54-
this.waypoints = ArrayList(waypointBuilder.size)
55-
for (waypoint in waypointBuilder) {
56-
val point = NavigationPoint.at(waypoint.parent, waypoint.location, walkSpeed)
57-
this.waypoints.add(point)
58-
this.waypoints.addAll(NavigationPoint.nop(point, waypoint.delay.toInt()))
54+
this.waypoints = ArrayList<NavigationPoint>(128)
55+
for (i in 1 until waypointBuilder.size) {
56+
val source = waypointBuilder[i - 1]
57+
val destination = waypointBuilder[i]
58+
this.waypoints.addAll(NavigationPoint.from(source.parent, source.location, destination.parent, destination.location, walkSpeed))
59+
if (destination.delay > 0)
60+
this.waypoints.addAll(NavigationPoint.nop(this.waypoints[this.waypoints.size - 1], destination.delay.toInt() - 1))
5961
}
62+
this.waypoints.addAll(NavigationPoint.from(waypointBuilder[waypointBuilder.size - 1].parent, waypointBuilder[waypointBuilder.size - 1].location, waypointBuilder[0].parent, waypointBuilder[0].location, walkSpeed))
6063
}
6164

6265
override suspend fun onModeStart() {
66+
val route = calculateRouteOffset(calculateInitialRoutePoints())
67+
68+
ai.moveVia(route, loop = true)
69+
}
70+
71+
override suspend fun onModeLoop() {
72+
throw CancellationException() // No loop necessary
73+
}
74+
75+
private fun calculateInitialRoutePoints(): List<NavigationPoint> {
6376
val compiledWaypoints: MutableList<NavigationPoint>
6477
if (waypoints.isNotEmpty()) {
6578
var index = 0
6679
var closestDistance = waypoints[0].distanceTo(ai)
6780
for (i in 1 until waypoints.size) {
6881
if (waypoints[i].isNoOperation)
6982
continue
70-
83+
7184
val distance = waypoints[i].distanceTo(ai)
7285
if (distance < closestDistance) {
7386
closestDistance = distance
@@ -88,46 +101,49 @@ class NpcPatrolMode(obj: AIObject, waypoints: List<ResolvedPatrolWaypoint>) : Np
88101
} else {
89102
compiledWaypoints = waypoints
90103
}
104+
return compiledWaypoints
105+
}
106+
107+
private fun calculateRouteOffset(compiledWaypoints: List<NavigationPoint>): List<NavigationPoint> {
91108
val spawner = spawner ?: throw CancellationException()
92109
val spacing = 3.0
93110
val position = spawner.npcs.indexOf(ai)
111+
var offsetX = 0.0
112+
var offsetZ = 0.0
94113
assert(position != -1)
95114

96115
when (spawner.patrolFormation) {
97-
NpcStaticSpawnLoader.PatrolFormation.NONE -> CompileNpcMovementIntent(ai, compiledWaypoints, NavigationRouteType.LOOP, walkSpeed, null).broadcast()
116+
NpcStaticSpawnLoader.PatrolFormation.NONE -> {}
98117
NpcStaticSpawnLoader.PatrolFormation.COLUMN -> {
99-
val x = if (position % 2 == 0) 0.0 else spacing
100-
val z = -(spacing * ceil((position - 1) / 2.0))
101-
CompileNpcMovementIntent(ai, compiledWaypoints, NavigationRouteType.LOOP, walkSpeed, NavigationOffset(x, z)).broadcast()
118+
offsetX = if (position % 2 == 0) 0.0 else spacing
119+
offsetZ = -(spacing * ceil((position - 1) / 2.0))
102120
}
103121
NpcStaticSpawnLoader.PatrolFormation.WEDGE -> {
104-
val x = spacing * ceil(position / 2.0)
105-
val z = -x
106-
CompileNpcMovementIntent(ai, compiledWaypoints, NavigationRouteType.LOOP, walkSpeed, NavigationOffset(if (position % 2 == 0) -x else x, z)).broadcast()
122+
offsetX = spacing * ceil(position / 2.0) * (if (position % 2 == 0) -1 else 1)
123+
offsetZ = -offsetX
107124
}
108125
NpcStaticSpawnLoader.PatrolFormation.LINE -> {
109-
val x = spacing * ceil(position / 2.0)
110-
CompileNpcMovementIntent(ai, compiledWaypoints, NavigationRouteType.LOOP, walkSpeed, NavigationOffset(if (position % 2 == 0) -x else x, 0.0)).broadcast()
126+
offsetX = spacing * ceil(position / 2.0) * (if (position % 2 == 0) -1 else 1)
111127
}
112128
NpcStaticSpawnLoader.PatrolFormation.BOX -> {
113-
val x = when (position) {
129+
offsetX = when (position) {
114130
0, 1, 2 -> position * 3.0
115131
3 -> 0.0
116132
4 -> 6.0
117133
else -> (position - 5) * 3.0
118134
}
119-
val z = when (position) {
135+
offsetZ = when (position) {
120136
0, 1, 2 -> 0.0 // front of the box
121137
3, 4 -> 3.0 // sides of the box
122138
else -> 6.0 // back of the box
123139
}
124-
CompileNpcMovementIntent(ai, compiledWaypoints, NavigationRouteType.LOOP, walkSpeed, NavigationOffset(x, z)).broadcast()
125140
}
126141
}
127-
}
128-
129-
override suspend fun onModeLoop() {
130-
throw CancellationException() // No loop necessary
142+
143+
val offsetWaypoints = ArrayList<NavigationPoint>(compiledWaypoints.size)
144+
for (wp in compiledWaypoints)
145+
offsetWaypoints.add(NavigationPoint(wp.parent, Location.builder(wp.location).translatePosition(offsetX, 0.0, offsetZ).build(), wp.speed))
146+
return offsetWaypoints
131147
}
132148

133149
}

src/main/java/com/projectswg/holocore/resources/support/npc/ai/NpcTurningMode.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,11 @@ class NpcTurningMode(obj: AIObject) : NpcMode(obj) {
4242

4343
override suspend fun onModeStart() {
4444
val currentLocation = ai.location
45-
if (mainLocation == null)
46-
mainLocation = currentLocation
47-
if (mainParent == null)
48-
mainParent = ai.parent
49-
50-
if (mainLocation!!.distanceTo(currentLocation) >= 1)
51-
runTo(mainLocation)
45+
var startingLocation = mainLocation
46+
if (startingLocation == null) startingLocation = currentLocation
47+
if (mainParent == null) mainParent = ai.parent
48+
if (startingLocation.distanceTo(currentLocation) >= 1) runTo(startingLocation)
49+
mainLocation = startingLocation
5250
}
5351

5452
override suspend fun onModeLoop() {

src/main/java/com/projectswg/holocore/resources/support/objects/awareness/ObjectAware.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/***********************************************************************************
2-
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
2+
* Copyright (c) 2025 /// Project SWG /// www.projectswg.com *
33
* *
4-
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
4+
* ProjectSWG is an emulation project for Star Wars Galaxies founded on *
55
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
6-
* Our goal is to create an emulator which will provide a server for players to *
7-
* continue playing a game similar to the one they used to play. We are basing *
8-
* it on the final publish of the game prior to end-game events. *
6+
* Our goal is to create one or more emulators which will provide servers for *
7+
* players to continue playing a game similar to the one they used to play. *
98
* *
109
* This file is part of Holocore. *
1110
* *
@@ -32,6 +31,7 @@
3231

3332
import java.util.*;
3433
import java.util.concurrent.atomic.AtomicReference;
34+
import java.util.function.Consumer;
3535
import java.util.stream.Collectors;
3636
import java.util.stream.Stream;
3737

@@ -56,7 +56,9 @@ public synchronized void setAware(@NotNull AwarenessType type, @NotNull Collecti
5656

5757
@NotNull
5858
public Set<SWGObject> getAware() {
59-
return getAwareStream().collect(Collectors.toSet());
59+
Set<SWGObject> aware = new HashSet<>();
60+
forEachAware(aware::add);
61+
return aware;
6062
}
6163

6264
@NotNull
@@ -77,8 +79,12 @@ protected TerrainMapChunk getTerrainMapChunk() {
7779
return chunk.get();
7880
}
7981

80-
private Stream<SWGObject> getAwareStream() {
81-
return awareness.values().stream().flatMap(Collection::stream);
82+
public void forEachAware(Consumer<SWGObject> handler) {
83+
for (Collection<SWGObject> objects : awareness.values()) {
84+
for (SWGObject object : objects) {
85+
handler.accept(object);
86+
}
87+
}
8288
}
8389

8490
private boolean notAware(SWGObject test) {

src/main/java/com/projectswg/holocore/resources/support/objects/awareness/TerrainMapChunk.kt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
/***********************************************************************************
2-
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
3-
* *
4-
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
2+
* Copyright (c) 2025 /// Project SWG /// www.projectswg.com *
3+
* *
4+
* ProjectSWG is an emulation project for Star Wars Galaxies founded on *
55
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
6-
* Our goal is to create an emulator which will provide a server for players to *
7-
* continue playing a game similar to the one they used to play. We are basing *
8-
* it on the final publish of the game prior to end-game events. *
9-
* *
6+
* Our goal is to create one or more emulators which will provide servers for *
7+
* players to continue playing a game similar to the one they used to play. *
8+
* *
109
* This file is part of Holocore. *
11-
* *
10+
* *
1211
* --------------------------------------------------------------------------------*
13-
* *
12+
* *
1413
* Holocore is free software: you can redistribute it and/or modify *
1514
* it under the terms of the GNU Affero General Public License as *
1615
* published by the Free Software Foundation, either version 3 of the *
1716
* License, or (at your option) any later version. *
18-
* *
17+
* *
1918
* Holocore is distributed in the hope that it will be useful, *
2019
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
2120
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
2221
* GNU Affero General Public License for more details. *
23-
* *
22+
* *
2423
* You should have received a copy of the GNU Affero General Public License *
25-
* along with Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
26-
*/
24+
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
25+
***********************************************************************************/
2726
package com.projectswg.holocore.resources.support.objects.awareness
2827

2928
import com.projectswg.holocore.resources.support.objects.swg.SWGObject

0 commit comments

Comments
 (0)