Skip to content

Commit

Permalink
Replaced nice code with fast code
Browse files Browse the repository at this point in the history
  • Loading branch information
Martomate committed Aug 4, 2024
1 parent 5ed1e91 commit 7086045
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 41 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Dependencies.*
import scala.util.Properties.isMac

ThisBuild / organization := "com.martomate"
ThisBuild / version := "0.14"
ThisBuild / version := "0.14.1"
ThisBuild / scalaVersion := "3.4.2"
ThisBuild / publishArtifact := false
ThisBuild / logBuffered := false
Expand Down
73 changes: 45 additions & 28 deletions client/src/main/scala/hexacraft/client/ClientWorld.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import hexacraft.world.coord.*
import hexacraft.world.entity.{Entity, EntityFactory, EntityPhysicsSystem}

import java.util.UUID
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

Expand Down Expand Up @@ -210,34 +209,47 @@ class ClientWorld(val worldInfo: WorldInfo) extends BlockRepository with BlocksI

var chunkWasRemoved = false

for col <- columns.get(columnCoords.value) do {
for removedChunk <- chunks.remove(chunkCoords.value) do {
chunkWasRemoved = true
requestRenderUpdate(chunkCoords) // this will remove the render data for the chunk
requestRenderUpdateForNeighborChunks(chunkCoords)
}
columns.get(columnCoords.value) match {
case Some(col) =>
chunks.remove(chunkCoords.value) match {
case Some(removedChunk) =>
chunkWasRemoved = true
requestRenderUpdate(chunkCoords) // this will remove the render data for the chunk
requestRenderUpdateForNeighborChunks(chunkCoords)
case None =>
}

if chunks.keys.count(v => ChunkRelWorld(v).getColumnRelWorld == columnCoords) == 0 then {
columns.remove(columnCoords.value)
}
if chunks.keys.count(v => ChunkRelWorld(v).getColumnRelWorld == columnCoords) == 0 then {
columns.remove(columnCoords.value)
}
case None =>
}

chunkWasRemoved
}

def tick(cameras: Seq[Camera], entityEvents: Seq[(UUID, EntityEvent)]): WorldTickResult = {
val allEntitiesById = mutable.HashMap.empty[UUID, (ChunkRelWorld, Entity)]
for (chunkCoordsValue, ch) <- chunks do {
val chunkCoords = ChunkRelWorld(chunkCoordsValue)
for e <- ch.entities do {
allEntitiesById(e.id) = (chunkCoords, e)

{
val chIt = chunks.iterator
while chIt.hasNext do {
val (chunkCoordsValue, ch) = chIt.next()
val chunkCoords = ChunkRelWorld(chunkCoordsValue)
val eIt = ch.entities.iterator
while eIt.hasNext do {
val e = eIt.next()
allEntitiesById(e.id) = (chunkCoords, e)
}
}
}

{
val entities = entitiesToSpawnLater.toSeq
entitiesToSpawnLater.clear()
for e <- entities do {
val eIt = entities.iterator
while eIt.hasNext do {
val e = eIt.next()
if addEntity(e).isEmpty then {
entitiesToSpawnLater += e
// println(s"Client: not ready to spawn entity ${e.id}")
Expand All @@ -247,7 +259,9 @@ class ClientWorld(val worldInfo: WorldInfo) extends BlockRepository with BlocksI
}
}

for (id, event) <- entityEvents do {
val evIt = entityEvents.iterator
while evIt.hasNext do {
val (id, event) = evIt.next()
allEntitiesById.get(id) match {
case Some(ent) =>
val (c, e) = ent
Expand Down Expand Up @@ -294,9 +308,18 @@ class ClientWorld(val worldInfo: WorldInfo) extends BlockRepository with BlocksI
}
}

for ch <- chunks.values do {
ch.optimizeStorage()
tickEntities(ch.entities)
{
val chIt = chunks.valuesIterator
while chIt.hasNext do {
val ch = chIt.next()
ch.optimizeStorage()

val eIt = ch.entities.iterator
while eIt.hasNext do {
val e = eIt.next()
tickEntity(e)
}
}
}

val r = chunksNeedingRenderUpdate.toSeq
Expand All @@ -305,14 +328,6 @@ class ClientWorld(val worldInfo: WorldInfo) extends BlockRepository with BlocksI
new WorldTickResult(r)
}

@tailrec // this is done for performance
private def tickEntities(ents: Iterable[Entity]): Unit = {
if ents.nonEmpty then {
tickEntity(ents.head)
tickEntities(ents.tail)
}
}

private def tickEntity(e: Entity): Unit = {
e.ai match {
case Some(ai) =>
Expand All @@ -328,7 +343,9 @@ class ClientWorld(val worldInfo: WorldInfo) extends BlockRepository with BlocksI

val vel = e.motion.velocity
val horizontalSpeedSq = vel.x * vel.x + vel.z * vel.z
e.model.foreach(_.tick(horizontalSpeedSq > 0.1))
if e.model.isDefined then {
e.model.get.tick(horizontalSpeedSq > 0.1)
}
}

private def requestRenderUpdateForNeighborChunks(coords: ChunkRelWorld): Unit = {
Expand Down
22 changes: 10 additions & 12 deletions server/src/main/scala/hexacraft/server/ServerWorld.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.martomate.nbt.Nbt

import java.util.UUID
import java.util.concurrent.{Executors, TimeUnit}
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.{Await, ExecutionContext, Future}
Expand Down Expand Up @@ -322,12 +321,17 @@ class ServerWorld(worldProvider: WorldProvider, val worldInfo: WorldInfo)
performEntityRelocation()
}

val chIt = chunks.values.iterator
val chIt = chunks.valuesIterator
while chIt.hasNext do {
val ch = chIt.next

ch.optimizeStorage()
tickEntities(ch.entities)

val eIt = ch.entities.iterator
while eIt.hasNext do {
val e = eIt.next()
tickEntity(e)
}
}

val entityEvents = mutable.ArrayBuffer.empty[(UUID, EntityEvent)]
Expand Down Expand Up @@ -460,14 +464,6 @@ class ServerWorld(worldProvider: WorldProvider, val worldInfo: WorldInfo)
worldProvider.saveColumnData(ChunkColumnData(Some(col.terrainHeight)).toNBT, columnCoords)
}

@tailrec // this is done for performance
private def tickEntities(ents: Iterable[Entity]): Unit = {
if ents.nonEmpty then {
tickEntity(ents.head)
tickEntities(ents.tail)
}
}

private def tickEntity(e: Entity): Unit = {
e.ai match {
case Some(ai) =>
Expand All @@ -481,7 +477,9 @@ class ServerWorld(worldProvider: WorldProvider, val worldInfo: WorldInfo)

entityPhysicsSystem.update(e.transform, e.motion, e.boundingBox)

e.model.foreach(_.tick(e.motion.velocity.lengthSquared() > 0.1))
if e.model.isDefined then {
e.model.get.tick(e.motion.velocity.lengthSquared() > 0.1)
}
}

private val blockUpdateTimer: TickableTimer = TickableTimer(ServerWorld.ticksBetweenBlockUpdates)
Expand Down

0 comments on commit 7086045

Please sign in to comment.