SkyParameters are now finally generated

This commit is contained in:
DBotThePony 2024-04-04 10:50:46 +07:00
parent 55253f78d1
commit cb384be77a
Signed by: DBot
GPG Key ID: DCC23B5715498507
27 changed files with 548 additions and 235 deletions

View File

@ -12,6 +12,9 @@ import ru.dbotthepony.kstarbound.defs.actor.player.PlayerConfig
import ru.dbotthepony.kstarbound.defs.tile.TileDamageConfig
import ru.dbotthepony.kstarbound.defs.world.TerrestrialWorldsConfig
import ru.dbotthepony.kstarbound.defs.world.AsteroidWorldsConfig
import ru.dbotthepony.kstarbound.defs.world.CelestialBaseInformation
import ru.dbotthepony.kstarbound.defs.world.CelestialConfig
import ru.dbotthepony.kstarbound.defs.world.CelestialNames
import ru.dbotthepony.kstarbound.defs.world.DungeonWorldsConfig
import ru.dbotthepony.kstarbound.defs.world.SkyGlobalConfig
import ru.dbotthepony.kstarbound.defs.world.SystemWorldConfig
@ -24,7 +27,7 @@ import java.util.concurrent.Future
import kotlin.properties.Delegates
import kotlin.reflect.KMutableProperty0
object GlobalDefaults {
object Globals {
private val LOGGER = LogManager.getLogger()
var player by Delegates.notNull<PlayerConfig>()
@ -78,6 +81,15 @@ object GlobalDefaults {
var systemWorld by Delegates.notNull<SystemWorldConfig>()
private set
var celestialBaseInformation by Delegates.notNull<CelestialBaseInformation>()
private set
var celestialConfig by Delegates.notNull<CelestialConfig>()
private set
var celestialNames by Delegates.notNull<CelestialNames>()
private set
private object EmptyTask : ForkJoinTask<Unit>() {
private fun readResolve(): Any = EmptyTask
override fun getRawResult() {
@ -128,6 +140,9 @@ object GlobalDefaults {
tasks.add(load("/universe_server.config", ::universeServer))
tasks.add(load("/player.config", ::player))
tasks.add(load("/systemworld.config", ::systemWorld))
tasks.add(load("/celestial.config", ::celestialBaseInformation))
tasks.add(load("/celestial.config", ::celestialConfig))
tasks.add(load("/celestial/names.config", ::celestialNames))
tasks.add(load("/plants/grassDamage.config", ::grassDamage))
tasks.add(load("/plants/treeDamage.config", ::treeDamage))

View File

@ -24,17 +24,13 @@ import ru.dbotthepony.kommons.gson.Vector4iTypeAdapter
import ru.dbotthepony.kommons.util.MailboxExecutorService
import ru.dbotthepony.kstarbound.collect.WeightedList
import ru.dbotthepony.kstarbound.defs.*
import ru.dbotthepony.kstarbound.defs.actor.StatModifier
import ru.dbotthepony.kstarbound.defs.image.Image
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
import ru.dbotthepony.kstarbound.defs.item.api.IArmorItemDefinition
import ru.dbotthepony.kstarbound.defs.item.InventoryIcon
import ru.dbotthepony.kstarbound.defs.item.TreasurePoolDefinition
import ru.dbotthepony.kstarbound.defs.`object`.ObjectDefinition
import ru.dbotthepony.kstarbound.defs.`object`.ObjectOrientation
import ru.dbotthepony.kstarbound.defs.actor.player.BlueprintLearnList
import ru.dbotthepony.kstarbound.defs.animation.Particle
import ru.dbotthepony.kstarbound.defs.item.ItemDescriptor
import ru.dbotthepony.kstarbound.defs.quest.QuestParameter
import ru.dbotthepony.kstarbound.defs.world.CelestialParameters
import ru.dbotthepony.kstarbound.defs.world.VisitableWorldParametersType
@ -57,7 +53,6 @@ import ru.dbotthepony.kstarbound.json.factory.ImmutableCollectionAdapterFactory
import ru.dbotthepony.kstarbound.json.factory.PairAdapterFactory
import ru.dbotthepony.kstarbound.json.factory.RGBAColorTypeAdapter
import ru.dbotthepony.kstarbound.json.factory.SingletonTypeAdapterFactory
import ru.dbotthepony.kstarbound.math.*
import ru.dbotthepony.kstarbound.server.world.UniverseChunk
import ru.dbotthepony.kstarbound.item.ItemStack
import ru.dbotthepony.kstarbound.json.JsonAdapterTypeFactory
@ -68,7 +63,6 @@ import ru.dbotthepony.kstarbound.util.ExceptionLogger
import ru.dbotthepony.kstarbound.util.SBPattern
import ru.dbotthepony.kstarbound.util.HashTableInterner
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise
import ru.dbotthepony.kstarbound.world.UniversePos
import ru.dbotthepony.kstarbound.world.physics.Poly
import java.io.*
import java.lang.ref.Cleaner
@ -571,7 +565,7 @@ object Starbound : ISBFileLocator {
tasks.addAll(Registries.load(ext2files))
tasks.addAll(RecipeRegistry.load(ext2files))
tasks.addAll(GlobalDefaults.load())
tasks.addAll(Globals.load())
tasks.add(VersionRegistry.load())
val total = tasks.size.toDouble()

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.defs.tile
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.Either
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.AssetReference
import ru.dbotthepony.kstarbound.world.physics.CollisionType
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
@ -27,7 +27,7 @@ data class TileDefinition(
val category: String,
@Deprecated("", replaceWith = ReplaceWith("this.actualDamageTable"))
val damageTable: AssetReference<TileDamageConfig> = AssetReference(GlobalDefaults::tileDamage),
val damageTable: AssetReference<TileDamageConfig> = AssetReference(Globals::tileDamage),
val health: Double? = null,
val requiredHarvestLevel: Int? = null,

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.defs.tile
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.AssetReference
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription
@ -23,7 +23,7 @@ data class TileModifierDefinition(
val miningSounds: ImmutableList<String> = ImmutableList.of(),
@Deprecated("", replaceWith = ReplaceWith("this.actualDamageTable"))
val damageTable: AssetReference<TileDamageConfig> = AssetReference(GlobalDefaults::tileDamage),
val damageTable: AssetReference<TileDamageConfig> = AssetReference(Globals::tileDamage),
@JsonFlat
val descriptionData: ThingDescription,

View File

@ -7,9 +7,8 @@ import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.AABBi
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.fromJson
import ru.dbotthepony.kstarbound.io.readColor
import ru.dbotthepony.kstarbound.io.readInternedString
import ru.dbotthepony.kstarbound.io.writeColor
@ -96,7 +95,7 @@ class AsteroidsWorldParameters : VisitableWorldParameters() {
override fun createLayout(seed: Long): WorldLayout {
val random = random(seed)
val terrain = GlobalDefaults.asteroidWorlds.terrains.random(random)
val terrain = Globals.asteroidWorlds.terrains.random(random)
val layout = WorldLayout()
layout.worldSize = worldSize
@ -118,12 +117,12 @@ class AsteroidsWorldParameters : VisitableWorldParameters() {
worldSize.y / 2,
threatLevel,
asteroidBiome,
GlobalDefaults.asteroidWorlds.emptyTerrain.terrainSelector,
GlobalDefaults.asteroidWorlds.emptyTerrain.caveSelector,
GlobalDefaults.asteroidWorlds.emptyTerrain.bgCaveSelector,
GlobalDefaults.asteroidWorlds.emptyTerrain.oreSelector,
GlobalDefaults.asteroidWorlds.emptyTerrain.oreSelector,
GlobalDefaults.asteroidWorlds.emptyTerrain.subBlockSelector,
Globals.asteroidWorlds.emptyTerrain.terrainSelector,
Globals.asteroidWorlds.emptyTerrain.caveSelector,
Globals.asteroidWorlds.emptyTerrain.bgCaveSelector,
Globals.asteroidWorlds.emptyTerrain.oreSelector,
Globals.asteroidWorlds.emptyTerrain.oreSelector,
Globals.asteroidWorlds.emptyTerrain.subBlockSelector,
WorldLayout.RegionLiquids(),
)
@ -132,7 +131,7 @@ class AsteroidsWorldParameters : VisitableWorldParameters() {
layout.addLayer(random, asteroidTopLevel, emptyRegion)
layout.regionBlending = blendSize
layout.blockNoise = GlobalDefaults.asteroidWorlds.blockNoise?.build(random)
layout.blockNoise = Globals.asteroidWorlds.blockNoise?.build(random)
layout.playerStartSearchRegions.add(
AABBi(
@ -151,21 +150,21 @@ class AsteroidsWorldParameters : VisitableWorldParameters() {
val parameters = AsteroidsWorldParameters()
parameters.threatLevel = random.nextRange(GlobalDefaults.asteroidWorlds.threatRange)
parameters.threatLevel = random.nextRange(Globals.asteroidWorlds.threatRange)
parameters.typeName = "asteroids"
parameters.worldSize = GlobalDefaults.asteroidWorlds.worldSize
parameters.gravity = Vector2d(y = random.nextRange(GlobalDefaults.asteroidWorlds.gravityRange))
parameters.environmentStatusEffects = GlobalDefaults.asteroidWorlds.environmentStatusEffects
parameters.overrideTech = GlobalDefaults.asteroidWorlds.overrideTech
parameters.globalDirectives = GlobalDefaults.asteroidWorlds.globalDirectives
parameters.beamUpRule = GlobalDefaults.asteroidWorlds.beamUpRule
parameters.disableDeathDrops = GlobalDefaults.asteroidWorlds.disableDeathDrops
parameters.worldEdgeForceRegions = GlobalDefaults.asteroidWorlds.worldEdgeForceRegions
parameters.asteroidTopLevel = GlobalDefaults.asteroidWorlds.asteroidsTop
parameters.asteroidBottomLevel = GlobalDefaults.asteroidWorlds.asteroidsBottom
parameters.blendSize = GlobalDefaults.asteroidWorlds.blendSize
parameters.ambientLightLevel = GlobalDefaults.asteroidWorlds.ambientLightLevel
parameters.asteroidBiome = GlobalDefaults.asteroidWorlds.biome
parameters.worldSize = Globals.asteroidWorlds.worldSize
parameters.gravity = Vector2d(y = random.nextRange(Globals.asteroidWorlds.gravityRange))
parameters.environmentStatusEffects = Globals.asteroidWorlds.environmentStatusEffects
parameters.overrideTech = Globals.asteroidWorlds.overrideTech
parameters.globalDirectives = Globals.asteroidWorlds.globalDirectives
parameters.beamUpRule = Globals.asteroidWorlds.beamUpRule
parameters.disableDeathDrops = Globals.asteroidWorlds.disableDeathDrops
parameters.worldEdgeForceRegions = Globals.asteroidWorlds.worldEdgeForceRegions
parameters.asteroidTopLevel = Globals.asteroidWorlds.asteroidsTop
parameters.asteroidBottomLevel = Globals.asteroidWorlds.asteroidsBottom
parameters.blendSize = Globals.asteroidWorlds.blendSize
parameters.ambientLightLevel = Globals.asteroidWorlds.ambientLightLevel
parameters.asteroidBiome = Globals.asteroidWorlds.biome
return parameters
}

View File

@ -3,8 +3,7 @@ package ru.dbotthepony.kstarbound.defs.world
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableSet
import com.google.gson.JsonElement
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.AssetReference
@ -65,7 +64,7 @@ class BushVariant(
ceiling = data.value.ceiling,
descriptions = data.value.descriptions.fixDescription("${data.key} with $modName").toMap(),
ephemeral = data.value.ephemeral,
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.bushDamage).copy(totalHealth = data.value.health),
tileDamageParameters = (data.value.damageTable?.value ?: Globals.bushDamage).copy(totalHealth = data.value.health),
modName = modName,
shapes = data.value.shapes.stream().map { Shape(it.base, it.mods[modName] ?: ImmutableList.of()) }.collect(ImmutableList.toImmutableList())
)

View File

@ -4,11 +4,12 @@ import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.gson.JsonObject
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise
@JsonFactory
data class CelestialGenerationInformation(
data class CelestialConfig(
val systemProbability: Double,
val constellationProbability: Double,
val constellationLineCountRange: Vector2i,
@ -19,11 +20,18 @@ data class CelestialGenerationInformation(
val minimumConstellationLineCloseness: Double,
val systemTypes: ImmutableMap<String, System>,
val systemTypePerlin: AbstractPerlinNoise,
val systemTypePerlin: PerlinNoiseParameters,
val systemTypeBins: ImmutableList<Pair<Double, String>>,
val planetaryTypes: ImmutableMap<String, Planet>,
val satelliteTypes: ImmutableMap<String, Satellite>,
val terrestrialGraphics: ImmutableMap<String, JsonObject>,
val terrestrialHorizonGraphics: ImmutableMap<String, JsonObject>,
val asteroidsHorizons: String,
val floatingDungeonHorizons: ImmutableMap<String, String>,
val gasGiantGraphics: JsonObject,
) {
init {
systemTypeBins.forEach {

View File

@ -5,10 +5,9 @@ import ru.dbotthepony.kommons.gson.set
import ru.dbotthepony.kommons.io.writeBinaryString
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.fromJson
import ru.dbotthepony.kstarbound.io.readColor
import ru.dbotthepony.kstarbound.io.readInternedString
import ru.dbotthepony.kstarbound.io.readNullableString
@ -144,7 +143,7 @@ class FloatingDungeonWorldParameters : VisitableWorldParameters() {
companion object {
fun generate(typeName: String): FloatingDungeonWorldParameters {
val config = GlobalDefaults.dungeonWorlds[typeName] ?: throw NoSuchElementException("Unknown dungeon world type $typeName!")
val config = Globals.dungeonWorlds[typeName] ?: throw NoSuchElementException("Unknown dungeon world type $typeName!")
val parameters = FloatingDungeonWorldParameters()
parameters.threatLevel = config.threatLevel

View File

@ -2,8 +2,7 @@ package ru.dbotthepony.kstarbound.defs.world
import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableSet
import com.google.gson.JsonElement
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.AssetReference
@ -54,7 +53,7 @@ data class GrassVariant(
ephemeral = data.value.ephemeral,
hueShift = hueShift,
descriptions = data.value.descriptions.fixDescription(data.value.name).toMap(),
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.grassDamage).copy(totalHealth = data.value.health)
tileDamageParameters = (data.value.damageTable?.value ?: Globals.grassDamage).copy(totalHealth = data.value.health)
)
}
}

View File

@ -1,15 +1,24 @@
package ru.dbotthepony.kstarbound.defs.world
import com.google.common.collect.ImmutableList
import com.google.gson.JsonObject
import it.unimi.dsi.fastutil.ints.IntArrayList
import ru.dbotthepony.kommons.gson.contains
import ru.dbotthepony.kommons.gson.get
import ru.dbotthepony.kommons.io.StreamCodec
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.Either
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.AssetPath
import ru.dbotthepony.kstarbound.io.readColor
import ru.dbotthepony.kstarbound.io.writeColor
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.json.mergeJson
import ru.dbotthepony.kstarbound.util.random.nextRange
import ru.dbotthepony.kstarbound.util.random.random
import ru.dbotthepony.kstarbound.world.Universe
import ru.dbotthepony.kstarbound.world.UniversePos
@ -123,16 +132,17 @@ data class SkyWorldHorizon(val center: Vector2d, val scale: Double, val rotation
@JsonFactory
data class SkyParameters(
val skyType: SkyType = SkyType.BARREN,
val seed: Long = 0L,
val dayLength: Double? = null,
val horizonClouds: Boolean = false,
val skyColoring: Either<SkyColoring, RGBAColor> = Either.left(SkyColoring()),
val spaceLevel: Double? = null,
val surfaceLevel: Double? = null,
val nearbyPlanet: Planet? = null,
val nearbyMoons: ImmutableList<Planet> = ImmutableList.of(),
val horizonImages: ImmutableList<HorizonImage> = ImmutableList.of(),
var skyType: SkyType = SkyType.BARREN,
var seed: Long = 0L,
var dayLength: Double? = null,
var horizonClouds: Boolean = false,
var skyColoring: SkyColoring? = null,
var ambientLightLevel: RGBAColor? = RGBAColor.BLACK,
var spaceLevel: Double? = null,
var surfaceLevel: Double? = null,
var planet: Planet? = null,
var satellites: ImmutableList<Planet> = ImmutableList.of(),
var horizonImages: ImmutableList<HorizonImage> = ImmutableList.of(),
) {
@JsonFactory
data class HorizonImage(val left: String, val right: String)
@ -144,6 +154,196 @@ data class SkyParameters(
data class Planet(val pos: Vector2d, val layers: ImmutableList<Layer>)
companion object {
private val vectors by lazy { Starbound.gson.getAdapter(Vector2i::class.java) }
fun drawWorld(parameters: CelestialParameters, shadow: CelestialParameters? = null): List<Layer> {
val layers = ArrayList<Layer>()
val random = random(parameters.seed)
// i have no clue why they added this but ok
val shadowRandom = random(shadow?.seed ?: parameters.seed)
when (parameters.parameters["worldType"]?.asString?.lowercase() ?: return emptyList()) {
"terrestrial" -> {
val visitable = parameters.visitableParameters as? TerrestrialWorldParameters ?: return emptyList()
val gfxConfig = mergeJson(Globals.celestialConfig.terrestrialGraphics["default"] ?: return emptyList(), Globals.celestialConfig.terrestrialGraphics[visitable.typeName] ?: JsonObject())
val liquidImages = gfxConfig.get("liquidImages", "")
val baseImages = gfxConfig.get("baseImages", "")
val shadowImages = gfxConfig.get("shadowImages", "")
val baseCount = gfxConfig.get("baseCount", 0)
val dynamicsImages = gfxConfig.get("dynamicsImages", "")
val imageScale = parameters.parameters.get("imageScale", 1.0)
// If the planet has water, then draw the corresponding water image as the
// base layer, otherwise use the bottom most mask image.
val surfaceLiquid = visitable.surfaceLiquid?.map({ Registries.liquid[it] }, { Registries.liquid[it] })?.key
if (surfaceLiquid != null && liquidImages.isNotBlank()) {
layers.add(Layer(liquidImages.replace("<liquid>", surfaceLiquid), imageScale))
} else {
if (baseCount > 0) {
layers.add(Layer("${baseImages.replace("<biome>", visitable.primaryBiome).replace("<num>", baseCount.toString())}?hueshift=${visitable.hueShift}", imageScale))
}
}
// Then draw all the biome layers
for (i in 0 until baseCount) {
val baseImage = baseImages.replace("<num>", (baseCount - i).toString())
var hueShift = ""
var dynamicMask = ""
if (dynamicsImages.isNotBlank())
dynamicMask = "?addmask=" + dynamicsImages.replace("<num>", random.nextRange(gfxConfig.get("dynamicsRange", vectors)).toString())
if (visitable.hueShift != 0.0)
hueShift = "?hueshift=${visitable.hueShift.toInt()}"
layers.add(Layer(baseImage + hueShift + dynamicMask, imageScale))
}
if (shadowImages.isNotBlank()) {
layers.add(Layer(shadowImages.replace("<num>", shadowRandom.nextRange(gfxConfig.get("shadowNumber", vectors)).toString()), imageScale))
}
}
"asteroids" -> {
val maskImages = parameters.parameters.get("maskImages").asString
val masks = parameters.parameters.get("masks").asInt
val dynamicsImages = parameters.parameters.get("dynamicsImages").asString
val imageScale = parameters.parameters.get("imageScale", 1.0)
val dynamicsRange = parameters.parameters.get("dynamicsRange", vectors)
for (i in 0 until masks) {
val biomeMaskBase = maskImages.replace("<num>", (masks - i).toString())
val dynamicMask = dynamicsImages.replace("<num>", random.nextRange(dynamicsRange).toString())
layers.add(Layer("$biomeMaskBase?addmask=$dynamicMask", imageScale))
}
}
"floatingdungeon" -> {
val image = parameters.parameters.get("image").asString
val imageScale = parameters.parameters.get("imageScale", 1.0)
layers.add(Layer(image, imageScale))
if ("dynamicsImages" in parameters.parameters && parameters.parameters.get("dynamicsImages").asString.isNotBlank()) {
layers.add(Layer(
parameters.parameters.get("dynamicsImages").asString
.replace("<num>", random.nextRange(parameters.parameters.get("dynamicsRange", vectors)).toString()), imageScale))
}
}
"gasgiant" -> {
val gfxConfig = Globals.celestialConfig.gasGiantGraphics
val baseImage = gfxConfig.get("baseImage", "")
val shadowImages = gfxConfig.get("shadowImages", "")
val dynamicsImages = gfxConfig.get("dynamicsImages", "")
val overlayImages = gfxConfig.get("overlayImages", "")
val overlayCount = gfxConfig.get("overlayCount", 0)
val imageScale = parameters.parameters.get("imageScale", 1.0)
val offsetRange = gfxConfig.get("hueShiftOffsetRange", vectors)
val dynamicsRange = gfxConfig.get("dynamicsRange", vectors)
var hueshift = random.nextRange(gfxConfig.get("primaryHueShiftRange", vectors))
if (baseImage.isNotBlank())
layers.add(Layer("$baseImage?hueshift=$hueshift", imageScale))
if (overlayImages.isNotBlank()) {
for (i in 0 until overlayCount) {
hueshift += random.nextRange(offsetRange)
val maskImage = dynamicsImages.replace("<num>", random.nextRange(dynamicsRange).toString())
val overlayImage = overlayImages.replace("<num>", i.toString())
layers.add(Layer("$overlayImage?hueshift=$hueshift?addmask=$maskImage", imageScale))
}
}
if (shadowImages.isNotBlank()) {
layers.add(Layer(shadowImages.replace("<num>", shadowRandom.nextRange(gfxConfig.get("shadowNumber", vectors)).toString()), imageScale))
}
}
}
return layers
}
fun horizonImages(parameters: CelestialParameters): List<HorizonImage> {
fun getLR(value: String): HorizonImage {
return HorizonImage(value.replace("<selector>", "l"), value.replace("<selector>", "r"))
}
val images = ArrayList<HorizonImage>()
when (parameters.parameters["worldType"]?.asString?.lowercase() ?: return emptyList()) {
"terrestrial" -> {
val visitable = parameters.visitableParameters as? TerrestrialWorldParameters ?: return emptyList()
val gfxConfig = mergeJson(Globals.celestialConfig.terrestrialHorizonGraphics["default"] ?: return emptyList(), Globals.celestialConfig.terrestrialHorizonGraphics[visitable.typeName] ?: JsonObject())
val baseImages = gfxConfig.get("baseImages").asString
val atmoTextures = gfxConfig.get("atmosphereTextures").asString
val shadowTextures = gfxConfig.get("shadowTextures").asString
val maskTextures = gfxConfig.get("maskTextures").asString
val liquidTextures = gfxConfig.get("liquidTextures").asString
val numMasks = gfxConfig.get("maskRange", vectors)
val maskPerPlanetRange = gfxConfig.get("maskPerPlanetRange", vectors)
val biomeHueShift = "?hueshift=${visitable.hueShift.toInt()}"
val surfaceLiquid = visitable.surfaceLiquid?.map({ Registries.liquid[it] }, { Registries.liquid[it] })?.key
if (surfaceLiquid != null) {
val random = random(parameters.seed)
for (i in 0 until 23)
random.nextInt()
images.add(getLR(liquidTextures.replace("<liquid>", surfaceLiquid)))
val masksL = ArrayList<String>()
val masksR = ArrayList<String>()
for (i in 0 until random.nextRange(maskPerPlanetRange)) {
val m = random.nextRange(numMasks)
val (l, r) = getLR(maskTextures.replace("<mask>", m.toString()))
masksL.add(l)
masksR.add(r)
}
val left = if (masksL.isNotEmpty()) "?" + masksL.joinToString("?") { "addmask=$it" } else ""
val right = if (masksR.isNotEmpty()) "?" + masksR.joinToString("?") { "addmask=$it" } else ""
val (l, r) = getLR(baseImages + biomeHueShift)
images.add(HorizonImage(l + left, r + right))
} else {
images.add(getLR(baseImages + biomeHueShift))
}
// original code uses "atmosphere" parameter, but... it seems to be a leftover?
if (!visitable.airless) {
images.add(getLR(atmoTextures))
}
images.add(getLR(shadowTextures))
}
"asteroids" -> {
images.add(getLR(Globals.celestialConfig.asteroidsHorizons))
}
"floatingdungeon" -> {
val visitable = parameters.visitableParameters as? FloatingDungeonWorldParameters ?: return emptyList()
val base = Globals.celestialConfig.floatingDungeonHorizons[visitable.typeName] ?: return emptyList()
images.add(getLR(base))
}
}
return images
}
suspend fun create(coordinate: UniversePos, universe: Universe): SkyParameters {
if (coordinate.isSystem)
throw IllegalArgumentException("$coordinate is system location")
@ -153,13 +353,22 @@ data class SkyParameters(
val random = random(params.seed)
val selfPos = params.coordinate
val nearbyMoons = ArrayList<Planet>()
val sky = SkyParameters()
for (i in 0 until 66)
random.nextInt()
sky.seed = random.nextLong()
if (selfPos.isSatellite) {
val planet = universe.parameters(selfPos.parent())
if (planet != null) {
val pos = Vector2d(random.nextDouble(), random.nextDouble())
// My parent's parent is no one.
sky.planet = Planet(pos, ImmutableList.copyOf(drawWorld(planet)))
}
}
@ -169,10 +378,44 @@ data class SkyParameters(
if (satellite != null) {
val pos = Vector2d(random.nextDouble(), random.nextDouble())
nearbyMoons.add(Planet(pos, ImmutableList.copyOf(drawWorld(satellite, universe.parameters(satellitePos.parent())))))
}
}
}
sky.satellites = ImmutableList.copyOf(nearbyMoons)
sky.horizonImages = ImmutableList.copyOf(horizonImages(params))
val visitable = params.visitableParameters
if (visitable is TerrestrialWorldParameters) {
sky.dayLength = visitable.dayLength
if (visitable.airless) {
sky.skyType = SkyType.ATMOSPHERELESS
sky.horizonClouds = false
} else {
sky.skyType = SkyType.ATMOSPHERIC
sky.horizonClouds = true
}
sky.skyColoring = visitable.skyColoring
sky.ambientLightLevel = null
sky.spaceLevel = visitable.spaceLayer.layerMinHeight.toDouble()
sky.surfaceLevel = visitable.surfaceLayer.layerMinHeight.toDouble()
} else {
sky.skyType = SkyType.BARREN
sky.horizonClouds = false
if (visitable is AsteroidsWorldParameters) {
sky.ambientLightLevel = visitable.ambientLightLevel
} else if (visitable is FloatingDungeonWorldParameters) {
sky.ambientLightLevel = visitable.ambientLightLevel
} else {
sky.ambientLightLevel = RGBAColor.BLACK
}
}
return sky
}
}

View File

@ -19,11 +19,10 @@ import ru.dbotthepony.kommons.io.writeCollection
import ru.dbotthepony.kommons.util.Either
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.collect.WeightedList
import ru.dbotthepony.kstarbound.defs.JsonDriven
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
import ru.dbotthepony.kstarbound.fromJson
import ru.dbotthepony.kstarbound.io.readInternedString
@ -405,9 +404,9 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
}
fun generate(typeName: String, sizeName: String, random: RandomGenerator): TerrestrialWorldParameters {
val config = GlobalDefaults.terrestrialWorlds.planetDefaults.deepCopy()
mergeJson(config, GlobalDefaults.terrestrialWorlds.planetSizes[sizeName] ?: throw NoSuchElementException("Unknown world size name $sizeName"))
mergeJson(config, GlobalDefaults.terrestrialWorlds.planetTypes[typeName] ?: throw NoSuchElementException("Unknown world type name $typeName"))
val config = Globals.terrestrialWorlds.planetDefaults.deepCopy()
mergeJson(config, Globals.terrestrialWorlds.planetSizes[sizeName] ?: throw NoSuchElementException("Unknown world size name $sizeName"))
mergeJson(config, Globals.terrestrialWorlds.planetTypes[typeName] ?: throw NoSuchElementException("Unknown world type name $typeName"))
val params = Starbound.gson.fromJson(config, Generic::class.java)
@ -481,8 +480,8 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
}
fun makeRegion(name: String, baseHeight: Int): Pair<Region, Region> {
val primaryRegionJson = GlobalDefaults.terrestrialWorlds.regionDefaults.deepCopy()
mergeJson(primaryRegionJson, GlobalDefaults.terrestrialWorlds.regionTypes[name]!!)
val primaryRegionJson = Globals.terrestrialWorlds.regionDefaults.deepCopy()
mergeJson(primaryRegionJson, Globals.terrestrialWorlds.regionTypes[name]!!)
val region = readRegion(primaryRegionJson, baseHeight)
val subRegionList = primaryRegionJson.getArray("subRegion")
@ -490,8 +489,8 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
val subRegion = readRegion(if (subRegionList.isEmpty) {
primaryRegionJson
} else {
val result = GlobalDefaults.terrestrialWorlds.regionDefaults.deepCopy()
mergeJson(result, GlobalDefaults.terrestrialWorlds.regionTypes[subRegionList.random(random).asString]!!)
val result = Globals.terrestrialWorlds.regionDefaults.deepCopy()
mergeJson(result, Globals.terrestrialWorlds.regionTypes[subRegionList.random(random).asString]!!)
result
}, baseHeight)

View File

@ -4,7 +4,7 @@ import com.google.common.collect.ImmutableMap
import com.google.gson.JsonElement
import com.google.gson.JsonNull
import com.google.gson.JsonObject
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.AssetReference
@ -81,7 +81,7 @@ data class TreeVariant(
stemDropConfig = data.value.dropConfig.deepCopy(),
descriptions = data.value.descriptions.fixDescription(data.key).toMap(),
ephemeral = data.value.ephemeral,
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
tileDamageParameters = (data.value.damageTable?.value ?: Globals.treeDamage).copy(totalHealth = data.value.health),
foliageSettings = JsonNull.INSTANCE,
foliageDropConfig = JsonObject(),
@ -108,7 +108,7 @@ data class TreeVariant(
stemDropConfig = data.value.dropConfig.deepCopy(),
descriptions = data.value.descriptions.fixDescription("${data.key} with ${fdata.key}").toMap(),
ephemeral = data.value.ephemeral,
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
tileDamageParameters = (data.value.damageTable?.value ?: Globals.treeDamage).copy(totalHealth = data.value.health),
foliageSettings = fdata.json,
foliageDropConfig = fdata.value.dropConfig.deepCopy(),

View File

@ -20,7 +20,7 @@ import ru.dbotthepony.kommons.util.AABBi
import ru.dbotthepony.kommons.util.Either
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.world.terrain.AbstractTerrainSelector
@ -336,7 +336,7 @@ class WorldLayout {
val region = buildRegion(random, params)
val subRegion = buildRegion(random, params)
if (!GlobalDefaults.terrestrialWorlds.useSecondaryEnvironmentBiomeIndex) {
if (!Globals.terrestrialWorlds.useSecondaryEnvironmentBiomeIndex) {
region.environmentBiome = primaryEnvironment.environmentBiome
}
@ -387,7 +387,7 @@ class WorldLayout {
}
layer.cells.add(0, layer.cells.last())
val yRange = GlobalDefaults.worldTemplate.playerStartSearchYRange
val yRange = Globals.worldTemplate.playerStartSearchYRange
var i = 0
var lastBoundary = 0

View File

@ -7,7 +7,7 @@ import org.classdump.luna.Table
import org.classdump.luna.lib.ArgumentIterator
import org.classdump.luna.runtime.ExecutionContext
import org.classdump.luna.runtime.LuaFunction
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.RecipeRegistry
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
@ -243,7 +243,7 @@ private fun materialFootstepSound(context: ExecutionContext, arguments: Argument
return
}
context.returnBuffer.setTo(GlobalDefaults.client.defaultFootstepSound.map({ it }, { it.random() }))
context.returnBuffer.setTo(Globals.client.defaultFootstepSound.map({ it }, { it.random() }))
}
private fun materialHealth(context: ExecutionContext, arguments: ArgumentIterator) {

View File

@ -8,6 +8,7 @@ import io.netty.channel.ChannelOption
import io.netty.channel.nio.NioEventLoopGroup
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.cancel
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.io.StreamCodec
@ -19,7 +20,7 @@ import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.WarpAction
import ru.dbotthepony.kstarbound.defs.EntityDamageTeam
@ -50,7 +51,8 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType) :
var entityIDRange: IntRange by Delegates.notNull()
private set
val scope = CoroutineScope(Starbound.COROUTINE_EXECUTOR)
var scope: CoroutineScope by Delegates.notNull()
private set
var connectionID: Int = -1
set(value) {
@ -120,6 +122,8 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType) :
}
fun bind(channel: Channel) {
scope = CoroutineScope(channel.eventLoop().asCoroutineDispatcher())
channel.config().setOption(ChannelOption.TCP_NODELAY, true)
this.channel = channel
@ -196,8 +200,8 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType) :
fun trackingTileRegions(): List<AABBi> {
val result = ArrayList<AABBi>()
var mins = Vector2i(windowXMin - GlobalDefaults.client.windowMonitoringBorder, windowYMin - GlobalDefaults.client.windowMonitoringBorder)
var maxs = Vector2i(windowWidth + GlobalDefaults.client.windowMonitoringBorder * 2, windowHeight + GlobalDefaults.client.windowMonitoringBorder * 2)
var mins = Vector2i(windowXMin - Globals.client.windowMonitoringBorder, windowYMin - Globals.client.windowMonitoringBorder)
var maxs = Vector2i(windowWidth + Globals.client.windowMonitoringBorder * 2, windowHeight + Globals.client.windowMonitoringBorder * 2)
if (maxs.x - mins.x > 1000) {
// holy shit

View File

@ -30,33 +30,10 @@ class CelestialRequestPacket(val requests: Collection<Either<Vector2i, Vector3i>
}
override fun play(connection: ServerConnection) {
connection.pushCelestialRequests(requests)
connection.scope.launch {
val responses = ArrayList<Either<CelestialResponsePacket.ChunkData, CelestialResponsePacket.SystemData>>()
for (request in requests) {
if (request.isLeft) {
val chunkPos = request.left()
responses.add(Either.left(connection.server.universe.getChunk(chunkPos)?.toNetwork() ?: continue))
} else {
val systemPos = UniversePos(request.right())
val map = HashMap<Int, CelestialResponsePacket.PlanetData>()
for (planet in connection.server.universe.children(systemPos)) {
val planetData = connection.server.universe.parameters(planet) ?: continue
val children = HashMap<Int, CelestialParameters>()
for (satellite in connection.server.universe.children(planet)) {
children[satellite.satelliteOrbit] = connection.server.universe.parameters(satellite) ?: continue
}
map[planet.planetOrbit] = CelestialResponsePacket.PlanetData(planetData, children)
}
responses.add(Either.right(CelestialResponsePacket.SystemData(systemPos.location, map)))
}
}
connection.send(CelestialResponsePacket(responses))
}
}
}

View File

@ -10,24 +10,27 @@ import kotlinx.coroutines.future.await
import kotlinx.coroutines.launch
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.io.ByteKey
import ru.dbotthepony.kommons.util.Either
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kommons.vector.Vector3i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.WarpAction
import ru.dbotthepony.kstarbound.defs.WarpAlias
import ru.dbotthepony.kstarbound.defs.WorldID
import ru.dbotthepony.kstarbound.defs.world.CelestialParameters
import ru.dbotthepony.kstarbound.defs.world.VisitableWorldParameters
import ru.dbotthepony.kstarbound.network.Connection
import ru.dbotthepony.kstarbound.network.ConnectionSide
import ru.dbotthepony.kstarbound.network.ConnectionType
import ru.dbotthepony.kstarbound.network.IServerPacket
import ru.dbotthepony.kstarbound.network.packets.ClientContextUpdatePacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.CelestialResponsePacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.PlayerWarpResultPacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.ServerDisconnectPacket
import ru.dbotthepony.kstarbound.server.world.ServerWorldTracker
import ru.dbotthepony.kstarbound.server.world.WorldStorage
import ru.dbotthepony.kstarbound.server.world.LegacyWorldStorage
import ru.dbotthepony.kstarbound.server.world.ServerSystemWorld
import ru.dbotthepony.kstarbound.server.world.ServerWorld
import ru.dbotthepony.kstarbound.world.SystemWorldLocation
import ru.dbotthepony.kstarbound.world.UniversePos
@ -183,13 +186,13 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
flyShipQueue.trySend(system to location)
}
// coordinates ship flights between systems
// coordinates ship flight
private suspend fun shipFlightEventLoop() {
shipWorld.sky.startFlying(true, true)
var visited = 0
LOGGER.info("Finding starter world for ${alias()}...")
val params = GlobalDefaults.universeServer.findStarterWorldParameters
val params = Globals.universeServer.findStarterWorldParameters
// visit all since sparsingly trying to find specific world is not healthy performance wise
val found = server.universe.findRandomWorld(params.tries, params.range, visitAll = true, predicate = {
@ -235,6 +238,15 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
shipWorld.sky.stopFlyingAt(ship.location.skyParameters(world))
shipCoordinate = found
run {
val action = ship.location.orbitalAction(world)
orbitalWarpAction = action
for (client in shipWorld.clients) {
client.client.orbitalWarpAction = action
}
}
var currentFlightJob: Job? = null
while (true) {
@ -302,10 +314,66 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
shipWorld.mailbox.execute {
shipWorld.sky.stopFlyingAt(newParams)
}
// this seems to be way too big isn't it?
delay((Globals.universeServer.queuedFlightWaitTime * 1000.0).toLong())
}
}
}
val celestialRequestQueue = Channel<Either<Vector2i, Vector3i>>(capacity = 100)
fun pushCelestialRequests(requests: Iterable<Either<Vector2i, Vector3i>>) {
requests.forEach {
celestialRequestQueue.trySend(it)
}
}
private suspend fun handleCelestialRequests(requests: Collection<Either<Vector2i, Vector3i>>) {
val responses = ArrayList<Either<CelestialResponsePacket.ChunkData, CelestialResponsePacket.SystemData>>()
for (request in requests) {
if (request.isLeft) {
val chunkPos = request.left()
responses.add(Either.left(server.universe.getChunk(chunkPos)?.toNetwork() ?: continue))
} else {
val systemPos = UniversePos(request.right())
val map = HashMap<Int, CelestialResponsePacket.PlanetData>()
for (planet in server.universe.children(systemPos)) {
val planetData = server.universe.parameters(planet) ?: continue
val children = HashMap<Int, CelestialParameters>()
for (satellite in server.universe.children(planet)) {
children[satellite.satelliteOrbit] = server.universe.parameters(satellite) ?: continue
}
map[planet.planetOrbit] = CelestialResponsePacket.PlanetData(planetData, children)
}
responses.add(Either.right(CelestialResponsePacket.SystemData(systemPos.location, map)))
}
}
send(CelestialResponsePacket(responses))
}
// protects from malicious actors
private suspend fun celestialRequestsHandler() {
while (true) {
val next = celestialRequestQueue.receive()
val requests = ArrayList<Either<Vector2i, Vector3i>>()
requests.add(next)
while (true) {
val tryNext = celestialRequestQueue.tryReceive().getOrNull() ?: break
requests.add(tryNext)
}
handleCelestialRequests(requests)
}
}
fun enqueueWarp(destination: WarpAction, deploy: Boolean = false) {
warpQueue.trySend(destination to deploy)
}
@ -377,6 +445,8 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
server.channels.incrementPlayerCount()
if (isLegacy) {
scope.launch { celestialRequestsHandler() }
ServerWorld.load(server, shipChunkSource, WorldID.ShipWorld(uuid!!)).thenAccept {
if (!isConnected || !channel.isOpen) {
LOGGER.warn("$this disconnected before loaded their ShipWorld")

View File

@ -10,7 +10,7 @@ import kotlinx.coroutines.runBlocking
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.util.MailboxExecutorService
import ru.dbotthepony.kommons.vector.Vector3i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.WorldID
import ru.dbotthepony.kstarbound.network.packets.clientbound.UniverseTimeUpdatePacket
@ -83,7 +83,7 @@ sealed class StarboundServer(val root: File) : Closeable {
init {
mailbox.scheduleAtFixedRate(Runnable {
channels.broadcast(UniverseTimeUpdatePacket(universeClock.seconds))
}, GlobalDefaults.universeServer.clockUpdatePacketInterval, GlobalDefaults.universeServer.clockUpdatePacketInterval, TimeUnit.MILLISECONDS)
}, Globals.universeServer.clockUpdatePacketInterval, Globals.universeServer.clockUpdatePacketInterval, TimeUnit.MILLISECONDS)
thread.uncaughtExceptionHandler = Thread.UncaughtExceptionHandler { t, e ->
LOGGER.fatal("Unexpected exception in server execution loop, shutting down", e)

View File

@ -6,15 +6,13 @@ import com.google.gson.JsonObject
import it.unimi.dsi.fastutil.bytes.ByteArrayList
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.io.writeBinaryString
import ru.dbotthepony.kommons.io.writeUUID
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector3i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.world.SystemWorldObjectConfig
import ru.dbotthepony.kstarbound.io.writeStruct2d
@ -34,12 +32,10 @@ import ru.dbotthepony.kstarbound.util.random.staticRandom64
import ru.dbotthepony.kstarbound.world.SystemWorld
import ru.dbotthepony.kstarbound.world.SystemWorldLocation
import ru.dbotthepony.kstarbound.world.UniversePos
import java.io.Closeable
import java.io.DataOutputStream
import java.util.UUID
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.atomic.AtomicBoolean
import java.util.function.Supplier
import kotlin.math.PI
import kotlin.math.cos
@ -118,7 +114,7 @@ class ServerSystemWorld : SystemWorld {
ships.values.forEach { it.client.send(packet) }
}
fun addClient(client: ServerConnection, shipSpeed: Double = GlobalDefaults.systemWorld.clientShip.speed, location: SystemWorldLocation = SystemWorldLocation.Transit): CompletableFuture<ServerShip> {
fun addClient(client: ServerConnection, shipSpeed: Double = Globals.systemWorld.clientShip.speed, location: SystemWorldLocation = SystemWorldLocation.Transit): CompletableFuture<ServerShip> {
val task = Task { addClient0(client, shipSpeed, location) }
tasks.add(task)
return task.future
@ -150,8 +146,8 @@ class ServerSystemWorld : SystemWorld {
private constructor(server: StarboundServer, location: Vector3i) : super(location, server.universeClock, server.universe) {
this.server = server
this.lastSpawn = clock.seconds - GlobalDefaults.systemWorld.objectSpawnCycle
objectSpawnTime = random.nextRange(GlobalDefaults.systemWorld.objectSpawnInterval)
this.lastSpawn = clock.seconds - Globals.systemWorld.objectSpawnCycle
objectSpawnTime = random.nextRange(Globals.systemWorld.objectSpawnInterval)
}
private constructor(server: StarboundServer, data: JsonData) : super(data.location, server.universeClock, server.universe) {
@ -168,11 +164,11 @@ class ServerSystemWorld : SystemWorld {
private suspend fun spawnInitialObjects() {
val random = random(staticRandom64("SystemWorldGeneration", location.toString()))
GlobalDefaults.systemWorld.initialObjectPools.sample(random).ifPresent {
Globals.systemWorld.initialObjectPools.sample(random).ifPresent {
for (i in 0 until it.first) {
val name = it.second.sample(random).orNull() ?: return@ifPresent
val uuid = UUID(random.nextLong(), random.nextLong())
val prototype = GlobalDefaults.systemObjects[name] ?: throw NullPointerException("Tried to create $name system world object, but there is no such object in /system_objects.config!")
val prototype = Globals.systemObjects[name] ?: throw NullPointerException("Tried to create $name system world object, but there is no such object in /system_objects.config!")
val create = ServerEntity(prototype.create(uuid, name), uuid, randomObjectSpawnPosition(), clock.seconds)
create.enterOrbit(UniversePos(location), Vector2d.ZERO, clock.seconds) // orbit center of system
}
@ -180,17 +176,17 @@ class ServerSystemWorld : SystemWorld {
}
private suspend fun spawnObjects() {
var diff = GlobalDefaults.systemWorld.objectSpawnCycle.coerceAtMost(clock.seconds - lastSpawn)
var diff = Globals.systemWorld.objectSpawnCycle.coerceAtMost(clock.seconds - lastSpawn)
lastSpawn = clock.seconds - diff
while (diff > objectSpawnTime) {
lastSpawn += objectSpawnTime
objectSpawnTime = random.nextRange(GlobalDefaults.systemWorld.objectSpawnInterval)
objectSpawnTime = random.nextRange(Globals.systemWorld.objectSpawnInterval)
diff = clock.seconds - lastSpawn
GlobalDefaults.systemWorld.objectSpawnPool.sample(random).ifPresent {
Globals.systemWorld.objectSpawnPool.sample(random).ifPresent {
val uuid = UUID(random.nextLong(), random.nextLong())
val config = GlobalDefaults.systemObjects[it]?.create(uuid, it) ?: throw NullPointerException("Tried to create $it system world object, but there is no such object in /system_objects.config!")
val config = Globals.systemObjects[it]?.create(uuid, it) ?: throw NullPointerException("Tried to create $it system world object, but there is no such object in /system_objects.config!")
val pos = randomObjectSpawnPosition()
if (clock.seconds > lastSpawn + objectSpawnTime && config.moving) {
@ -219,8 +215,8 @@ class ServerSystemWorld : SystemWorld {
val orbits = universe.children(systemLocation)
suspend fun addSpawn(inner: UniversePos, outer: UniversePos) {
val min = planetOrbitDistance(inner) + clusterSize(inner) / 2.0 + GlobalDefaults.systemWorld.objectSpawnPadding
val max = planetOrbitDistance(outer) - clusterSize(outer) / 2.0 - GlobalDefaults.systemWorld.objectSpawnPadding
val min = planetOrbitDistance(inner) + clusterSize(inner) / 2.0 + Globals.systemWorld.objectSpawnPadding
val max = planetOrbitDistance(outer) - clusterSize(outer) / 2.0 - Globals.systemWorld.objectSpawnPadding
spawnRanges.add(Vector2d(min, max))
}
@ -230,8 +226,8 @@ class ServerSystemWorld : SystemWorld {
addSpawn(orbits[i - 1], orbits[i])
val outer = orbits.last()
val rim = planetOrbitDistance(outer) + clusterSize(outer) / 2.0 + GlobalDefaults.systemWorld.objectSpawnPadding
spawnRanges.add(Vector2d(rim, rim + GlobalDefaults.systemWorld.objectSpawnPadding))
val rim = planetOrbitDistance(outer) + clusterSize(outer) / 2.0 + Globals.systemWorld.objectSpawnPadding
spawnRanges.add(Vector2d(rim, rim + Globals.systemWorld.objectSpawnPadding))
val range = spawnRanges.random(random)
val angle = random.nextDouble() * PI * 2.0
@ -308,7 +304,7 @@ class ServerSystemWorld : SystemWorld {
suspend fun nearPlanetOrbit(planet: UniversePos): Orbit {
val toShip = planetPosition(planet) - position
val angle = toShip.toAngle()
return Orbit(planet, 1, clock.seconds, Vector2d(cos(angle), sin(angle)) * (planetSize(planet) / 2.0 + GlobalDefaults.systemWorld.clientShip.orbitDistance))
return Orbit(planet, 1, clock.seconds, Vector2d(cos(angle), sin(angle)) * (planetSize(planet) / 2.0 + Globals.systemWorld.clientShip.orbitDistance))
}
if (location is SystemWorldLocation.Celestial) {
@ -390,9 +386,9 @@ class ServerSystemWorld : SystemWorld {
destinationFuture = future
if (location is SystemWorldLocation.Celestial || location is SystemWorldLocation.Entity)
departTimer = GlobalDefaults.systemWorld.clientShip.departTime
departTimer = Globals.systemWorld.clientShip.departTime
else if (destination == SystemWorldLocation.Transit)
departTimer = GlobalDefaults.systemWorld.clientShip.spaceDepartTime
departTimer = Globals.systemWorld.clientShip.spaceDepartTime
this.destination = destination
this.location = SystemWorldLocation.Transit
@ -412,7 +408,7 @@ class ServerSystemWorld : SystemWorld {
inner class ServerEntity(data: SystemWorldObjectConfig.Data, uuid: UUID, position: Vector2d, spawnTime: Double = 0.0, parameters: JsonObject = JsonObject()) : Entity(data, uuid, position, spawnTime, parameters) {
constructor(data: EntityJsonData) : this(
GlobalDefaults.systemObjects[data.name]?.create(data.actualUUID, data.name) ?: throw NullPointerException("Tried to create ${data.name} system world object, but there is no such object in /system_objects.config!"),
Globals.systemObjects[data.name]?.create(data.actualUUID, data.name) ?: throw NullPointerException("Tried to create ${data.name} system world object, but there is no such object in /system_objects.config!"),
data.actualUUID,
data.position,
data.spawnTime,

View File

@ -3,8 +3,6 @@ package ru.dbotthepony.kstarbound.server.world
import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine
import com.github.benmanes.caffeine.cache.Scheduler
import com.google.gson.stream.JsonReader
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
import it.unimi.dsi.fastutil.objects.ObjectArrayList
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
import kotlinx.coroutines.future.await
@ -14,21 +12,17 @@ import ru.dbotthepony.kommons.io.BTreeDB6
import ru.dbotthepony.kommons.util.AABBi
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.world.CelestialBaseInformation
import ru.dbotthepony.kstarbound.defs.world.CelestialGenerationInformation
import ru.dbotthepony.kstarbound.defs.world.CelestialNames
import ru.dbotthepony.kstarbound.defs.world.CelestialConfig
import ru.dbotthepony.kstarbound.defs.world.CelestialParameters
import ru.dbotthepony.kstarbound.fromJson
import ru.dbotthepony.kstarbound.io.BTreeDB5
import ru.dbotthepony.kstarbound.util.random.nextRange
import ru.dbotthepony.kstarbound.util.random.random
import ru.dbotthepony.kstarbound.util.random.staticRandom64
import ru.dbotthepony.kstarbound.world.Universe
import ru.dbotthepony.kstarbound.world.UniversePos
import java.io.Closeable
import java.io.File
import java.io.InputStreamReader
import java.time.Duration
import java.util.concurrent.CompletableFuture
import kotlin.collections.ArrayList
@ -63,8 +57,10 @@ class ServerUniverse private constructor(marker: Nothing?) : Universe(), Closeab
}
override val baseInformation: CelestialBaseInformation
val generationInformation: CelestialGenerationInformation
val celestialNames: CelestialNames
get() = Globals.celestialBaseInformation
val generationInformation: CelestialConfig
get() = Globals.celestialConfig
private val sources = ArrayList<UniverseSource>()
private val closeables = ArrayList<Closeable>()
@ -236,23 +232,6 @@ class ServerUniverse private constructor(marker: Nothing?) : Universe(), Closeab
}
}
init {
val celestial = Starbound.read("/celestial.config")
val stream0 = JsonReader(InputStreamReader(FastByteArrayInputStream(celestial.array())))
val stream1 = JsonReader(InputStreamReader(FastByteArrayInputStream(celestial.array())))
stream0.isLenient = true
stream1.isLenient = true
baseInformation = Starbound.gson.fromJson(stream0)!!
generationInformation = Starbound.gson.fromJson(stream1)!!
if (!generationInformation.systemTypePerlin.hasSeedSpecified)
generationInformation.systemTypePerlin.init(staticRandom64("SystemTypePerlin"))
celestialNames = Starbound.gson.fromJson(Starbound.jsonReader("/celestial/names.config"))!!
}
override val region: AABBi = AABBi(Vector2i(baseInformation.xyCoordRange.x, baseInformation.xyCoordRange.x), Vector2i(baseInformation.xyCoordRange.y, baseInformation.xyCoordRange.y))
}

View File

@ -16,6 +16,7 @@ import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kommons.vector.Vector3i
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.world.CelestialParameters
import ru.dbotthepony.kstarbound.io.BTreeDB5
@ -25,6 +26,7 @@ import ru.dbotthepony.kstarbound.json.writeJsonElement
import ru.dbotthepony.kstarbound.math.Line2d
import ru.dbotthepony.kstarbound.util.binnedChoice
import ru.dbotthepony.kstarbound.util.paddedNumber
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise
import ru.dbotthepony.kstarbound.util.random.random
import ru.dbotthepony.kstarbound.util.random.staticRandom64
import ru.dbotthepony.kstarbound.world.UniversePos
@ -163,8 +165,16 @@ class NativeUniverseSource(private val db: BTreeDB6?, private val universe: Serv
}
}
private val systemPerlin = AbstractPerlinNoise.of(universe.generationInformation.systemTypePerlin)
init {
if (!systemPerlin.hasSeedSpecified) {
systemPerlin.init(staticRandom64("SystemTypePerlin"))
}
}
private fun generateSystem(random: RandomGenerator, location: Vector3i): UniverseChunk.System? {
val typeSelector = universe.generationInformation.systemTypePerlin[location.x.toDouble(), location.y.toDouble()]
val typeSelector = systemPerlin[location.x.toDouble(), location.y.toDouble()]
val type = universe.generationInformation.systemTypeBins
.stream()
@ -177,9 +187,9 @@ class NativeUniverseSource(private val db: BTreeDB6?, private val universe: Serv
val systemPos = UniversePos(location)
val systemSeed = random.nextLong()
val prefix = universe.celestialNames.systemPrefixNames.sample(random).orElse("")
val mid = universe.celestialNames.systemNames.sample(random).orElse("missingsystemname $location")
val suffix = universe.celestialNames.systemSuffixNames.sample(random).orElse("")
val prefix = Globals.celestialNames.systemPrefixNames.sample(random).orElse("")
val mid = Globals.celestialNames.systemNames.sample(random).orElse("missingsystemname $location")
val suffix = Globals.celestialNames.systemSuffixNames.sample(random).orElse("")
val systemName = "$prefix $mid $suffix".trim()
.replace("<onedigit>", random.nextInt(0, 10).toString())
@ -221,7 +231,7 @@ class NativeUniverseSource(private val db: BTreeDB6?, private val universe: Serv
val planetCoordinate = UniversePos(location, planetOrbitIndex)
val planetSeed = random.nextLong()
val planetName = "$systemName ${universe.celestialNames.planetarySuffixes[planetOrbitIndex]}"
val planetName = "$systemName ${Globals.celestialNames.planetarySuffixes[planetOrbitIndex]}"
val planetParams = CelestialParameters(
planetCoordinate,
@ -240,7 +250,7 @@ class NativeUniverseSource(private val db: BTreeDB6?, private val universe: Serv
if (!satelliteTypeO.isPresent) continue
val satelliteType = satelliteTypeO.value
val satelliteSeed = random.nextLong()
val satelliteName = "$planetName ${universe.celestialNames.satelliteSuffixes[satellites.size]}"
val satelliteName = "$planetName ${Globals.celestialNames.satelliteSuffixes[satellites.size]}"
val satelliteCoordinate = UniversePos(location, planetOrbitIndex, satelliteOrbitIndex)
val merge = JsonObject()

View File

@ -7,7 +7,7 @@ import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.world.FlyingType
import ru.dbotthepony.kstarbound.defs.world.SkyGlobalConfig
@ -75,17 +75,17 @@ class Sky() {
val speedupTime: Double get() {
if (enterHyperspace) {
return GlobalDefaults.sky.hyperspaceSpeedupTime.coerceAtLeast(0.01)
return Globals.sky.hyperspaceSpeedupTime.coerceAtLeast(0.01)
} else {
return GlobalDefaults.sky.speedupTime.coerceAtLeast(0.01)
return Globals.sky.speedupTime.coerceAtLeast(0.01)
}
}
val slowdownTime: Double get() {
if (enterHyperspace) {
return GlobalDefaults.sky.hyperspaceSlowdownTime.coerceAtLeast(0.01)
return Globals.sky.hyperspaceSlowdownTime.coerceAtLeast(0.01)
} else {
return GlobalDefaults.sky.slowdownTime.coerceAtLeast(0.01)
return Globals.sky.slowdownTime.coerceAtLeast(0.01)
}
}
@ -138,8 +138,8 @@ class Sky() {
lastWarpPhase = warpPhase
}
worldMoveOffset = Vector2d(cos(pathRotation), sin(pathRotation)) * GlobalDefaults.sky.flyMaxVelocity / 2.0 * speedupTime
starMoveOffset = Vector2d(x = GlobalDefaults.sky.flyMaxVelocity * GlobalDefaults.sky.starVelocityFactor / 2.0 * speedupTime)
worldMoveOffset = Vector2d(cos(pathRotation), sin(pathRotation)) * Globals.sky.flyMaxVelocity / 2.0 * speedupTime
starMoveOffset = Vector2d(x = Globals.sky.flyMaxVelocity * Globals.sky.starVelocityFactor / 2.0 * speedupTime)
} else if (flyingType == FlyingType.ARRIVING) {
sentSFX = false
worldOffset = Vector2d.ZERO
@ -156,17 +156,17 @@ class Sky() {
//flashTimer = GlobalDefaults.sky.flashTimer
sentSFX = false
val origin = if (skyType == SkyType.SPACE) GlobalDefaults.sky.spaceArrivalOrigin else GlobalDefaults.sky.arrivalOrigin
val path = if (skyType == SkyType.SPACE) GlobalDefaults.sky.spaceArrivalPath else GlobalDefaults.sky.arrivalPath
val origin = if (skyType == SkyType.SPACE) Globals.sky.spaceArrivalOrigin else Globals.sky.arrivalOrigin
val path = if (skyType == SkyType.SPACE) Globals.sky.spaceArrivalPath else Globals.sky.arrivalPath
pathOffset = origin.offset
pathRotation = origin.rotationRad
var exitDistance = GlobalDefaults.sky.flyMaxVelocity / 2.0 * slowdownTime
var exitDistance = Globals.sky.flyMaxVelocity / 2.0 * slowdownTime
worldMoveOffset = Vector2d(x = exitDistance)
worldOffset = worldMoveOffset
exitDistance *= GlobalDefaults.sky.starVelocityFactor
exitDistance *= Globals.sky.starVelocityFactor
starMoveOffset = Vector2d(x = exitDistance)
starOffset = starMoveOffset
@ -202,25 +202,25 @@ class Sky() {
if (flyingType == FlyingType.DISEMBARKING) {
val finished = if (skyParametersNetState.value.skyType == SkyType.SPACE)
controlledMovement(GlobalDefaults.sky.spaceDisembarkPath, GlobalDefaults.sky.spaceDisembarkOrigin, flyingTimer)
controlledMovement(Globals.sky.spaceDisembarkPath, Globals.sky.spaceDisembarkOrigin, flyingTimer)
else
controlledMovement(GlobalDefaults.sky.disembarkPath, GlobalDefaults.sky.disembarkOrigin, flyingTimer)
controlledMovement(Globals.sky.disembarkPath, Globals.sky.disembarkOrigin, flyingTimer)
if (finished) {
flyingType = FlyingType.WARP
}
} else if (flyingType == FlyingType.ARRIVING) {
val finished = if (skyParametersNetState.value.skyType == SkyType.SPACE)
controlledMovement(GlobalDefaults.sky.spaceArrivalPath, GlobalDefaults.sky.spaceArrivalOrigin, flyingTimer)
controlledMovement(Globals.sky.spaceArrivalPath, Globals.sky.spaceArrivalOrigin, flyingTimer)
else
controlledMovement(GlobalDefaults.sky.arrivalPath, GlobalDefaults.sky.arrivalOrigin, flyingTimer)
controlledMovement(Globals.sky.arrivalPath, Globals.sky.arrivalOrigin, flyingTimer)
if (finished) {
flyingType = FlyingType.NONE
}
starOffset -= starOffset * GlobalDefaults.sky.correctionPower
worldOffset -= worldOffset * GlobalDefaults.sky.correctionPower
starOffset -= starOffset * Globals.sky.correctionPower
worldOffset -= worldOffset * Globals.sky.correctionPower
} else if (flyingType == FlyingType.WARP) {
val percentage = when (warpPhase) {
WarpPhase.SLOWING_DOWN -> (flyingTimer / speedupTime).pow(2.0)
@ -235,7 +235,7 @@ class Sky() {
} else {
val angle = -(starRotation + pathRotation)
val angleVec = Vector2d(cos(angle), sin(angle))
starOffset += angleVec * GlobalDefaults.sky.flyMaxVelocity * delta * GlobalDefaults.sky.starVelocityFactor
starOffset += angleVec * Globals.sky.flyMaxVelocity * delta * Globals.sky.starVelocityFactor
worldOffset = worldMoveOffset
}
@ -245,7 +245,7 @@ class Sky() {
warpPhase = WarpPhase.SLOWING_DOWN
} else if (warpPhase == WarpPhase.SPEEDING_UP && flyingTimer >= speedupTime && enterHyperspace) {
warpPhase = WarpPhase.MAINTAIN
} else if (warpPhase == WarpPhase.MAINTAIN && flyingTimer >= GlobalDefaults.sky.flyingTimer && destination != null) {
} else if (warpPhase == WarpPhase.MAINTAIN && flyingTimer >= Globals.sky.flyingTimer && destination != null) {
skyParametersNetState.value = destination!!
destination = null
warpPhase = WarpPhase.SLOWING_DOWN

View File

@ -1,25 +1,19 @@
package ru.dbotthepony.kstarbound.world
import com.google.gson.JsonObject
import kotlinx.coroutines.CoroutineScope
import ru.dbotthepony.kommons.io.koptional
import ru.dbotthepony.kommons.io.writeBinaryString
import ru.dbotthepony.kommons.io.writeUUID
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector3i
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.world.FloatingDungeonWorldParameters
import ru.dbotthepony.kstarbound.defs.world.SystemWorldObjectConfig
import ru.dbotthepony.kstarbound.io.readDouble
import ru.dbotthepony.kstarbound.io.readVector2d
import ru.dbotthepony.kstarbound.io.writeDouble
import ru.dbotthepony.kstarbound.io.writeStruct2d
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.json.writeJsonObject
import ru.dbotthepony.kstarbound.math.Interpolator
import ru.dbotthepony.kstarbound.network.syncher.MasterElement
import ru.dbotthepony.kstarbound.network.syncher.NetworkedGroup
@ -61,9 +55,9 @@ abstract class SystemWorld(val location: Vector3i, val clock: Clock, val univers
}
if (coordinate.isPlanet)
distance += random.nextFloat(GlobalDefaults.systemWorld.planetaryOrbitPadding.x.toFloat(), GlobalDefaults.systemWorld.planetaryOrbitPadding.y.toFloat())
distance += random.nextFloat(Globals.systemWorld.planetaryOrbitPadding.x.toFloat(), Globals.systemWorld.planetaryOrbitPadding.y.toFloat())
else if (coordinate.isSatellite)
distance += random.nextFloat(GlobalDefaults.systemWorld.satelliteOrbitPadding.x.toFloat(), GlobalDefaults.systemWorld.satelliteOrbitPadding.y.toFloat())
distance += random.nextFloat(Globals.systemWorld.satelliteOrbitPadding.x.toFloat(), Globals.systemWorld.satelliteOrbitPadding.y.toFloat())
}
distance += clusterSize(coordinate) / 2.0
@ -87,10 +81,10 @@ abstract class SystemWorld(val location: Vector3i, val clock: Clock, val univers
suspend fun planetSize(coordinate: UniversePos): Double {
if (coordinate.isSystem)
return GlobalDefaults.systemWorld.starSize
return Globals.systemWorld.starSize
if (!universe.children(coordinate.parent()).any { it.orbitNumber == coordinate.orbitNumber })
return GlobalDefaults.systemWorld.emptyOrbitSize
return Globals.systemWorld.emptyOrbitSize
val parameters = universe.parameters(coordinate)
@ -101,14 +95,14 @@ abstract class SystemWorld(val location: Vector3i, val clock: Clock, val univers
var size = 0.0
if (visitable is FloatingDungeonWorldParameters) {
val getSize = GlobalDefaults.systemWorld.floatingDungeonWorldSizes[visitable.typeName]
val getSize = Globals.systemWorld.floatingDungeonWorldSizes[visitable.typeName]
if (getSize != null) {
return getSize
}
}
for ((planetSize, orbitSize) in GlobalDefaults.systemWorld.planetSizes) {
for ((planetSize, orbitSize) in Globals.systemWorld.planetSizes) {
if (visitable.worldSize.x >= planetSize)
size = orbitSize
else
@ -119,11 +113,11 @@ abstract class SystemWorld(val location: Vector3i, val clock: Clock, val univers
}
}
return GlobalDefaults.systemWorld.unvisitablePlanetSize
return Globals.systemWorld.unvisitablePlanetSize
}
fun orbitInterval(distance: Double, isSatellite: Boolean): Double {
val gravityConstant = if (isSatellite) GlobalDefaults.systemWorld.planetGravitationalConstant else GlobalDefaults.systemWorld.starGravitationalConstant
val gravityConstant = if (isSatellite) Globals.systemWorld.planetGravitationalConstant else Globals.systemWorld.starGravitationalConstant
return distance * 2.0 * PI / sqrt(gravityConstant / distance)
}
@ -171,7 +165,7 @@ abstract class SystemWorld(val location: Vector3i, val clock: Clock, val univers
}
fun randomArrivalPosition(): Vector2d {
val range = random.nextRange(GlobalDefaults.systemWorld.arrivalRange)
val range = random.nextRange(Globals.systemWorld.arrivalRange)
val angle = random.nextDouble(0.0, PI * 2.0)
return Vector2d(cos(angle), sin(angle)) * range
}
@ -210,7 +204,7 @@ abstract class SystemWorld(val location: Vector3i, val clock: Clock, val univers
}
abstract inner class Ship(val uuid: UUID, location: SystemWorldLocation) {
var speed = GlobalDefaults.systemWorld.clientShip.speed
var speed = Globals.systemWorld.clientShip.speed
var departTimer = 0.0
val networkGroup = MasterElement(NetworkedGroup())
@ -239,7 +233,7 @@ abstract class SystemWorld(val location: Vector3i, val clock: Clock, val univers
abstract inner class Entity(val data: SystemWorldObjectConfig.Data, val uuid: UUID, position: Vector2d, val spawnTime: Double = 0.0, val parameters: JsonObject = JsonObject()) {
constructor(data: EntityJsonData) : this(
GlobalDefaults.systemObjects[data.name]?.create(data.actualUUID, data.name) ?: throw NullPointerException("Tried to create ${data.name} system world object, but there is no such object in /system_objects.config!"),
Globals.systemObjects[data.name]?.create(data.actualUUID, data.name) ?: throw NullPointerException("Tried to create ${data.name} system world object, but there is no such object in /system_objects.config!"),
data.actualUUID,
data.position,
data.spawnTime,

View File

@ -1,21 +1,23 @@
package ru.dbotthepony.kstarbound.world
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kommons.io.readUUID
import ru.dbotthepony.kommons.io.writeUUID
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.SpawnTarget
import ru.dbotthepony.kstarbound.defs.WarpAction
import ru.dbotthepony.kstarbound.defs.WarpMode
import ru.dbotthepony.kstarbound.defs.WorldID
import ru.dbotthepony.kstarbound.defs.world.AsteroidsWorldParameters
import ru.dbotthepony.kstarbound.defs.world.SkyParameters
import ru.dbotthepony.kstarbound.defs.world.SkyType
import ru.dbotthepony.kstarbound.io.readVector2d
import ru.dbotthepony.kstarbound.io.writeStruct2d
import ru.dbotthepony.kstarbound.network.syncher.legacyCodec
import ru.dbotthepony.kstarbound.network.syncher.nativeCodec
import ru.dbotthepony.kstarbound.util.random.random
import ru.dbotthepony.kstarbound.util.random.staticRandom64
import java.io.DataInputStream
import java.io.DataOutputStream
import java.util.UUID
@ -28,8 +30,32 @@ sealed class SystemWorldLocation {
abstract suspend fun orbitalAction(system: SystemWorld): KOptional<Pair<WarpAction, WarpMode>>
abstract suspend fun skyParameters(system: SystemWorld): SkyParameters
protected suspend fun appendParameters(parameters: SkyParameters, system: SystemWorld) {
protected suspend fun appendParameters(parameters: SkyParameters, system: SystemWorld, orbit: UniversePos): SkyParameters {
val planets = ArrayList<UniversePos>()
// in original code, they only append nearby planet list only if we are orbiting a planet,
// and not a satellite. So let's fix that!
if (orbit.isSatellite) {
planets.add(orbit.parent())
planets.addAll(system.universe.children(orbit.parent()))
} else if (orbit.isPlanet) {
planets.add(orbit)
planets.addAll(system.universe.children(orbit))
}
val random = random(staticRandom64(orbit.toString()))
val satellites = ArrayList(parameters.satellites)
for (body in planets) {
val pos = Vector2d(random.nextDouble(), random.nextDouble())
val bodyParams = system.universe.parameters(body) ?: continue
satellites.add(SkyParameters.Planet(pos, ImmutableList.copyOf(SkyParameters.drawWorld(bodyParams))))
}
parameters.satellites = ImmutableList.copyOf(satellites)
return parameters
}
object Transit : SystemWorldLocation() {
@ -46,7 +72,7 @@ sealed class SystemWorldLocation {
}
override suspend fun skyParameters(system: SystemWorld): SkyParameters {
return GlobalDefaults.systemWorld.emptySkyParameters
return Globals.systemWorld.emptySkyParameters
}
}
@ -86,11 +112,10 @@ sealed class SystemWorldLocation {
}
override suspend fun skyParameters(system: SystemWorld): SkyParameters {
if (position.target.isPlanet) {
}
return GlobalDefaults.systemWorld.emptySkyParameters
// original code here is different,
// since it is assumed we can't "outer" orbit satellites
// (but that is still technically possible to outer-orbit a satellite)
return appendParameters(Globals.systemWorld.emptySkyParameters.copy(), system, position.target)
}
}
@ -110,8 +135,20 @@ sealed class SystemWorldLocation {
}
override suspend fun skyParameters(system: SystemWorld): SkyParameters {
val get = system.entities[uuid] ?: return GlobalDefaults.systemWorld.emptySkyParameters
return get.data.skyParameters
val get = system.entities[uuid] ?: return Globals.systemWorld.emptySkyParameters
val orbit = get.orbit.orNull()?.target
var sky = get.data.skyParameters
// original code here is slightly different again,
// if entity is orbiting a satellite, it won't add planets and
// its satellites to sky parameters
if (orbit != null && !orbit.isSystem) {
sky = sky.copy()
appendParameters(sky, system, orbit)
}
return sky
}
}
@ -128,7 +165,7 @@ sealed class SystemWorldLocation {
override suspend fun orbitalAction(system: SystemWorld): KOptional<Pair<WarpAction, WarpMode>> {
// player can beam to asteroid fields simply by being in proximity to them
for (child in system.universe.children(system.systemLocation)) {
if ((system.planetPosition(child).length - position.length).absoluteValue > GlobalDefaults.systemWorld.asteroidBeamDistance) {
if ((system.planetPosition(child).length - position.length).absoluteValue > Globals.systemWorld.asteroidBeamDistance) {
continue
}
@ -146,7 +183,7 @@ sealed class SystemWorldLocation {
override suspend fun skyParameters(system: SystemWorld): SkyParameters {
for (child in system.universe.children(system.systemLocation)) {
if ((system.planetPosition(child).length - position.length).absoluteValue > GlobalDefaults.systemWorld.asteroidBeamDistance) {
if ((system.planetPosition(child).length - position.length).absoluteValue > Globals.systemWorld.asteroidBeamDistance) {
continue
}
@ -158,7 +195,7 @@ sealed class SystemWorldLocation {
}
}
return GlobalDefaults.systemWorld.emptySkyParameters
return Globals.systemWorld.emptySkyParameters
}
}

View File

@ -5,7 +5,7 @@ import ru.dbotthepony.kommons.guava.immutableMap
import ru.dbotthepony.kommons.io.readVarInt
import ru.dbotthepony.kommons.io.writeBinaryString
import ru.dbotthepony.kommons.io.writeVarInt
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.actor.EquipmentSlot
import ru.dbotthepony.kstarbound.item.ItemStack
import ru.dbotthepony.kstarbound.io.readInternedString
@ -101,7 +101,7 @@ sealed class InventoryIndex {
companion object {
private val bagIndexCache by lazy {
immutableMap {
GlobalDefaults.player.inventory.itemBags.keys.forEach { n ->
Globals.player.inventory.itemBags.keys.forEach { n ->
put(n, immutableList(256) {
BagIndex(n, it)
})

View File

@ -1,15 +1,12 @@
package ru.dbotthepony.kstarbound.world.entities.player
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import it.unimi.dsi.fastutil.bytes.ByteArrayList
import ru.dbotthepony.kommons.io.writeBinaryString
import ru.dbotthepony.kommons.util.AABB
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.EntityDamageTeam
import ru.dbotthepony.kstarbound.defs.EntityType
import ru.dbotthepony.kstarbound.defs.actor.HumanoidData
@ -19,8 +16,6 @@ import ru.dbotthepony.kstarbound.io.readInternedString
import ru.dbotthepony.kstarbound.json.JsonPath
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
import ru.dbotthepony.kstarbound.math.Interpolator
import ru.dbotthepony.kstarbound.network.syncher.NetworkedGroup
import ru.dbotthepony.kstarbound.network.syncher.MasterElement
import ru.dbotthepony.kstarbound.network.syncher.networkedBoolean
import ru.dbotthepony.kstarbound.network.syncher.networkedData
import ru.dbotthepony.kstarbound.network.syncher.networkedEnum
@ -80,8 +75,8 @@ class PlayerEntity() : HumanoidActorEntity("/") {
val inventory = PlayerInventory()
val songbook = Songbook(this)
val effectAnimator = if (GlobalDefaults.player.effectsAnimator.value == null) Animator() else Animator(GlobalDefaults.player.effectsAnimator.value!!)
override val statusController = StatusController(this, GlobalDefaults.player.statusControllerSettings)
val effectAnimator = if (Globals.player.effectsAnimator.value == null) Animator() else Animator(Globals.player.effectsAnimator.value!!)
override val statusController = StatusController(this, Globals.player.statusControllerSettings)
val techController = TechController(this)
var state by networkGroup.upstream.add(networkedEnum(State.IDLE))
@ -126,7 +121,7 @@ class PlayerEntity() : HumanoidActorEntity("/") {
if (fixturesChangeset != movement.fixturesChangeset) {
fixturesChangeset = movement.fixturesChangeset
metaFixture!!.move(GlobalDefaults.player.metaBoundBox + position)
metaFixture!!.move(Globals.player.metaBoundBox + position)
}
}

View File

@ -1,20 +1,16 @@
package ru.dbotthepony.kstarbound.world.entities.player
import com.google.common.collect.ImmutableMap
import it.unimi.dsi.fastutil.objects.Object2LongAVLTreeMap
import ru.dbotthepony.kommons.arrays.Object2DArray
import ru.dbotthepony.kommons.guava.immutableList
import ru.dbotthepony.kommons.io.BinaryStringCodec
import ru.dbotthepony.kommons.io.LongValueCodec
import ru.dbotthepony.kommons.io.StreamCodec
import ru.dbotthepony.kommons.io.UnsignedVarLongCodec
import ru.dbotthepony.kommons.io.VarLongValueCodec
import ru.dbotthepony.kommons.io.readKOptional
import ru.dbotthepony.kommons.io.writeKOptional
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kstarbound.GlobalDefaults
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.defs.actor.EquipmentSlot
import ru.dbotthepony.kstarbound.defs.actor.EssentialSlot
import ru.dbotthepony.kstarbound.item.ItemStack
@ -65,7 +61,7 @@ class PlayerInventory {
// if bags have same priority, PlayerInventory behavior becomes undefined
// We, on the other hand, use stable sort provided by Java
// (and if bags have the same priority they will appear in order they are defined in json)
val bags: ImmutableMap<String, Bag> = GlobalDefaults.player.inventory.itemBags.entries
val bags: ImmutableMap<String, Bag> = Globals.player.inventory.itemBags.entries
.stream()
.sorted { o1, o2 -> o1.value.priority.compareTo(o2.value.priority) }
.map { it.key to Bag(it.value.size) }
@ -88,7 +84,7 @@ class PlayerInventory {
// because otherwise
// it will throw "element not found"
// when trying to update currencies
for (key in GlobalDefaults.currencies.keys) {
for (key in Globals.currencies.keys) {
currencies[key] = 0L
}
}
@ -130,7 +126,7 @@ class PlayerInventory {
}
var hotbarGroup by networkGroup.add(networkedUnsignedInt())
val hotbarSlots = Object2DArray(GlobalDefaults.player.inventory.customBarIndexes, GlobalDefaults.player.inventory.customBarGroups) { _, _ ->
val hotbarSlots = Object2DArray(Globals.player.inventory.customBarIndexes, Globals.player.inventory.customBarGroups) { _, _ ->
networkedData(HotbarSlot(), HotbarSlot.CODEC, HotbarSlot.LEGACY_CODEC)
}