Make worlds be capable of loading from disk, and capable of sending to legacy clients
This commit is contained in:
parent
6df7710dc2
commit
0c60dd6a02
@ -105,7 +105,7 @@ fun main() {
|
|||||||
Starbound.mailboxInitialized.submit {
|
Starbound.mailboxInitialized.submit {
|
||||||
val server = IntegratedStarboundServer(File("./"))
|
val server = IntegratedStarboundServer(File("./"))
|
||||||
val world = ServerWorld.load(server, LegacyWorldStorage.file(db)).get()
|
val world = ServerWorld.load(server, LegacyWorldStorage.file(db)).get()
|
||||||
//world.thread.start()
|
world.thread.start()
|
||||||
|
|
||||||
//ply = PlayerEntity(client.world!!)
|
//ply = PlayerEntity(client.world!!)
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ import ru.dbotthepony.kstarbound.defs.world.VisitableWorldParametersType
|
|||||||
import ru.dbotthepony.kstarbound.defs.world.BiomePlaceables
|
import ru.dbotthepony.kstarbound.defs.world.BiomePlaceables
|
||||||
import ru.dbotthepony.kstarbound.defs.world.BiomePlacementDistributionType
|
import ru.dbotthepony.kstarbound.defs.world.BiomePlacementDistributionType
|
||||||
import ru.dbotthepony.kstarbound.defs.world.BiomePlacementItemType
|
import ru.dbotthepony.kstarbound.defs.world.BiomePlacementItemType
|
||||||
|
import ru.dbotthepony.kstarbound.defs.world.WorldLayout
|
||||||
import ru.dbotthepony.kstarbound.world.terrain.TerrainSelectorType
|
import ru.dbotthepony.kstarbound.world.terrain.TerrainSelectorType
|
||||||
import ru.dbotthepony.kstarbound.io.*
|
import ru.dbotthepony.kstarbound.io.*
|
||||||
import ru.dbotthepony.kstarbound.json.factory.MapsTypeAdapterFactory
|
import ru.dbotthepony.kstarbound.json.factory.MapsTypeAdapterFactory
|
||||||
@ -58,6 +59,7 @@ import ru.dbotthepony.kstarbound.json.factory.SingletonTypeAdapterFactory
|
|||||||
import ru.dbotthepony.kstarbound.math.*
|
import ru.dbotthepony.kstarbound.math.*
|
||||||
import ru.dbotthepony.kstarbound.server.world.UniverseChunk
|
import ru.dbotthepony.kstarbound.server.world.UniverseChunk
|
||||||
import ru.dbotthepony.kstarbound.item.ItemStack
|
import ru.dbotthepony.kstarbound.item.ItemStack
|
||||||
|
import ru.dbotthepony.kstarbound.json.NativeLegacy
|
||||||
import ru.dbotthepony.kstarbound.util.Directives
|
import ru.dbotthepony.kstarbound.util.Directives
|
||||||
import ru.dbotthepony.kstarbound.util.ExceptionLogger
|
import ru.dbotthepony.kstarbound.util.ExceptionLogger
|
||||||
import ru.dbotthepony.kstarbound.util.SBPattern
|
import ru.dbotthepony.kstarbound.util.SBPattern
|
||||||
@ -155,8 +157,30 @@ object Starbound : ISBFileLocator {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val STRINGS: Interner<String> = interner(5)
|
val STRINGS: Interner<String> = interner(5)
|
||||||
|
|
||||||
|
// immeasurably lazy and fragile solution
|
||||||
|
var IS_WRITING_LEGACY_JSON: Boolean by ThreadLocal.withInitial { false }
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun writeLegacyJson(data: Any): JsonElement {
|
||||||
|
try {
|
||||||
|
IS_WRITING_LEGACY_JSON = true
|
||||||
|
return gson.toJsonTree(data)
|
||||||
|
} finally {
|
||||||
|
IS_WRITING_LEGACY_JSON = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> writeLegacyJson(block: () -> T): T {
|
||||||
|
try {
|
||||||
|
IS_WRITING_LEGACY_JSON = true
|
||||||
|
return block.invoke()
|
||||||
|
} finally {
|
||||||
|
IS_WRITING_LEGACY_JSON = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val gson: Gson = with(GsonBuilder()) {
|
val gson: Gson = with(GsonBuilder()) {
|
||||||
serializeNulls()
|
// serializeNulls()
|
||||||
setDateFormat(DateFormat.LONG)
|
setDateFormat(DateFormat.LONG)
|
||||||
setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
|
setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
|
||||||
setPrettyPrinting()
|
setPrettyPrinting()
|
||||||
@ -215,18 +239,20 @@ object Starbound : ISBFileLocator {
|
|||||||
registerTypeAdapter(ObjectDefinition::Adapter)
|
registerTypeAdapter(ObjectDefinition::Adapter)
|
||||||
registerTypeAdapter(StatModifier::Adapter)
|
registerTypeAdapter(StatModifier::Adapter)
|
||||||
|
|
||||||
|
registerTypeAdapterFactory(NativeLegacy.Companion)
|
||||||
|
|
||||||
// математические классы
|
// математические классы
|
||||||
registerTypeAdapter(AABBTypeAdapter)
|
registerTypeAdapter(AABBTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(AABBiTypeAdapter)
|
registerTypeAdapter(AABBiTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector2dTypeAdapter)
|
registerTypeAdapter(Vector2dTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector2fTypeAdapter)
|
registerTypeAdapter(Vector2fTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector2iTypeAdapter)
|
registerTypeAdapter(Vector2iTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector3dTypeAdapter)
|
registerTypeAdapter(Vector3dTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector3fTypeAdapter)
|
registerTypeAdapter(Vector3fTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector3iTypeAdapter)
|
registerTypeAdapter(Vector3iTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector4iTypeAdapter)
|
registerTypeAdapter(Vector4iTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector4dTypeAdapter)
|
registerTypeAdapter(Vector4dTypeAdapter.nullSafe())
|
||||||
registerTypeAdapter(Vector4fTypeAdapter)
|
registerTypeAdapter(Vector4fTypeAdapter.nullSafe())
|
||||||
registerTypeAdapterFactory(Line2d.Companion)
|
registerTypeAdapterFactory(Line2d.Companion)
|
||||||
registerTypeAdapterFactory(UniversePos.Companion)
|
registerTypeAdapterFactory(UniversePos.Companion)
|
||||||
registerTypeAdapterFactory(AbstractPerlinNoise.Companion)
|
registerTypeAdapterFactory(AbstractPerlinNoise.Companion)
|
||||||
@ -269,7 +295,6 @@ object Starbound : ISBFileLocator {
|
|||||||
registerTypeAdapter(CelestialParameters::Adapter)
|
registerTypeAdapter(CelestialParameters::Adapter)
|
||||||
registerTypeAdapter(Particle::Adapter)
|
registerTypeAdapter(Particle::Adapter)
|
||||||
|
|
||||||
registerTypeAdapterFactory(BiomePlacementDistributionType.DATA_ADAPTER)
|
|
||||||
registerTypeAdapterFactory(BiomePlacementDistributionType.DEFINITION_ADAPTER)
|
registerTypeAdapterFactory(BiomePlacementDistributionType.DEFINITION_ADAPTER)
|
||||||
registerTypeAdapterFactory(BiomePlacementItemType.DATA_ADAPTER)
|
registerTypeAdapterFactory(BiomePlacementItemType.DATA_ADAPTER)
|
||||||
registerTypeAdapterFactory(BiomePlacementItemType.DEFINITION_ADAPTER)
|
registerTypeAdapterFactory(BiomePlacementItemType.DEFINITION_ADAPTER)
|
||||||
@ -278,6 +303,7 @@ object Starbound : ISBFileLocator {
|
|||||||
// register companion first, so it has lesser priority than dispatching adapter
|
// register companion first, so it has lesser priority than dispatching adapter
|
||||||
registerTypeAdapterFactory(VisitableWorldParametersType.Companion)
|
registerTypeAdapterFactory(VisitableWorldParametersType.Companion)
|
||||||
registerTypeAdapterFactory(VisitableWorldParametersType.ADAPTER)
|
registerTypeAdapterFactory(VisitableWorldParametersType.ADAPTER)
|
||||||
|
registerTypeAdapter(WorldLayout.Companion)
|
||||||
|
|
||||||
Registries.registerAdapters(this)
|
Registries.registerAdapters(this)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import com.google.gson.stream.JsonReader
|
|||||||
import com.google.gson.stream.JsonToken
|
import com.google.gson.stream.JsonToken
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kommons.gson.consumeNull
|
import ru.dbotthepony.kommons.gson.consumeNull
|
||||||
|
import ru.dbotthepony.kommons.guava.immutableMap
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonImplementation
|
import ru.dbotthepony.kstarbound.json.builder.JsonImplementation
|
||||||
|
|
||||||
@JsonImplementation(ThingDescription::class)
|
@JsonImplementation(ThingDescription::class)
|
||||||
@ -84,6 +85,13 @@ data class ThingDescription(
|
|||||||
val EMPTY = ThingDescription()
|
val EMPTY = ThingDescription()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toMap(): ImmutableMap<String, String> {
|
||||||
|
return immutableMap {
|
||||||
|
putAll(racialDescription)
|
||||||
|
put("description", description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun fixDescription(newDescription: String): ThingDescription {
|
fun fixDescription(newDescription: String): ThingDescription {
|
||||||
return copy(
|
return copy(
|
||||||
shortdescription = if (shortdescription == "...") newDescription else shortdescription,
|
shortdescription = if (shortdescription == "...") newDescription else shortdescription,
|
||||||
|
@ -23,6 +23,7 @@ data class PerlinNoiseParameters(
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class Type(override val jsonName: String) : IStringSerializable {
|
enum class Type(override val jsonName: String) : IStringSerializable {
|
||||||
|
UNITIALIZED("uninitialized"),
|
||||||
PERLIN("perlin"),
|
PERLIN("perlin"),
|
||||||
BILLOW("billow"),
|
BILLOW("billow"),
|
||||||
RIDGED_MULTI("ridgedMulti");
|
RIDGED_MULTI("ridgedMulti");
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs.world
|
package ru.dbotthepony.kstarbound.defs.world
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import ru.dbotthepony.kstarbound.Registry
|
import ru.dbotthepony.kstarbound.json.NativeLegacy
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
|
||||||
import ru.dbotthepony.kstarbound.defs.world.AmbientNoisesDefinition
|
|
||||||
import ru.dbotthepony.kstarbound.defs.world.BiomePlaceables
|
|
||||||
import ru.dbotthepony.kstarbound.defs.world.Parallax
|
|
||||||
|
|
||||||
|
@JsonFactory
|
||||||
data class Biome(
|
data class Biome(
|
||||||
val hueShift: Double = 0.0,
|
val hueShift: Double = 0.0,
|
||||||
|
val materialHueShift: Int = 0,
|
||||||
val baseName: String,
|
val baseName: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
val mainBlock: Registry.Entry<TileDefinition>? = null,
|
val mainBlock: NativeLegacy.Tile,
|
||||||
val subBlocks: ImmutableList<Registry.Entry<TileDefinition>> = ImmutableList.of(),
|
val subBlocks: ImmutableList<NativeLegacy.Tile> = ImmutableList.of(),
|
||||||
val ores: ImmutableList<Pair<Registry.Entry<MaterialModifier>, Double>> = ImmutableList.of(),
|
val ores: ImmutableList<Pair<NativeLegacy.TileMod, Double>> = ImmutableList.of(),
|
||||||
val musicTrack: AmbientNoisesDefinition? = null,
|
val musicTrack: AmbientNoisesDefinition? = null,
|
||||||
val ambientNoises: AmbientNoisesDefinition? = null,
|
val ambientNoises: AmbientNoisesDefinition? = null,
|
||||||
val surfacePlaceables: BiomePlaceables = BiomePlaceables(),
|
val surfacePlaceables: BiomePlaceables = BiomePlaceables(),
|
||||||
|
@ -11,9 +11,11 @@ import ru.dbotthepony.kstarbound.defs.AssetReference
|
|||||||
import ru.dbotthepony.kstarbound.defs.JsonConfigFunction
|
import ru.dbotthepony.kstarbound.defs.JsonConfigFunction
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||||
|
import ru.dbotthepony.kstarbound.json.NativeLegacy
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.json.pairListAdapter
|
import ru.dbotthepony.kstarbound.json.pairListAdapter
|
||||||
import ru.dbotthepony.kstarbound.util.random.random
|
import ru.dbotthepony.kstarbound.util.random.random
|
||||||
|
import ru.dbotthepony.kstarbound.world.positiveModulo
|
||||||
import java.util.random.RandomGenerator
|
import java.util.random.RandomGenerator
|
||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
@ -63,9 +65,10 @@ data class BiomeDefinition(
|
|||||||
baseName = name,
|
baseName = name,
|
||||||
description = description,
|
description = description,
|
||||||
hueShift = hueShift,
|
hueShift = hueShift,
|
||||||
|
materialHueShift = ((positiveModulo(hueShift, 360.0) / 360.0) * 255.0).toInt(),
|
||||||
|
|
||||||
mainBlock = mainBlock?.entry,
|
mainBlock = NativeLegacy.Tile(mainBlock?.entry),
|
||||||
subBlocks = subBlocks?.stream()?.map { it.entry }?.filterNotNull()?.collect(ImmutableList.toImmutableList()) ?: ImmutableList.of(),
|
subBlocks = subBlocks?.stream()?.map { NativeLegacy.Tile(it.entry) }?.filterNotNull()?.collect(ImmutableList.toImmutableList()) ?: ImmutableList.of(),
|
||||||
|
|
||||||
musicTrack = musicTrack,
|
musicTrack = musicTrack,
|
||||||
ambientNoises = ambientNoises,
|
ambientNoises = ambientNoises,
|
||||||
@ -77,10 +80,10 @@ data class BiomeDefinition(
|
|||||||
ores = (ores?.value?.evaluate(threatLevel, oresAdapter)?.map {
|
ores = (ores?.value?.evaluate(threatLevel, oresAdapter)?.map {
|
||||||
it.stream()
|
it.stream()
|
||||||
.filter { it.second > 0.0 }
|
.filter { it.second > 0.0 }
|
||||||
.map { Registries.tileModifiers[it.first] to it.second }
|
.map { NativeLegacy.TileMod(Registries.tileModifiers.ref(it.first)) to it.second }
|
||||||
.filter { it.first != null }
|
.filter { it.first.native.isPresent }
|
||||||
.collect(ImmutableList.toImmutableList())
|
.collect(ImmutableList.toImmutableList())
|
||||||
}?.orElse(ImmutableList.of()) ?: ImmutableList.of()) as ImmutableList<Pair<Registry.Entry<MaterialModifier>, Double>>
|
}?.orElse(ImmutableList.of()) ?: ImmutableList.of())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableSet
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
import com.google.gson.JsonSyntaxException
|
import com.google.gson.JsonSyntaxException
|
||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
@ -19,7 +20,9 @@ import ru.dbotthepony.kommons.gson.value
|
|||||||
import ru.dbotthepony.kstarbound.Registry
|
import ru.dbotthepony.kstarbound.Registry
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
import ru.dbotthepony.kstarbound.collect.WeightedList
|
import ru.dbotthepony.kstarbound.collect.WeightedList
|
||||||
|
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
|
import ru.dbotthepony.kstarbound.json.NativeLegacy
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFlat
|
import ru.dbotthepony.kstarbound.json.builder.JsonFlat
|
||||||
import ru.dbotthepony.kstarbound.json.listAdapter
|
import ru.dbotthepony.kstarbound.json.listAdapter
|
||||||
@ -28,14 +31,14 @@ import java.util.stream.Stream
|
|||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
data class BiomePlaceables(
|
data class BiomePlaceables(
|
||||||
val grassMod: Registry.Entry<MaterialModifier>? = null,
|
val grassMod: NativeLegacy.TileMod = NativeLegacy.TileMod(null as Registry.Ref<MaterialModifier>?),
|
||||||
val ceilingGrassMod: Registry.Entry<MaterialModifier>? = null,
|
val ceilingGrassMod: NativeLegacy.TileMod = NativeLegacy.TileMod(null as Registry.Ref<MaterialModifier>?),
|
||||||
val grassModDensity: Double = 0.0,
|
val grassModDensity: Double = 0.0,
|
||||||
val ceilingGrassModDensity: Double = 0.0,
|
val ceilingGrassModDensity: Double = 0.0,
|
||||||
val items: ImmutableList<DistributionItem> = ImmutableList.of(),
|
val itemDistributions: ImmutableList<DistributionItem> = ImmutableList.of(),
|
||||||
) {
|
) {
|
||||||
fun firstTreeVariant(): TreeVariant? {
|
fun firstTreeVariant(): TreeVariant? {
|
||||||
return items.stream()
|
return itemDistributions.stream()
|
||||||
.flatMap { it.data.itemStream() }
|
.flatMap { it.data.itemStream() }
|
||||||
.map { it as? Tree }
|
.map { it as? Tree }
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
@ -107,7 +110,7 @@ data class BiomePlaceables(
|
|||||||
))
|
))
|
||||||
"grass" -> Grass(grassVariant.read(`in`))
|
"grass" -> Grass(grassVariant.read(`in`))
|
||||||
"bush" -> Bush(bushVariant.read(`in`))
|
"bush" -> Bush(bushVariant.read(`in`))
|
||||||
"tree" -> Tree(trees.read(`in`))
|
"treePair" -> Tree(trees.read(`in`))
|
||||||
"objectPool" -> Object(objects.read(`in`))
|
"objectPool" -> Object(objects.read(`in`))
|
||||||
else -> throw JsonSyntaxException("Unknown biome placement item $type")
|
else -> throw JsonSyntaxException("Unknown biome placement item $type")
|
||||||
}
|
}
|
||||||
@ -187,39 +190,28 @@ data class BiomePlaceables(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- DISTRIBUTION
|
// ТЕПЕРЬ УГАДАЙ
|
||||||
abstract class DistributionData {
|
// МОЙ
|
||||||
abstract val type: BiomePlacementDistributionType
|
// ПОЛ.
|
||||||
|
// БЛЯДЬ
|
||||||
abstract fun itemStream(): Stream<Item>
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
data class RandomDistribution(
|
data class DistributionData(
|
||||||
val blockSeed: Long,
|
val distribution: BiomePlacementDistributionType,
|
||||||
val randomItems: ImmutableList<Item>,
|
val blockSeed: Long = 0L,
|
||||||
) : DistributionData() {
|
val blockProbability: Double = 0.0,
|
||||||
override val type: BiomePlacementDistributionType
|
val randomItems: ImmutableList<Item> = ImmutableList.of(),
|
||||||
get() = BiomePlacementDistributionType.RANDOM
|
val modulus: Int = 0,
|
||||||
|
val modulusOffset: Int = 0,
|
||||||
override fun itemStream(): Stream<Item> {
|
val densityFunction: AbstractPerlinNoise = AbstractPerlinNoise.of(PerlinNoiseParameters()),
|
||||||
return randomItems.stream()
|
val modulusDistortion: AbstractPerlinNoise = AbstractPerlinNoise.of(PerlinNoiseParameters()),
|
||||||
}
|
val weightedItems: ImmutableList<Pair<Item, AbstractPerlinNoise>> = ImmutableList.of(),
|
||||||
}
|
) {
|
||||||
|
fun itemStream(): Stream<Item> {
|
||||||
@JsonFactory
|
if (distribution == BiomePlacementDistributionType.RANDOM) {
|
||||||
data class PeriodicDistribution(
|
return randomItems.stream()
|
||||||
val modulus: Int,
|
} else {
|
||||||
val modulusOffset: Int,
|
return weightedItems.stream().map { it.first }
|
||||||
val densityFunction: AbstractPerlinNoise,
|
}
|
||||||
val modulusDistortion: AbstractPerlinNoise,
|
|
||||||
val weightedItems: ImmutableList<Pair<Item, AbstractPerlinNoise>>,
|
|
||||||
) : DistributionData() {
|
|
||||||
override val type: BiomePlacementDistributionType
|
|
||||||
get() = BiomePlacementDistributionType.PERIODIC
|
|
||||||
|
|
||||||
override fun itemStream(): Stream<Item> {
|
|
||||||
return weightedItems.stream().map { it.first }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,6 +11,8 @@ import ru.dbotthepony.kstarbound.collect.WeightedList
|
|||||||
import ru.dbotthepony.kstarbound.defs.AssetReference
|
import ru.dbotthepony.kstarbound.defs.AssetReference
|
||||||
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
|
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
|
import ru.dbotthepony.kstarbound.json.NativeLegacy
|
||||||
|
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFlat
|
import ru.dbotthepony.kstarbound.json.builder.JsonFlat
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonSingleton
|
import ru.dbotthepony.kstarbound.json.builder.JsonSingleton
|
||||||
@ -27,8 +29,8 @@ data class BiomePlaceablesDefinition(
|
|||||||
val ceilingGrassModDensity: Double = 0.0,
|
val ceilingGrassModDensity: Double = 0.0,
|
||||||
val items: ImmutableList<DistributionItem> = ImmutableList.of(),
|
val items: ImmutableList<DistributionItem> = ImmutableList.of(),
|
||||||
) {
|
) {
|
||||||
enum class Placement {
|
enum class Placement(override val jsonName: String) : IStringSerializable {
|
||||||
FLOOR, CEILING, BACKGROUND, OCEAN;
|
FLOOR("floor"), CEILING("ceiling"), BACKGROUND("background"), OCEAN("ocean");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------- ITEMS
|
// ----------- ITEMS
|
||||||
@ -251,8 +253,8 @@ data class BiomePlaceablesDefinition(
|
|||||||
abstract fun create(self: DistributionItem, biome: BiomeDefinition.CreationParams): BiomePlaceables.DistributionData
|
abstract fun create(self: DistributionItem, biome: BiomeDefinition.CreationParams): BiomePlaceables.DistributionData
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSingleton
|
@JsonFactory
|
||||||
object RandomDistribution : DistributionData() {
|
data class RandomDistribution(val blockProbability: Double) : DistributionData() {
|
||||||
override val type: BiomePlacementDistributionType
|
override val type: BiomePlacementDistributionType
|
||||||
get() = BiomePlacementDistributionType.RANDOM
|
get() = BiomePlacementDistributionType.RANDOM
|
||||||
|
|
||||||
@ -260,8 +262,10 @@ data class BiomePlaceablesDefinition(
|
|||||||
self: DistributionItem,
|
self: DistributionItem,
|
||||||
biome: BiomeDefinition.CreationParams
|
biome: BiomeDefinition.CreationParams
|
||||||
): BiomePlaceables.DistributionData {
|
): BiomePlaceables.DistributionData {
|
||||||
return BiomePlaceables.RandomDistribution(
|
return BiomePlaceables.DistributionData(
|
||||||
|
distribution = BiomePlacementDistributionType.RANDOM,
|
||||||
blockSeed = biome.random.nextLong(),
|
blockSeed = biome.random.nextLong(),
|
||||||
|
blockProbability = blockProbability,
|
||||||
randomItems = IntStream.range(0, self.variants)
|
randomItems = IntStream.range(0, self.variants)
|
||||||
.mapToObj { self.data.create(biome) }
|
.mapToObj { self.data.create(biome) }
|
||||||
.collect(ImmutableList.toImmutableList())
|
.collect(ImmutableList.toImmutableList())
|
||||||
@ -291,7 +295,8 @@ data class BiomePlaceablesDefinition(
|
|||||||
): BiomePlaceables.DistributionData {
|
): BiomePlaceables.DistributionData {
|
||||||
val modulusOffset = if (modulus == 0) 0 else biome.random.nextInt(-modulus, modulus)
|
val modulusOffset = if (modulus == 0) 0 else biome.random.nextInt(-modulus, modulus)
|
||||||
|
|
||||||
return BiomePlaceables.PeriodicDistribution(
|
return BiomePlaceables.DistributionData(
|
||||||
|
distribution = BiomePlacementDistributionType.PERIODIC,
|
||||||
modulus = modulus,
|
modulus = modulus,
|
||||||
modulusOffset = modulusOffset,
|
modulusOffset = modulusOffset,
|
||||||
|
|
||||||
@ -350,11 +355,11 @@ data class BiomePlaceablesDefinition(
|
|||||||
|
|
||||||
fun create(biome: BiomeDefinition.CreationParams): BiomePlaceables {
|
fun create(biome: BiomeDefinition.CreationParams): BiomePlaceables {
|
||||||
return BiomePlaceables(
|
return BiomePlaceables(
|
||||||
grassMod = grassMod.random(biome.random) { null }?.entry,
|
grassMod = NativeLegacy.TileMod(grassMod.random(biome.random) { null }?.entry),
|
||||||
ceilingGrassMod = ceilingGrassMod.random(biome.random) { null }?.entry,
|
ceilingGrassMod = NativeLegacy.TileMod(ceilingGrassMod.random(biome.random) { null }?.entry),
|
||||||
grassModDensity = grassModDensity,
|
grassModDensity = grassModDensity,
|
||||||
ceilingGrassModDensity = ceilingGrassModDensity,
|
ceilingGrassModDensity = ceilingGrassModDensity,
|
||||||
items = items.stream()
|
itemDistributions = items.stream()
|
||||||
.map { it.create(biome) }
|
.map { it.create(biome) }
|
||||||
.collect(ImmutableList.toImmutableList())
|
.collect(ImmutableList.toImmutableList())
|
||||||
)
|
)
|
||||||
|
@ -7,16 +7,9 @@ import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
|
|||||||
enum class BiomePlacementDistributionType(
|
enum class BiomePlacementDistributionType(
|
||||||
override val jsonName: String,
|
override val jsonName: String,
|
||||||
val def: TypeToken<out BiomePlaceablesDefinition.DistributionData>,
|
val def: TypeToken<out BiomePlaceablesDefinition.DistributionData>,
|
||||||
val data: TypeToken<out BiomePlaceables.DistributionData>,
|
|
||||||
) : IStringSerializable {
|
) : IStringSerializable {
|
||||||
RANDOM("random",
|
RANDOM("random",TypeToken.get(BiomePlaceablesDefinition.RandomDistribution::class.java)),
|
||||||
TypeToken.get(BiomePlaceablesDefinition.RandomDistribution::class.java),
|
PERIODIC("periodic", TypeToken.get(BiomePlaceablesDefinition.PeriodicDistribution::class.java));
|
||||||
TypeToken.get(BiomePlaceables.RandomDistribution::class.java)
|
|
||||||
),
|
|
||||||
PERIODIC("periodic",
|
|
||||||
TypeToken.get(BiomePlaceablesDefinition.PeriodicDistribution::class.java),
|
|
||||||
TypeToken.get(BiomePlaceables.PeriodicDistribution::class.java)
|
|
||||||
);
|
|
||||||
|
|
||||||
override fun match(name: String): Boolean {
|
override fun match(name: String): Boolean {
|
||||||
return name.lowercase() == jsonName
|
return name.lowercase() == jsonName
|
||||||
@ -24,6 +17,5 @@ enum class BiomePlacementDistributionType(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val DEFINITION_ADAPTER = DispatchingAdapter("type", { type }, { def }, entries)
|
val DEFINITION_ADAPTER = DispatchingAdapter("type", { type }, { def }, entries)
|
||||||
val DATA_ADAPTER = DispatchingAdapter("type", { type }, { data }, entries)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,14 +26,13 @@ class BushVariant(
|
|||||||
val baseHueShift: Double,
|
val baseHueShift: Double,
|
||||||
val modHueShift: Double,
|
val modHueShift: Double,
|
||||||
|
|
||||||
@JsonFlat
|
val descriptions: ImmutableMap<String, String> = ImmutableMap.of(),
|
||||||
val descriptions: ThingDescription,
|
|
||||||
val ceiling: Boolean,
|
val ceiling: Boolean,
|
||||||
|
|
||||||
val ephemeral: Boolean,
|
val ephemeral: Boolean,
|
||||||
val tileDamageParameters: TileDamageConfig,
|
val tileDamageParameters: TileDamageConfig,
|
||||||
) {
|
) {
|
||||||
@JsonFactory
|
@JsonFactory(asList = true)
|
||||||
data class Shape(val image: String, val mods: ImmutableList<String>)
|
data class Shape(val image: String, val mods: ImmutableList<String>)
|
||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
@ -64,7 +63,7 @@ class BushVariant(
|
|||||||
directory = data.file?.computeDirectory() ?: "/",
|
directory = data.file?.computeDirectory() ?: "/",
|
||||||
modHueShift = modHueShift,
|
modHueShift = modHueShift,
|
||||||
ceiling = data.value.ceiling,
|
ceiling = data.value.ceiling,
|
||||||
descriptions = data.value.descriptions.fixDescription("${data.key} with $modName"),
|
descriptions = data.value.descriptions.fixDescription("${data.key} with $modName").toMap(),
|
||||||
ephemeral = data.value.ephemeral,
|
ephemeral = data.value.ephemeral,
|
||||||
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.bushDamage).copy(totalHealth = data.value.health),
|
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.bushDamage).copy(totalHealth = data.value.health),
|
||||||
modName = modName,
|
modName = modName,
|
||||||
|
@ -11,7 +11,9 @@ import com.google.gson.reflect.TypeToken
|
|||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kommons.gson.consumeNull
|
import ru.dbotthepony.kommons.gson.consumeNull
|
||||||
|
import ru.dbotthepony.kommons.gson.set
|
||||||
import ru.dbotthepony.kommons.gson.value
|
import ru.dbotthepony.kommons.gson.value
|
||||||
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.util.random.random
|
import ru.dbotthepony.kstarbound.util.random.random
|
||||||
import ru.dbotthepony.kstarbound.world.UniversePos
|
import ru.dbotthepony.kstarbound.world.UniversePos
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs.world
|
package ru.dbotthepony.kstarbound.defs.world
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import ru.dbotthepony.kstarbound.GlobalDefaults
|
import ru.dbotthepony.kstarbound.GlobalDefaults
|
||||||
@ -17,8 +18,7 @@ data class GrassVariant(
|
|||||||
val directory: String,
|
val directory: String,
|
||||||
val images: ImmutableSet<String> = ImmutableSet.of(),
|
val images: ImmutableSet<String> = ImmutableSet.of(),
|
||||||
val hueShift: Double,
|
val hueShift: Double,
|
||||||
@JsonFlat
|
val descriptions: ImmutableMap<String, String> = ImmutableMap.of(),
|
||||||
val descriptions: ThingDescription,
|
|
||||||
val ceiling: Boolean,
|
val ceiling: Boolean,
|
||||||
val ephemeral: Boolean,
|
val ephemeral: Boolean,
|
||||||
val tileDamageParameters: TileDamageConfig,
|
val tileDamageParameters: TileDamageConfig,
|
||||||
@ -53,7 +53,7 @@ data class GrassVariant(
|
|||||||
ceiling = data.value.ceiling,
|
ceiling = data.value.ceiling,
|
||||||
ephemeral = data.value.ephemeral,
|
ephemeral = data.value.ephemeral,
|
||||||
hueShift = hueShift,
|
hueShift = hueShift,
|
||||||
descriptions = data.value.descriptions.fixDescription(data.value.name),
|
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 ?: GlobalDefaults.grassDamage).copy(totalHealth = data.value.health)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.defs.world
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import ru.dbotthepony.kommons.collect.filterNotNull
|
import ru.dbotthepony.kommons.collect.filterNotNull
|
||||||
|
import ru.dbotthepony.kommons.gson.get
|
||||||
import ru.dbotthepony.kommons.math.RGBAColor
|
import ru.dbotthepony.kommons.math.RGBAColor
|
||||||
import ru.dbotthepony.kommons.util.Either
|
import ru.dbotthepony.kommons.util.Either
|
||||||
import ru.dbotthepony.kommons.vector.Vector2d
|
import ru.dbotthepony.kommons.vector.Vector2d
|
||||||
@ -80,7 +81,7 @@ class Parallax(
|
|||||||
|
|
||||||
if (isFoliage) {
|
if (isFoliage) {
|
||||||
if (treeVariant == null) return null
|
if (treeVariant == null) return null
|
||||||
if (!treeVariant.foliageSettings.parallaxFoliage) return null
|
if (!treeVariant.foliageSettings.asJsonObject.get("parallaxFoliage", false)) return null
|
||||||
texPath = "${treeVariant.foliageDirectory}/parallax/${kind.replace("foliage/", "")}/"
|
texPath = "${treeVariant.foliageDirectory}/parallax/${kind.replace("foliage/", "")}/"
|
||||||
} else if (isStem) {
|
} else if (isStem) {
|
||||||
if (treeVariant == null) return null
|
if (treeVariant == null) return null
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs.world
|
package ru.dbotthepony.kstarbound.defs.world
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableMap
|
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonNull
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
@ -24,13 +22,11 @@ import ru.dbotthepony.kstarbound.Starbound
|
|||||||
import ru.dbotthepony.kstarbound.collect.WeightedList
|
import ru.dbotthepony.kstarbound.collect.WeightedList
|
||||||
import ru.dbotthepony.kstarbound.defs.JsonDriven
|
import ru.dbotthepony.kstarbound.defs.JsonDriven
|
||||||
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
|
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
|
||||||
import ru.dbotthepony.kstarbound.fromJson
|
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.json.pairAdapter
|
import ru.dbotthepony.kstarbound.json.pairAdapter
|
||||||
import ru.dbotthepony.kstarbound.json.stream
|
import ru.dbotthepony.kstarbound.json.stream
|
||||||
import ru.dbotthepony.kstarbound.util.binnedChoice
|
import ru.dbotthepony.kstarbound.util.binnedChoice
|
||||||
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise
|
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise
|
||||||
import ru.dbotthepony.kstarbound.util.random.PerlinNoise
|
|
||||||
import ru.dbotthepony.kstarbound.util.random.nextRange
|
import ru.dbotthepony.kstarbound.util.random.nextRange
|
||||||
import ru.dbotthepony.kstarbound.util.random.random
|
import ru.dbotthepony.kstarbound.util.random.random
|
||||||
import java.util.random.RandomGenerator
|
import java.util.random.RandomGenerator
|
||||||
@ -100,13 +96,13 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
|||||||
val read = Starbound.gson.fromJson(data, StoreData::class.java)
|
val read = Starbound.gson.fromJson(data, StoreData::class.java)
|
||||||
|
|
||||||
primaryBiome = read.primaryBiome
|
primaryBiome = read.primaryBiome
|
||||||
primarySurfaceLiquid = read.primarySurfaceLiquid
|
surfaceLiquid = read.surfaceLiquid
|
||||||
sizeName = read.sizeName
|
sizeName = read.sizeName
|
||||||
hueShift = read.hueShift
|
hueShift = read.hueShift
|
||||||
skyColoring = read.skyColoring
|
skyColoring = read.skyColoring
|
||||||
dayLength = read.dayLength
|
dayLength = read.dayLength
|
||||||
blockNoiseConfig = read.blockNoiseConfig
|
blockNoiseConfig = read.blockNoise
|
||||||
blendNoiseConfig = read.blendNoiseConfig
|
blendNoiseConfig = read.blendNoise
|
||||||
blendSize = read.blendSize
|
blendSize = read.blendSize
|
||||||
spaceLayer = read.spaceLayer
|
spaceLayer = read.spaceLayer
|
||||||
atmosphereLayer = read.atmosphereLayer
|
atmosphereLayer = read.atmosphereLayer
|
||||||
@ -124,23 +120,23 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
|||||||
// original engine operate on liquids solely with IDs
|
// original engine operate on liquids solely with IDs
|
||||||
// and we also need to network this json to legacy clients.
|
// and we also need to network this json to legacy clients.
|
||||||
// what a shame :JC:.
|
// what a shame :JC:.
|
||||||
if (this.primarySurfaceLiquid == null) {
|
if (this.surfaceLiquid == null) {
|
||||||
primarySurfaceLiquid = if (isLegacy) Either.left(0) else null
|
primarySurfaceLiquid = if (isLegacy) Either.left(0) else null
|
||||||
} else if (isLegacy) {
|
} else if (isLegacy) {
|
||||||
primarySurfaceLiquid = this.primarySurfaceLiquid!!.map({ it }, { Registries.liquid.get(it)!!.id })?.let { Either.left(it) }
|
primarySurfaceLiquid = this.surfaceLiquid!!.map({ it }, { Registries.liquid.get(it)!!.id })?.let { Either.left(it) }
|
||||||
} else {
|
} else {
|
||||||
primarySurfaceLiquid = this.primarySurfaceLiquid
|
primarySurfaceLiquid = this.surfaceLiquid
|
||||||
}
|
}
|
||||||
|
|
||||||
val store = StoreData(
|
val store = StoreData(
|
||||||
primaryBiome = primaryBiome,
|
primaryBiome = primaryBiome,
|
||||||
primarySurfaceLiquid = primarySurfaceLiquid,
|
surfaceLiquid = primarySurfaceLiquid,
|
||||||
sizeName = sizeName,
|
sizeName = sizeName,
|
||||||
hueShift = hueShift,
|
hueShift = hueShift,
|
||||||
skyColoring = skyColoring,
|
skyColoring = skyColoring,
|
||||||
dayLength = dayLength,
|
dayLength = dayLength,
|
||||||
blockNoiseConfig = blockNoiseConfig,
|
blockNoise = blockNoiseConfig,
|
||||||
blendNoiseConfig = blendNoiseConfig,
|
blendNoise = blendNoiseConfig,
|
||||||
blendSize = blendSize,
|
blendSize = blendSize,
|
||||||
spaceLayer = spaceLayer,
|
spaceLayer = spaceLayer,
|
||||||
atmosphereLayer = atmosphereLayer,
|
atmosphereLayer = atmosphereLayer,
|
||||||
@ -158,13 +154,13 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
|||||||
@JsonFactory
|
@JsonFactory
|
||||||
data class StoreData(
|
data class StoreData(
|
||||||
val primaryBiome: String,
|
val primaryBiome: String,
|
||||||
val primarySurfaceLiquid: Either<Int, String>? = null,
|
val surfaceLiquid: Either<Int, String>? = null,
|
||||||
val sizeName: String,
|
val sizeName: String,
|
||||||
val hueShift: Double,
|
val hueShift: Double,
|
||||||
val skyColoring: SkyColoring,
|
val skyColoring: SkyColoring,
|
||||||
val dayLength: Double,
|
val dayLength: Double,
|
||||||
val blockNoiseConfig: BlockNoiseConfig? = null,
|
val blockNoise: BlockNoiseConfig? = null,
|
||||||
val blendNoiseConfig: PerlinNoiseParameters? = null,
|
val blendNoise: PerlinNoiseParameters? = null,
|
||||||
val blendSize: Double,
|
val blendSize: Double,
|
||||||
val spaceLayer: Layer,
|
val spaceLayer: Layer,
|
||||||
val atmosphereLayer: Layer,
|
val atmosphereLayer: Layer,
|
||||||
@ -176,7 +172,7 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
|||||||
|
|
||||||
var primaryBiome: String by Delegates.notNull()
|
var primaryBiome: String by Delegates.notNull()
|
||||||
private set
|
private set
|
||||||
var primarySurfaceLiquid: Either<Int, String>? = null
|
var surfaceLiquid: Either<Int, String>? = null
|
||||||
private set
|
private set
|
||||||
var sizeName: String by Delegates.notNull()
|
var sizeName: String by Delegates.notNull()
|
||||||
private set
|
private set
|
||||||
@ -454,7 +450,7 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
|||||||
parameters.sizeName = sizeName
|
parameters.sizeName = sizeName
|
||||||
parameters.hueShift = primaryBiome.value.hueShift(random)
|
parameters.hueShift = primaryBiome.value.hueShift(random)
|
||||||
|
|
||||||
parameters.primarySurfaceLiquid = surfaceLayer.primaryRegion.oceanLiquid ?: surfaceLayer.primaryRegion.caveLiquid
|
parameters.surfaceLiquid = surfaceLayer.primaryRegion.oceanLiquid ?: surfaceLayer.primaryRegion.caveLiquid
|
||||||
parameters.skyColoring = primaryBiome.value.skyColoring(random)
|
parameters.skyColoring = primaryBiome.value.skyColoring(random)
|
||||||
parameters.dayLength = random.nextRange(params.dayLengthRange)
|
parameters.dayLength = random.nextRange(params.dayLengthRange)
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs.world
|
package ru.dbotthepony.kstarbound.defs.world
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
|
import com.google.gson.JsonNull
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import ru.dbotthepony.kstarbound.GlobalDefaults
|
import ru.dbotthepony.kstarbound.GlobalDefaults
|
||||||
import ru.dbotthepony.kstarbound.Registries
|
import ru.dbotthepony.kstarbound.Registries
|
||||||
@ -24,11 +26,10 @@ data class TreeVariant(
|
|||||||
|
|
||||||
val foliageDirectory: String,
|
val foliageDirectory: String,
|
||||||
// AGAIN.
|
// AGAIN.
|
||||||
val foliageSettings: FoliageData,
|
val foliageSettings: JsonElement,
|
||||||
val foliageHueShift: Double,
|
val foliageHueShift: Double,
|
||||||
|
|
||||||
@JsonFlat
|
val descriptions: ImmutableMap<String, String> = ImmutableMap.of(),
|
||||||
val descriptions: ThingDescription,
|
|
||||||
val ceiling: Boolean,
|
val ceiling: Boolean,
|
||||||
|
|
||||||
val ephemeral: Boolean,
|
val ephemeral: Boolean,
|
||||||
@ -78,11 +79,11 @@ data class TreeVariant(
|
|||||||
stemHueShift = stemHueShift,
|
stemHueShift = stemHueShift,
|
||||||
ceiling = data.value.ceiling,
|
ceiling = data.value.ceiling,
|
||||||
stemDropConfig = data.value.dropConfig.deepCopy(),
|
stemDropConfig = data.value.dropConfig.deepCopy(),
|
||||||
descriptions = data.value.descriptions.fixDescription(data.key),
|
descriptions = data.value.descriptions.fixDescription(data.key).toMap(),
|
||||||
ephemeral = data.value.ephemeral,
|
ephemeral = data.value.ephemeral,
|
||||||
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
|
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
|
||||||
|
|
||||||
foliageSettings = FoliageData("", shape = ""),
|
foliageSettings = JsonNull.INSTANCE,
|
||||||
foliageDropConfig = JsonObject(),
|
foliageDropConfig = JsonObject(),
|
||||||
foliageName = "",
|
foliageName = "",
|
||||||
foliageDirectory = "/",
|
foliageDirectory = "/",
|
||||||
@ -105,11 +106,11 @@ data class TreeVariant(
|
|||||||
stemHueShift = stemHueShift,
|
stemHueShift = stemHueShift,
|
||||||
ceiling = data.value.ceiling,
|
ceiling = data.value.ceiling,
|
||||||
stemDropConfig = data.value.dropConfig.deepCopy(),
|
stemDropConfig = data.value.dropConfig.deepCopy(),
|
||||||
descriptions = data.value.descriptions.fixDescription("${data.key} with ${fdata.key}"),
|
descriptions = data.value.descriptions.fixDescription("${data.key} with ${fdata.key}").toMap(),
|
||||||
ephemeral = data.value.ephemeral,
|
ephemeral = data.value.ephemeral,
|
||||||
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
|
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
|
||||||
|
|
||||||
foliageSettings = fdata.value,
|
foliageSettings = fdata.json,
|
||||||
foliageDropConfig = fdata.value.dropConfig.deepCopy(),
|
foliageDropConfig = fdata.value.dropConfig.deepCopy(),
|
||||||
foliageName = fdata.key,
|
foliageName = fdata.key,
|
||||||
foliageDirectory = fdata.file?.computeDirectory() ?: "/",
|
foliageDirectory = fdata.file?.computeDirectory() ?: "/",
|
||||||
|
@ -51,7 +51,7 @@ enum class VisitableWorldParametersType(override val jsonName: String, val token
|
|||||||
if (value == null)
|
if (value == null)
|
||||||
out.nullValue()
|
out.nullValue()
|
||||||
else
|
else
|
||||||
out.value(value.toJson(false))
|
out.value(value.toJson())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(`in`: JsonReader): VisitableWorldParameters? {
|
override fun read(`in`: JsonReader): VisitableWorldParameters? {
|
||||||
@ -140,7 +140,7 @@ abstract class VisitableWorldParameters {
|
|||||||
this.weatherPool = read.weatherPool
|
this.weatherPool = read.weatherPool
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun toJson(data: JsonObject, isLegacy: Boolean) {
|
open fun toJson(data: JsonObject, isLegacy: Boolean = Starbound.IS_WRITING_LEGACY_JSON) {
|
||||||
val store = StoreData(
|
val store = StoreData(
|
||||||
threatLevel,
|
threatLevel,
|
||||||
typeName,
|
typeName,
|
||||||
@ -164,7 +164,7 @@ abstract class VisitableWorldParameters {
|
|||||||
data["type"] = type.jsonName
|
data["type"] = type.jsonName
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toJson(isLegacy: Boolean): JsonObject {
|
fun toJson(isLegacy: Boolean = Starbound.IS_WRITING_LEGACY_JSON): JsonObject {
|
||||||
val data = JsonObject()
|
val data = JsonObject()
|
||||||
toJson(data, isLegacy)
|
toJson(data, isLegacy)
|
||||||
return data
|
return data
|
||||||
|
@ -4,12 +4,17 @@ import com.google.common.collect.ImmutableList
|
|||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
import it.unimi.dsi.fastutil.doubles.DoubleArrayList
|
import it.unimi.dsi.fastutil.doubles.DoubleArrayList
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList
|
import it.unimi.dsi.fastutil.ints.IntArrayList
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||||
import ru.dbotthepony.kommons.gson.JsonArrayCollector
|
import ru.dbotthepony.kommons.gson.JsonArrayCollector
|
||||||
|
import ru.dbotthepony.kommons.gson.consumeNull
|
||||||
import ru.dbotthepony.kommons.gson.set
|
import ru.dbotthepony.kommons.gson.set
|
||||||
|
import ru.dbotthepony.kommons.gson.value
|
||||||
import ru.dbotthepony.kommons.math.RGBAColor
|
import ru.dbotthepony.kommons.math.RGBAColor
|
||||||
import ru.dbotthepony.kommons.util.AABBi
|
import ru.dbotthepony.kommons.util.AABBi
|
||||||
import ru.dbotthepony.kommons.util.Either
|
import ru.dbotthepony.kommons.util.Either
|
||||||
@ -202,11 +207,11 @@ class WorldLayout {
|
|||||||
val layers: JsonArray,
|
val layers: JsonArray,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun toJson(isLegacy: Boolean): JsonObject {
|
fun toJson(): JsonObject {
|
||||||
return Starbound.gson.toJsonTree(SerializedForm(
|
return Starbound.gson.toJsonTree(SerializedForm(
|
||||||
worldSize, regionBlending, blockNoise, blendNoise,
|
worldSize, regionBlending, blockNoise, blendNoise,
|
||||||
playerStartSearchRegions, biomes.list, terrainSelectors.list,
|
playerStartSearchRegions, biomes.list, terrainSelectors.list,
|
||||||
layers = layers.stream().map { it.toJson(isLegacy) }.collect(JsonArrayCollector)
|
layers = layers.stream().map { it.toJson(Starbound.IS_WRITING_LEGACY_JSON) }.collect(JsonArrayCollector)
|
||||||
)) as JsonObject
|
)) as JsonObject
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,4 +415,24 @@ class WorldLayout {
|
|||||||
biome.parallax?.fadeToSkyColor(skyColoring)
|
biome.parallax?.fadeToSkyColor(skyColoring)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object : TypeAdapter<WorldLayout>() {
|
||||||
|
private val objects by lazy { Starbound.gson.getAdapter(JsonObject::class.java) }
|
||||||
|
|
||||||
|
override fun write(out: JsonWriter, value: WorldLayout?) {
|
||||||
|
if (value == null)
|
||||||
|
out.nullValue()
|
||||||
|
else
|
||||||
|
out.value(value.toJson())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): WorldLayout? {
|
||||||
|
if (`in`.consumeNull())
|
||||||
|
return null
|
||||||
|
|
||||||
|
val params = WorldLayout()
|
||||||
|
params.fromJson(objects.read(`in`))
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList
|
|||||||
import com.google.common.collect.ImmutableMap
|
import com.google.common.collect.ImmutableMap
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonNull
|
import com.google.gson.JsonNull
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import ru.dbotthepony.kommons.util.AABBi
|
import ru.dbotthepony.kommons.util.AABBi
|
||||||
import ru.dbotthepony.kommons.util.Either
|
import ru.dbotthepony.kommons.util.Either
|
||||||
import ru.dbotthepony.kommons.vector.Vector2d
|
import ru.dbotthepony.kommons.vector.Vector2d
|
||||||
@ -15,7 +16,7 @@ import ru.dbotthepony.kstarbound.world.Direction1D
|
|||||||
data class WorldStructure(
|
data class WorldStructure(
|
||||||
val region: AABBi = AABBi(Vector2i.ZERO, Vector2i.ZERO),
|
val region: AABBi = AABBi(Vector2i.ZERO, Vector2i.ZERO),
|
||||||
val anchorPosition: Vector2i = Vector2i.ZERO,
|
val anchorPosition: Vector2i = Vector2i.ZERO,
|
||||||
val config: JsonElement = JsonNull.INSTANCE,
|
var config: JsonElement = JsonObject(),
|
||||||
val backgroundOverlays: ImmutableList<Overlay> = ImmutableList.of(),
|
val backgroundOverlays: ImmutableList<Overlay> = ImmutableList.of(),
|
||||||
val foregroundOverlays: ImmutableList<Overlay> = ImmutableList.of(),
|
val foregroundOverlays: ImmutableList<Overlay> = ImmutableList.of(),
|
||||||
val backgroundBlocks: ImmutableList<Block> = ImmutableList.of(),
|
val backgroundBlocks: ImmutableList<Block> = ImmutableList.of(),
|
||||||
@ -23,6 +24,13 @@ data class WorldStructure(
|
|||||||
val objects: ImmutableList<Obj> = ImmutableList.of(),
|
val objects: ImmutableList<Obj> = ImmutableList.of(),
|
||||||
val flaggedBlocks: ImmutableMap<String, ImmutableList<Vector2i>> = ImmutableMap.of(),
|
val flaggedBlocks: ImmutableMap<String, ImmutableList<Vector2i>> = ImmutableMap.of(),
|
||||||
) {
|
) {
|
||||||
|
init {
|
||||||
|
if (config == JsonNull.INSTANCE) {
|
||||||
|
// so it is not omitted
|
||||||
|
config = JsonObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
data class Overlay(val min: Vector2d, val image: String, val fullbright: Boolean)
|
data class Overlay(val min: Vector2d, val image: String, val fullbright: Boolean)
|
||||||
|
|
||||||
|
@ -51,17 +51,17 @@ class WorldTemplate(val geometry: WorldGeometry) {
|
|||||||
val skyParameters: SkyParameters = SkyParameters(),
|
val skyParameters: SkyParameters = SkyParameters(),
|
||||||
val seed: Long = 0L,
|
val seed: Long = 0L,
|
||||||
val size: Either<WorldGeometry, Vector2i>,
|
val size: Either<WorldGeometry, Vector2i>,
|
||||||
val regionData: JsonElement = JsonNull.INSTANCE,
|
val regionData: WorldLayout? = null,
|
||||||
//val customTerrainRegions:
|
//val customTerrainRegions:
|
||||||
)
|
)
|
||||||
|
|
||||||
fun toJson(isLegacy: Boolean): JsonObject {
|
fun toJson(): JsonObject {
|
||||||
val data = Starbound.gson.toJsonTree(SerializedForm(
|
val data = Starbound.gson.toJsonTree(SerializedForm(
|
||||||
celestialParameters, worldParameters, skyParameters, seed,
|
celestialParameters, worldParameters, skyParameters, seed,
|
||||||
if (isLegacy) Either.right(geometry.size) else Either.left(geometry),
|
if (Starbound.IS_WRITING_LEGACY_JSON) Either.right(geometry.size) else Either.left(geometry),
|
||||||
|
worldLayout
|
||||||
)) as JsonObject
|
)) as JsonObject
|
||||||
|
|
||||||
data["regionData"] = worldLayout?.toJson(isLegacy) ?: JsonNull.INSTANCE
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ class WorldTemplate(val geometry: WorldGeometry) {
|
|||||||
template.worldParameters = load.worldParameters
|
template.worldParameters = load.worldParameters
|
||||||
template.skyParameters = load.skyParameters
|
template.skyParameters = load.skyParameters
|
||||||
template.seed = load.seed
|
template.seed = load.seed
|
||||||
template.worldLayout = load.regionData.let { if (it is JsonObject) WorldLayout().fromJson(it) else null }
|
template.worldLayout = load.regionData
|
||||||
|
|
||||||
template.determineName()
|
template.determineName()
|
||||||
|
|
||||||
|
146
src/main/kotlin/ru/dbotthepony/kstarbound/json/NativeLegacy.kt
Normal file
146
src/main/kotlin/ru/dbotthepony/kstarbound/json/NativeLegacy.kt
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.json
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.TypeAdapterFactory
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
import ru.dbotthepony.kommons.gson.consumeNull
|
||||||
|
import ru.dbotthepony.kommons.util.Either
|
||||||
|
import ru.dbotthepony.kommons.util.KOptional
|
||||||
|
import ru.dbotthepony.kstarbound.Registries
|
||||||
|
import ru.dbotthepony.kstarbound.Registry
|
||||||
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
|
import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
|
||||||
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||||
|
import java.lang.reflect.Constructor
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates single point of reference for both native json and legacy json
|
||||||
|
* values
|
||||||
|
*/
|
||||||
|
abstract class NativeLegacy<NATIVE, LEGACY> {
|
||||||
|
protected abstract fun computeLegacy(value: NATIVE): LEGACY
|
||||||
|
protected abstract fun computeNative(value: LEGACY): NATIVE
|
||||||
|
|
||||||
|
protected var nativeValue: KOptional<NATIVE> = KOptional()
|
||||||
|
protected var legacyValue: KOptional<LEGACY> = KOptional()
|
||||||
|
|
||||||
|
val legacy: LEGACY get() {
|
||||||
|
if (legacyValue.isEmpty) {
|
||||||
|
val compute = computeLegacy(nativeValue.value)
|
||||||
|
legacyValue = KOptional(compute)
|
||||||
|
return compute
|
||||||
|
}
|
||||||
|
|
||||||
|
return legacyValue.value
|
||||||
|
}
|
||||||
|
|
||||||
|
val native: NATIVE get() {
|
||||||
|
if (nativeValue.isEmpty) {
|
||||||
|
val compute = computeNative(legacyValue.value)
|
||||||
|
nativeValue = KOptional(compute)
|
||||||
|
return compute
|
||||||
|
}
|
||||||
|
|
||||||
|
return nativeValue.value
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tile() : NativeLegacy<Registry.Ref<TileDefinition>, Int?>() {
|
||||||
|
constructor(tile: Registry.Entry<TileDefinition>?) : this() {
|
||||||
|
if (tile == null)
|
||||||
|
legacyValue = KOptional(65535)
|
||||||
|
else
|
||||||
|
nativeValue = KOptional(tile.ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(tile: Registry.Ref<TileDefinition>?) : this() {
|
||||||
|
if (tile == null)
|
||||||
|
legacyValue = KOptional(65535)
|
||||||
|
else
|
||||||
|
nativeValue = KOptional(tile)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeLegacy(value: Registry.Ref<TileDefinition>): Int {
|
||||||
|
return value.value?.materialId ?: 65535
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeNative(value: Int?): Registry.Ref<TileDefinition> {
|
||||||
|
value ?: return Registries.tiles.emptyRef
|
||||||
|
return Registries.tiles.ref(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TileMod() : NativeLegacy<Registry.Ref<MaterialModifier>, Int?>() {
|
||||||
|
constructor(tile: Registry.Entry<MaterialModifier>?) : this() {
|
||||||
|
if (tile == null)
|
||||||
|
legacyValue = KOptional(65535)
|
||||||
|
else
|
||||||
|
nativeValue = KOptional(tile.ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(tile: Registry.Ref<MaterialModifier>?) : this() {
|
||||||
|
if (tile == null)
|
||||||
|
legacyValue = KOptional(65535)
|
||||||
|
else
|
||||||
|
nativeValue = KOptional(tile)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeLegacy(value: Registry.Ref<MaterialModifier>): Int {
|
||||||
|
return value.value?.modId ?: 65535
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeNative(value: Int?): Registry.Ref<MaterialModifier> {
|
||||||
|
value ?: return Registries.tileModifiers.emptyRef
|
||||||
|
return Registries.tileModifiers.ref(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Adapter<L, R>(gson: Gson, left: TypeToken<L>, right: TypeToken<R>, private val constructor: Constructor<NativeLegacy<L, R>>) : TypeAdapter<NativeLegacy<L, R>>() {
|
||||||
|
private val left = gson.getAdapter(left)
|
||||||
|
private val right = gson.getAdapter(right)
|
||||||
|
private val either = gson.getAdapter(TypeToken.getParameterized(Either::class.java, left.type, right.type)) as TypeAdapter<Either<L, R>>
|
||||||
|
|
||||||
|
override fun write(out: JsonWriter, value: NativeLegacy<L, R>?) {
|
||||||
|
if (value == null)
|
||||||
|
out.nullValue()
|
||||||
|
else if (Starbound.IS_WRITING_LEGACY_JSON || value.nativeValue.isEmpty)
|
||||||
|
right.write(out, value.legacy)
|
||||||
|
else
|
||||||
|
left.write(out, value.native)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): NativeLegacy<L, R>? {
|
||||||
|
if (`in`.consumeNull())
|
||||||
|
return null
|
||||||
|
|
||||||
|
val instance = constructor.newInstance()
|
||||||
|
val either = either.read(`in`)
|
||||||
|
instance.nativeValue = either.left
|
||||||
|
instance.legacyValue = either.right
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : TypeAdapterFactory {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
|
if (NativeLegacy::class.java.isAssignableFrom(type.rawType)) {
|
||||||
|
val rawType = type.rawType as? Class<*> ?: throw RuntimeException("bro what the fuck?")
|
||||||
|
val superclass = rawType.genericSuperclass as? ParameterizedType ?: throw RuntimeException("bro what the fuck?")
|
||||||
|
|
||||||
|
return Adapter(
|
||||||
|
gson,
|
||||||
|
TypeToken.get(superclass.actualTypeArguments[0]) as TypeToken<Any>,
|
||||||
|
TypeToken.get(superclass.actualTypeArguments[1]) as TypeToken<Any>,
|
||||||
|
rawType.getDeclaredConstructor() as Constructor<NativeLegacy<Any, Any>>
|
||||||
|
) as TypeAdapter<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -148,10 +148,15 @@ class FactoryAdapter<T : Any> private constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
out.beginObject()
|
if (asJsonArray)
|
||||||
|
out.beginArray()
|
||||||
|
else
|
||||||
|
out.beginObject()
|
||||||
|
|
||||||
for (type in types) {
|
for (type in types) {
|
||||||
if (type.isFlat) {
|
if (type.isFlat) {
|
||||||
|
check(!asJsonArray)
|
||||||
|
|
||||||
val (field, adapter) = type
|
val (field, adapter) = type
|
||||||
val result = (adapter as TypeAdapter<Any>).toJsonTree((field as KProperty1<T, Any>).get(value))
|
val result = (adapter as TypeAdapter<Any>).toJsonTree((field as KProperty1<T, Any>).get(value))
|
||||||
|
|
||||||
@ -160,17 +165,26 @@ class FactoryAdapter<T : Any> private constructor(
|
|||||||
throw JsonSyntaxException("Expected JsonObject from adapter of ${type.name}, but got ${result::class.qualifiedName}")
|
throw JsonSyntaxException("Expected JsonObject from adapter of ${type.name}, but got ${result::class.qualifiedName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
out.value(result)
|
for ((k, v) in result.entrySet()) {
|
||||||
|
out.name(k)
|
||||||
|
out.value(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val (field, adapter) = type
|
val (field, adapter) = type
|
||||||
out.name(field.name)
|
|
||||||
|
if (!asJsonArray)
|
||||||
|
out.name(field.name)
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
(adapter as TypeAdapter<Any>).write(out, (field as KProperty1<T, Any>).get(value))
|
(adapter as TypeAdapter<Any>).write(out, (field as KProperty1<T, Any>).get(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.endObject()
|
if (asJsonArray)
|
||||||
|
out.endArray()
|
||||||
|
else
|
||||||
|
out.endObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(reader: JsonReader): T? {
|
override fun read(reader: JsonReader): T? {
|
||||||
|
@ -121,6 +121,10 @@ class FloatingNetworkedElement(private var value: Double = 0.0, val ops: Ops, va
|
|||||||
}
|
}
|
||||||
|
|
||||||
queue.clear()
|
queue.clear()
|
||||||
|
|
||||||
|
if (isInterpolating) {
|
||||||
|
queue.add(currentTime to value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeInitial(data: DataOutputStream, isLegacy: Boolean) {
|
override fun writeInitial(data: DataOutputStream, isLegacy: Boolean) {
|
||||||
|
@ -322,18 +322,23 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
|
|||||||
shipWorld = it
|
shipWorld = it
|
||||||
shipWorld.thread.start()
|
shipWorld.thread.start()
|
||||||
send(PlayerWarpResultPacket(true, WarpAlias.OwnShip, false))
|
send(PlayerWarpResultPacket(true, WarpAlias.OwnShip, false))
|
||||||
shipWorld.acceptPlayer(this).thenAccept {
|
|
||||||
|
server.worlds.first().acceptPlayer(this)
|
||||||
|
|
||||||
|
/*shipWorld.acceptPlayer(this).thenAccept {
|
||||||
for (conn in server.channels.connections) {
|
for (conn in server.channels.connections) {
|
||||||
if (conn.isLegacy && conn !== this) {
|
if (conn.isLegacy && conn !== this) {
|
||||||
conn.shipWorld.acceptPlayer(this)
|
conn.shipWorld.acceptPlayer(this)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server.worlds.first().acceptPlayer(this)
|
||||||
}.exceptionally {
|
}.exceptionally {
|
||||||
LOGGER.error("Shipworld of $this rejected to accept its owner", it)
|
LOGGER.error("Shipworld of $this rejected to accept its owner", it)
|
||||||
disconnect("Shipworld rejected player warp request: $it")
|
disconnect("Shipworld rejected player warp request: $it")
|
||||||
null
|
null
|
||||||
}
|
}*/
|
||||||
}.exceptionally {
|
}.exceptionally {
|
||||||
LOGGER.error("Error while initializing shipworld for $this", it)
|
LOGGER.error("Error while initializing shipworld for $this", it)
|
||||||
disconnect("Error while initializing shipworld for player: $it")
|
disconnect("Error while initializing shipworld for player: $it")
|
||||||
|
@ -72,7 +72,7 @@ class ServerWorld private constructor(
|
|||||||
player.skyVersion = skyVersion
|
player.skyVersion = skyVersion
|
||||||
|
|
||||||
player.send(WorldStartPacket(
|
player.send(WorldStartPacket(
|
||||||
templateData = template.toJson(true),
|
templateData = Starbound.writeLegacyJson { template.toJson() },
|
||||||
skyData = skyData.toByteArray(),
|
skyData = skyData.toByteArray(),
|
||||||
weatherData = ByteArray(0),
|
weatherData = ByteArray(0),
|
||||||
playerStart = playerSpawnPosition,
|
playerStart = playerSpawnPosition,
|
||||||
@ -86,7 +86,9 @@ class ServerWorld private constructor(
|
|||||||
localInterpolationMode = false,
|
localInterpolationMode = false,
|
||||||
))
|
))
|
||||||
|
|
||||||
player.sendAndFlush(CentralStructureUpdatePacket(Starbound.gson.toJsonTree(centralStructure)))
|
Starbound.writeLegacyJson {
|
||||||
|
player.sendAndFlush(CentralStructureUpdatePacket(Starbound.gson.toJsonTree(centralStructure)))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
player.sendAndFlush(JoinWorldPacket(this))
|
player.sendAndFlush(JoinWorldPacket(this))
|
||||||
}
|
}
|
||||||
@ -97,7 +99,9 @@ class ServerWorld private constructor(
|
|||||||
unpause()
|
unpause()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return CompletableFuture.supplyAsync(Supplier { doAcceptPlayer(player) }, mailbox)
|
return CompletableFuture.supplyAsync(Supplier { doAcceptPlayer(player) }, mailbox).exceptionally {
|
||||||
|
LOGGER.error("Error while accepting new player into world", it)
|
||||||
|
}
|
||||||
} catch (err: RejectedExecutionException) {
|
} catch (err: RejectedExecutionException) {
|
||||||
return CompletableFuture.failedFuture(err)
|
return CompletableFuture.failedFuture(err)
|
||||||
}
|
}
|
||||||
@ -123,7 +127,10 @@ class ServerWorld private constructor(
|
|||||||
check(!isClosed.get()) { "$this is invalid" }
|
check(!isClosed.get()) { "$this is invalid" }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return CompletableFuture.supplyAsync(Supplier { doRemovePlayer(player) }, mailbox)
|
return CompletableFuture.supplyAsync(Supplier { doRemovePlayer(player) }, mailbox).exceptionally {
|
||||||
|
LOGGER.error("Error while removing player from world", it)
|
||||||
|
null
|
||||||
|
}
|
||||||
} catch (err: RejectedExecutionException) {
|
} catch (err: RejectedExecutionException) {
|
||||||
return CompletableFuture.completedFuture(false)
|
return CompletableFuture.completedFuture(false)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ object AssetPathStack {
|
|||||||
push(value.substringBefore(':').substringBeforeLast('/'))
|
push(value.substringBefore(':').substringBeforeLast('/'))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun last() = stack.lastOrNull()
|
fun last() = stack.lastOrNull() ?: "/"
|
||||||
fun pop() = stack.removeLast()
|
fun pop() = stack.removeLast()
|
||||||
|
|
||||||
inline fun <T> block(path: String, block: (String) -> T): T {
|
inline fun <T> block(path: String, block: (String) -> T): T {
|
||||||
@ -44,11 +44,11 @@ object AssetPathStack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun remap(path: String): String {
|
fun remap(path: String): String {
|
||||||
return remap(checkNotNull(last()) { "Not reading an asset on current thread" }, path)
|
return remap(last(), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remapSafe(path: String): String {
|
fun remapSafe(path: String): String {
|
||||||
return remap(last() ?: return path, path)
|
return remap(last(), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun relativeTo(base: String, path: String): String {
|
fun relativeTo(base: String, path: String): String {
|
||||||
|
@ -43,12 +43,15 @@ abstract class AbstractPerlinNoise(val parameters: PerlinNoiseParameters) {
|
|||||||
protected val g3 by lazy { Double2DArray.allocate(parameters.scale * 2 + 2, 3) }
|
protected val g3 by lazy { Double2DArray.allocate(parameters.scale * 2 + 2, 3) }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (parameters.seed != null) {
|
if (parameters.seed != null && parameters.type != PerlinNoiseParameters.Type.UNITIALIZED) {
|
||||||
init(parameters.seed)
|
init(parameters.seed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun init(seed: Long) {
|
fun init(seed: Long) {
|
||||||
|
if (parameters.type == PerlinNoiseParameters.Type.UNITIALIZED)
|
||||||
|
return
|
||||||
|
|
||||||
isInitialized = true
|
isInitialized = true
|
||||||
this.seed = seed
|
this.seed = seed
|
||||||
|
|
||||||
@ -218,6 +221,7 @@ abstract class AbstractPerlinNoise(val parameters: PerlinNoiseParameters) {
|
|||||||
PerlinNoiseParameters.Type.PERLIN -> PerlinNoise(parameters)
|
PerlinNoiseParameters.Type.PERLIN -> PerlinNoise(parameters)
|
||||||
PerlinNoiseParameters.Type.BILLOW -> BillowNoise(parameters)
|
PerlinNoiseParameters.Type.BILLOW -> BillowNoise(parameters)
|
||||||
PerlinNoiseParameters.Type.RIDGED_MULTI -> RidgedNoise(parameters)
|
PerlinNoiseParameters.Type.RIDGED_MULTI -> RidgedNoise(parameters)
|
||||||
|
PerlinNoiseParameters.Type.UNITIALIZED -> EmptyNoise(parameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.util.random
|
||||||
|
|
||||||
|
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
|
||||||
|
|
||||||
|
class EmptyNoise(parameters: PerlinNoiseParameters) : AbstractPerlinNoise(parameters) {
|
||||||
|
init {
|
||||||
|
require(parameters.type == PerlinNoiseParameters.Type.UNITIALIZED)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(x: Double): Double {
|
||||||
|
return 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(x: Double, y: Double): Double {
|
||||||
|
return 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(x: Double, y: Double, z: Double): Double {
|
||||||
|
return 0.0
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user