diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt index b935d143..6aa8e5ea 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt @@ -4,7 +4,7 @@ import com.google.common.collect.ImmutableMap import com.google.gson.TypeAdapter import org.apache.logging.log4j.LogManager import ru.dbotthepony.kstarbound.defs.ActorMovementParameters -import ru.dbotthepony.kstarbound.defs.ClientConfigParameters +import ru.dbotthepony.kstarbound.defs.ClientConfig import ru.dbotthepony.kstarbound.defs.CurrencyDefinition import ru.dbotthepony.kstarbound.defs.MovementParameters import ru.dbotthepony.kstarbound.defs.UniverseServerConfig @@ -16,9 +16,7 @@ import ru.dbotthepony.kstarbound.defs.world.DungeonWorldsConfig import ru.dbotthepony.kstarbound.defs.world.SkyGlobalConfig import ru.dbotthepony.kstarbound.defs.world.WorldTemplateConfig import ru.dbotthepony.kstarbound.json.mapAdapter -import ru.dbotthepony.kstarbound.json.pairSetAdapter import ru.dbotthepony.kstarbound.util.AssetPathStack -import java.util.concurrent.ExecutorService import java.util.concurrent.ForkJoinTask import java.util.concurrent.Future import kotlin.properties.Delegates @@ -36,7 +34,7 @@ object GlobalDefaults { var movementParameters = MovementParameters() private set - var clientParameters = ClientConfigParameters() + var client by Delegates.notNull() private set var worldTemplate by Delegates.notNull() @@ -111,7 +109,7 @@ object GlobalDefaults { tasks.add(load("/default_actor_movement.config", ::actorMovementParameters)) tasks.add(load("/default_movement.config", ::movementParameters)) - tasks.add(load("/client.config", ::clientParameters)) + tasks.add(load("/client.config", ::client)) tasks.add(load("/terrestrial_worlds.config", ::terrestrialWorlds)) tasks.add(load("/asteroids_worlds.config", ::asteroidWorlds)) tasks.add(load("/world_template.config", ::worldTemplate)) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfig.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfig.kt new file mode 100644 index 00000000..feb3b9a7 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfig.kt @@ -0,0 +1,10 @@ +package ru.dbotthepony.kstarbound.defs + +import com.google.common.collect.ImmutableList +import ru.dbotthepony.kommons.util.Either + +data class ClientConfig( + val defaultFootstepSound: Either> = Either.right(ImmutableList.of()), + val windowMonitoringBorder: Int, + val presenceEntityMonitoringBorder: Int, +) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfigParameters.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfigParameters.kt deleted file mode 100644 index cfb213b3..00000000 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfigParameters.kt +++ /dev/null @@ -1,7 +0,0 @@ -package ru.dbotthepony.kstarbound.defs - -import com.google.common.collect.ImmutableList - -data class ClientConfigParameters( - val defaultFootstepSound: ImmutableList = ImmutableList.of(), -) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/RootBindings.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/RootBindings.kt index 0dea446c..7eb4a1fb 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/RootBindings.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/RootBindings.kt @@ -243,7 +243,7 @@ private fun materialFootstepSound(context: ExecutionContext, arguments: Argument return } - context.returnBuffer.setTo(GlobalDefaults.clientParameters.defaultFootstepSound.random()) + context.returnBuffer.setTo(GlobalDefaults.client.defaultFootstepSound.random()) } private fun materialHealth(context: ExecutionContext, arguments: ArgumentIterator) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt index d3fd186c..0dd3ccb8 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt @@ -10,6 +10,9 @@ import it.unimi.dsi.fastutil.ints.IntAVLTreeSet import org.apache.logging.log4j.LogManager import ru.dbotthepony.kommons.io.StreamCodec import ru.dbotthepony.kommons.io.VarIntValueCodec +import ru.dbotthepony.kommons.util.AABBi +import ru.dbotthepony.kommons.vector.Vector2i +import ru.dbotthepony.kstarbound.GlobalDefaults import ru.dbotthepony.kstarbound.network.syncher.BasicNetworkedElement import ru.dbotthepony.kstarbound.network.syncher.NetworkedGroup import ru.dbotthepony.kstarbound.network.syncher.MasterElement @@ -18,6 +21,7 @@ import ru.dbotthepony.kstarbound.player.Avatar import ru.dbotthepony.kstarbound.server.ServerChannels import ru.dbotthepony.kstarbound.world.entities.player.PlayerEntity import java.io.Closeable +import kotlin.math.roundToInt import kotlin.properties.Delegates abstract class Connection(val side: ConnectionSide, val type: ConnectionType) : ChannelInboundHandlerAdapter(), Closeable { @@ -150,16 +154,45 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType) : val windowHeight = networkedSignedInt() val playerID = networkedSignedInt() - // holy shit - val clientPresenceEntities = BasicNetworkedElement(IntAVLTreeSet(), StreamCodec.Collection(VarIntValueCodec) { IntAVLTreeSet() }) + var playerEntity: PlayerEntity? = null + protected set - val clientStateGroup = MasterElement(NetworkedGroup(windowXMin, windowYMin, windowWidth, windowHeight, playerID, clientPresenceEntities)) + // holy shit + val clientSpectatingEntities = BasicNetworkedElement(IntAVLTreeSet(), StreamCodec.Collection(VarIntValueCodec) { IntAVLTreeSet() }) + val clientStateGroup = MasterElement(NetworkedGroup(windowXMin, windowYMin, windowWidth, windowHeight, playerID, clientSpectatingEntities)) + + // in tiles + fun trackingRegions(): List { + val result = ArrayList() + + val mins = Vector2i(windowXMin.get() - GlobalDefaults.client.windowMonitoringBorder, windowYMin.get() - GlobalDefaults.client.windowMonitoringBorder) + val maxs = Vector2i(windowWidth.get() + GlobalDefaults.client.windowMonitoringBorder, windowHeight.get() + GlobalDefaults.client.windowMonitoringBorder) + val window = AABBi(mins, maxs + mins) + + if (window.mins != Vector2i.ZERO && window.maxs != Vector2i.ZERO) { + result.add(window) + } + + val playerEntity = playerEntity + + if (playerEntity != null) { + // add an extra region the size of the window centered on the player's position to prevent nearby sectors + // being unloaded due to camera panning or centering on other entities + result.add(window + Vector2i(playerEntity.position.x.roundToInt(), playerEntity.position.y.roundToInt())) + } + + for (entity in clientSpectatingEntities.get()) { + // TODO + } + + return result + } companion object { private val LOGGER = LogManager.getLogger() val NIO_POOL by lazy { - NioEventLoopGroup(ThreadFactoryBuilder().setDaemon(true).setNameFormat("Starbound Network IO %d").build()) + NioEventLoopGroup(1, ThreadFactoryBuilder().setDaemon(true).setNameFormat("Starbound Network IO %d").build()) } } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerConnection.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerConnection.kt index 4b7b1290..a0fe3639 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerConnection.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerConnection.kt @@ -165,9 +165,12 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn tickets.values.forEach { it.cancel() } tickets.clear() pendingSend.clear() + playerEntity = null } override fun onChannelClosed() { + playerEntity = null + super.onChannelClosed() server.channels.freeConnectionID(connectionID) server.channels.connections.remove(this) @@ -265,12 +268,7 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn } fun tickWorld() { - val world = world - - if (world == null) { - onLeaveWorld() - return - } + val world = world!! run { var next = tasks.poll() @@ -281,6 +279,8 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn } } + playerEntity = world.entities[playerID.get()] as? PlayerEntity + if (needsToRecomputeTrackedChunks) { recomputeTrackedChunks() } @@ -318,10 +318,7 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn } else { val (data, version) = entity.networkGroup.write(remoteVersion = entityVersions.get(id), isLegacy = isLegacy) entityVersions.put(id, version) - - if (data.isNotEmpty()) { - send(EntityUpdateSetPacket(entity.connectionID, Int2ObjectMaps.singleton(entity.entityID, data))) - } + send(EntityUpdateSetPacket(entity.connectionID, Int2ObjectMaps.singleton(entity.entityID, data))) } } }