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 {
|
||||
val server = IntegratedStarboundServer(File("./"))
|
||||
val world = ServerWorld.load(server, LegacyWorldStorage.file(db)).get()
|
||||
//world.thread.start()
|
||||
world.thread.start()
|
||||
|
||||
//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.BiomePlacementDistributionType
|
||||
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.io.*
|
||||
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.server.world.UniverseChunk
|
||||
import ru.dbotthepony.kstarbound.item.ItemStack
|
||||
import ru.dbotthepony.kstarbound.json.NativeLegacy
|
||||
import ru.dbotthepony.kstarbound.util.Directives
|
||||
import ru.dbotthepony.kstarbound.util.ExceptionLogger
|
||||
import ru.dbotthepony.kstarbound.util.SBPattern
|
||||
@ -155,8 +157,30 @@ object Starbound : ISBFileLocator {
|
||||
@JvmField
|
||||
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()) {
|
||||
serializeNulls()
|
||||
// serializeNulls()
|
||||
setDateFormat(DateFormat.LONG)
|
||||
setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
|
||||
setPrettyPrinting()
|
||||
@ -215,18 +239,20 @@ object Starbound : ISBFileLocator {
|
||||
registerTypeAdapter(ObjectDefinition::Adapter)
|
||||
registerTypeAdapter(StatModifier::Adapter)
|
||||
|
||||
registerTypeAdapterFactory(NativeLegacy.Companion)
|
||||
|
||||
// математические классы
|
||||
registerTypeAdapter(AABBTypeAdapter)
|
||||
registerTypeAdapter(AABBiTypeAdapter)
|
||||
registerTypeAdapter(Vector2dTypeAdapter)
|
||||
registerTypeAdapter(Vector2fTypeAdapter)
|
||||
registerTypeAdapter(Vector2iTypeAdapter)
|
||||
registerTypeAdapter(Vector3dTypeAdapter)
|
||||
registerTypeAdapter(Vector3fTypeAdapter)
|
||||
registerTypeAdapter(Vector3iTypeAdapter)
|
||||
registerTypeAdapter(Vector4iTypeAdapter)
|
||||
registerTypeAdapter(Vector4dTypeAdapter)
|
||||
registerTypeAdapter(Vector4fTypeAdapter)
|
||||
registerTypeAdapter(AABBTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(AABBiTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector2dTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector2fTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector2iTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector3dTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector3fTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector3iTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector4iTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector4dTypeAdapter.nullSafe())
|
||||
registerTypeAdapter(Vector4fTypeAdapter.nullSafe())
|
||||
registerTypeAdapterFactory(Line2d.Companion)
|
||||
registerTypeAdapterFactory(UniversePos.Companion)
|
||||
registerTypeAdapterFactory(AbstractPerlinNoise.Companion)
|
||||
@ -269,7 +295,6 @@ object Starbound : ISBFileLocator {
|
||||
registerTypeAdapter(CelestialParameters::Adapter)
|
||||
registerTypeAdapter(Particle::Adapter)
|
||||
|
||||
registerTypeAdapterFactory(BiomePlacementDistributionType.DATA_ADAPTER)
|
||||
registerTypeAdapterFactory(BiomePlacementDistributionType.DEFINITION_ADAPTER)
|
||||
registerTypeAdapterFactory(BiomePlacementItemType.DATA_ADAPTER)
|
||||
registerTypeAdapterFactory(BiomePlacementItemType.DEFINITION_ADAPTER)
|
||||
@ -278,6 +303,7 @@ object Starbound : ISBFileLocator {
|
||||
// register companion first, so it has lesser priority than dispatching adapter
|
||||
registerTypeAdapterFactory(VisitableWorldParametersType.Companion)
|
||||
registerTypeAdapterFactory(VisitableWorldParametersType.ADAPTER)
|
||||
registerTypeAdapter(WorldLayout.Companion)
|
||||
|
||||
Registries.registerAdapters(this)
|
||||
|
||||
|
@ -10,6 +10,7 @@ import com.google.gson.stream.JsonReader
|
||||
import com.google.gson.stream.JsonToken
|
||||
import com.google.gson.stream.JsonWriter
|
||||
import ru.dbotthepony.kommons.gson.consumeNull
|
||||
import ru.dbotthepony.kommons.guava.immutableMap
|
||||
import ru.dbotthepony.kstarbound.json.builder.JsonImplementation
|
||||
|
||||
@JsonImplementation(ThingDescription::class)
|
||||
@ -84,6 +85,13 @@ data class ThingDescription(
|
||||
val EMPTY = ThingDescription()
|
||||
}
|
||||
|
||||
fun toMap(): ImmutableMap<String, String> {
|
||||
return immutableMap {
|
||||
putAll(racialDescription)
|
||||
put("description", description)
|
||||
}
|
||||
}
|
||||
|
||||
fun fixDescription(newDescription: String): ThingDescription {
|
||||
return copy(
|
||||
shortdescription = if (shortdescription == "...") newDescription else shortdescription,
|
||||
|
@ -23,6 +23,7 @@ data class PerlinNoiseParameters(
|
||||
}
|
||||
|
||||
enum class Type(override val jsonName: String) : IStringSerializable {
|
||||
UNITIALIZED("uninitialized"),
|
||||
PERLIN("perlin"),
|
||||
BILLOW("billow"),
|
||||
RIDGED_MULTI("ridgedMulti");
|
||||
|
@ -1,20 +1,18 @@
|
||||
package ru.dbotthepony.kstarbound.defs.world
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import ru.dbotthepony.kstarbound.Registry
|
||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||
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
|
||||
import ru.dbotthepony.kstarbound.json.NativeLegacy
|
||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||
|
||||
@JsonFactory
|
||||
data class Biome(
|
||||
val hueShift: Double = 0.0,
|
||||
val materialHueShift: Int = 0,
|
||||
val baseName: String,
|
||||
val description: String,
|
||||
val mainBlock: Registry.Entry<TileDefinition>? = null,
|
||||
val subBlocks: ImmutableList<Registry.Entry<TileDefinition>> = ImmutableList.of(),
|
||||
val ores: ImmutableList<Pair<Registry.Entry<MaterialModifier>, Double>> = ImmutableList.of(),
|
||||
val mainBlock: NativeLegacy.Tile,
|
||||
val subBlocks: ImmutableList<NativeLegacy.Tile> = ImmutableList.of(),
|
||||
val ores: ImmutableList<Pair<NativeLegacy.TileMod, Double>> = ImmutableList.of(),
|
||||
val musicTrack: AmbientNoisesDefinition? = null,
|
||||
val ambientNoises: AmbientNoisesDefinition? = null,
|
||||
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.tile.MaterialModifier
|
||||
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.pairListAdapter
|
||||
import ru.dbotthepony.kstarbound.util.random.random
|
||||
import ru.dbotthepony.kstarbound.world.positiveModulo
|
||||
import java.util.random.RandomGenerator
|
||||
|
||||
@JsonFactory
|
||||
@ -63,9 +65,10 @@ data class BiomeDefinition(
|
||||
baseName = name,
|
||||
description = description,
|
||||
hueShift = hueShift,
|
||||
materialHueShift = ((positiveModulo(hueShift, 360.0) / 360.0) * 255.0).toInt(),
|
||||
|
||||
mainBlock = mainBlock?.entry,
|
||||
subBlocks = subBlocks?.stream()?.map { it.entry }?.filterNotNull()?.collect(ImmutableList.toImmutableList()) ?: ImmutableList.of(),
|
||||
mainBlock = NativeLegacy.Tile(mainBlock?.entry),
|
||||
subBlocks = subBlocks?.stream()?.map { NativeLegacy.Tile(it.entry) }?.filterNotNull()?.collect(ImmutableList.toImmutableList()) ?: ImmutableList.of(),
|
||||
|
||||
musicTrack = musicTrack,
|
||||
ambientNoises = ambientNoises,
|
||||
@ -77,10 +80,10 @@ data class BiomeDefinition(
|
||||
ores = (ores?.value?.evaluate(threatLevel, oresAdapter)?.map {
|
||||
it.stream()
|
||||
.filter { it.second > 0.0 }
|
||||
.map { Registries.tileModifiers[it.first] to it.second }
|
||||
.filter { it.first != null }
|
||||
.map { NativeLegacy.TileMod(Registries.tileModifiers.ref(it.first)) to it.second }
|
||||
.filter { it.first.native.isPresent }
|
||||
.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.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.google.gson.TypeAdapter
|
||||
@ -19,7 +20,9 @@ import ru.dbotthepony.kommons.gson.value
|
||||
import ru.dbotthepony.kstarbound.Registry
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.collect.WeightedList
|
||||
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
|
||||
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.JsonFlat
|
||||
import ru.dbotthepony.kstarbound.json.listAdapter
|
||||
@ -28,14 +31,14 @@ import java.util.stream.Stream
|
||||
|
||||
@JsonFactory
|
||||
data class BiomePlaceables(
|
||||
val grassMod: Registry.Entry<MaterialModifier>? = null,
|
||||
val ceilingGrassMod: Registry.Entry<MaterialModifier>? = null,
|
||||
val grassMod: NativeLegacy.TileMod = NativeLegacy.TileMod(null as Registry.Ref<MaterialModifier>?),
|
||||
val ceilingGrassMod: NativeLegacy.TileMod = NativeLegacy.TileMod(null as Registry.Ref<MaterialModifier>?),
|
||||
val grassModDensity: Double = 0.0,
|
||||
val ceilingGrassModDensity: Double = 0.0,
|
||||
val items: ImmutableList<DistributionItem> = ImmutableList.of(),
|
||||
val itemDistributions: ImmutableList<DistributionItem> = ImmutableList.of(),
|
||||
) {
|
||||
fun firstTreeVariant(): TreeVariant? {
|
||||
return items.stream()
|
||||
return itemDistributions.stream()
|
||||
.flatMap { it.data.itemStream() }
|
||||
.map { it as? Tree }
|
||||
.filterNotNull()
|
||||
@ -107,7 +110,7 @@ data class BiomePlaceables(
|
||||
))
|
||||
"grass" -> Grass(grassVariant.read(`in`))
|
||||
"bush" -> Bush(bushVariant.read(`in`))
|
||||
"tree" -> Tree(trees.read(`in`))
|
||||
"treePair" -> Tree(trees.read(`in`))
|
||||
"objectPool" -> Object(objects.read(`in`))
|
||||
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
|
||||
data class RandomDistribution(
|
||||
val blockSeed: Long,
|
||||
val randomItems: ImmutableList<Item>,
|
||||
) : DistributionData() {
|
||||
override val type: BiomePlacementDistributionType
|
||||
get() = BiomePlacementDistributionType.RANDOM
|
||||
|
||||
override fun itemStream(): Stream<Item> {
|
||||
return randomItems.stream()
|
||||
}
|
||||
}
|
||||
|
||||
@JsonFactory
|
||||
data class PeriodicDistribution(
|
||||
val modulus: Int,
|
||||
val modulusOffset: Int,
|
||||
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 }
|
||||
data class DistributionData(
|
||||
val distribution: BiomePlacementDistributionType,
|
||||
val blockSeed: Long = 0L,
|
||||
val blockProbability: Double = 0.0,
|
||||
val randomItems: ImmutableList<Item> = ImmutableList.of(),
|
||||
val modulus: Int = 0,
|
||||
val modulusOffset: Int = 0,
|
||||
val densityFunction: AbstractPerlinNoise = AbstractPerlinNoise.of(PerlinNoiseParameters()),
|
||||
val modulusDistortion: AbstractPerlinNoise = AbstractPerlinNoise.of(PerlinNoiseParameters()),
|
||||
val weightedItems: ImmutableList<Pair<Item, AbstractPerlinNoise>> = ImmutableList.of(),
|
||||
) {
|
||||
fun itemStream(): Stream<Item> {
|
||||
if (distribution == BiomePlacementDistributionType.RANDOM) {
|
||||
return randomItems.stream()
|
||||
} else {
|
||||
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.PerlinNoiseParameters
|
||||
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.JsonFlat
|
||||
import ru.dbotthepony.kstarbound.json.builder.JsonSingleton
|
||||
@ -27,8 +29,8 @@ data class BiomePlaceablesDefinition(
|
||||
val ceilingGrassModDensity: Double = 0.0,
|
||||
val items: ImmutableList<DistributionItem> = ImmutableList.of(),
|
||||
) {
|
||||
enum class Placement {
|
||||
FLOOR, CEILING, BACKGROUND, OCEAN;
|
||||
enum class Placement(override val jsonName: String) : IStringSerializable {
|
||||
FLOOR("floor"), CEILING("ceiling"), BACKGROUND("background"), OCEAN("ocean");
|
||||
}
|
||||
|
||||
// ----------- ITEMS
|
||||
@ -251,8 +253,8 @@ data class BiomePlaceablesDefinition(
|
||||
abstract fun create(self: DistributionItem, biome: BiomeDefinition.CreationParams): BiomePlaceables.DistributionData
|
||||
}
|
||||
|
||||
@JsonSingleton
|
||||
object RandomDistribution : DistributionData() {
|
||||
@JsonFactory
|
||||
data class RandomDistribution(val blockProbability: Double) : DistributionData() {
|
||||
override val type: BiomePlacementDistributionType
|
||||
get() = BiomePlacementDistributionType.RANDOM
|
||||
|
||||
@ -260,8 +262,10 @@ data class BiomePlaceablesDefinition(
|
||||
self: DistributionItem,
|
||||
biome: BiomeDefinition.CreationParams
|
||||
): BiomePlaceables.DistributionData {
|
||||
return BiomePlaceables.RandomDistribution(
|
||||
return BiomePlaceables.DistributionData(
|
||||
distribution = BiomePlacementDistributionType.RANDOM,
|
||||
blockSeed = biome.random.nextLong(),
|
||||
blockProbability = blockProbability,
|
||||
randomItems = IntStream.range(0, self.variants)
|
||||
.mapToObj { self.data.create(biome) }
|
||||
.collect(ImmutableList.toImmutableList())
|
||||
@ -291,7 +295,8 @@ data class BiomePlaceablesDefinition(
|
||||
): BiomePlaceables.DistributionData {
|
||||
val modulusOffset = if (modulus == 0) 0 else biome.random.nextInt(-modulus, modulus)
|
||||
|
||||
return BiomePlaceables.PeriodicDistribution(
|
||||
return BiomePlaceables.DistributionData(
|
||||
distribution = BiomePlacementDistributionType.PERIODIC,
|
||||
modulus = modulus,
|
||||
modulusOffset = modulusOffset,
|
||||
|
||||
@ -350,11 +355,11 @@ data class BiomePlaceablesDefinition(
|
||||
|
||||
fun create(biome: BiomeDefinition.CreationParams): BiomePlaceables {
|
||||
return BiomePlaceables(
|
||||
grassMod = grassMod.random(biome.random) { null }?.entry,
|
||||
ceilingGrassMod = ceilingGrassMod.random(biome.random) { null }?.entry,
|
||||
grassMod = NativeLegacy.TileMod(grassMod.random(biome.random) { null }?.entry),
|
||||
ceilingGrassMod = NativeLegacy.TileMod(ceilingGrassMod.random(biome.random) { null }?.entry),
|
||||
grassModDensity = grassModDensity,
|
||||
ceilingGrassModDensity = ceilingGrassModDensity,
|
||||
items = items.stream()
|
||||
itemDistributions = items.stream()
|
||||
.map { it.create(biome) }
|
||||
.collect(ImmutableList.toImmutableList())
|
||||
)
|
||||
|
@ -7,16 +7,9 @@ import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
|
||||
enum class BiomePlacementDistributionType(
|
||||
override val jsonName: String,
|
||||
val def: TypeToken<out BiomePlaceablesDefinition.DistributionData>,
|
||||
val data: TypeToken<out BiomePlaceables.DistributionData>,
|
||||
) : IStringSerializable {
|
||||
RANDOM("random",
|
||||
TypeToken.get(BiomePlaceablesDefinition.RandomDistribution::class.java),
|
||||
TypeToken.get(BiomePlaceables.RandomDistribution::class.java)
|
||||
),
|
||||
PERIODIC("periodic",
|
||||
TypeToken.get(BiomePlaceablesDefinition.PeriodicDistribution::class.java),
|
||||
TypeToken.get(BiomePlaceables.PeriodicDistribution::class.java)
|
||||
);
|
||||
RANDOM("random",TypeToken.get(BiomePlaceablesDefinition.RandomDistribution::class.java)),
|
||||
PERIODIC("periodic", TypeToken.get(BiomePlaceablesDefinition.PeriodicDistribution::class.java));
|
||||
|
||||
override fun match(name: String): Boolean {
|
||||
return name.lowercase() == jsonName
|
||||
@ -24,6 +17,5 @@ enum class BiomePlacementDistributionType(
|
||||
|
||||
companion object {
|
||||
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 modHueShift: Double,
|
||||
|
||||
@JsonFlat
|
||||
val descriptions: ThingDescription,
|
||||
val descriptions: ImmutableMap<String, String> = ImmutableMap.of(),
|
||||
val ceiling: Boolean,
|
||||
|
||||
val ephemeral: Boolean,
|
||||
val tileDamageParameters: TileDamageConfig,
|
||||
) {
|
||||
@JsonFactory
|
||||
@JsonFactory(asList = true)
|
||||
data class Shape(val image: String, val mods: ImmutableList<String>)
|
||||
|
||||
@JsonFactory
|
||||
@ -64,7 +63,7 @@ class BushVariant(
|
||||
directory = data.file?.computeDirectory() ?: "/",
|
||||
modHueShift = modHueShift,
|
||||
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,
|
||||
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.bushDamage).copy(totalHealth = data.value.health),
|
||||
modName = modName,
|
||||
|
@ -11,7 +11,9 @@ 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.gson.set
|
||||
import ru.dbotthepony.kommons.gson.value
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||
import ru.dbotthepony.kstarbound.util.random.random
|
||||
import ru.dbotthepony.kstarbound.world.UniversePos
|
||||
|
@ -1,5 +1,6 @@
|
||||
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
|
||||
@ -17,8 +18,7 @@ data class GrassVariant(
|
||||
val directory: String,
|
||||
val images: ImmutableSet<String> = ImmutableSet.of(),
|
||||
val hueShift: Double,
|
||||
@JsonFlat
|
||||
val descriptions: ThingDescription,
|
||||
val descriptions: ImmutableMap<String, String> = ImmutableMap.of(),
|
||||
val ceiling: Boolean,
|
||||
val ephemeral: Boolean,
|
||||
val tileDamageParameters: TileDamageConfig,
|
||||
@ -53,7 +53,7 @@ data class GrassVariant(
|
||||
ceiling = data.value.ceiling,
|
||||
ephemeral = data.value.ephemeral,
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.defs.world
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import ru.dbotthepony.kommons.collect.filterNotNull
|
||||
import ru.dbotthepony.kommons.gson.get
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.kommons.util.Either
|
||||
import ru.dbotthepony.kommons.vector.Vector2d
|
||||
@ -80,7 +81,7 @@ class Parallax(
|
||||
|
||||
if (isFoliage) {
|
||||
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/", "")}/"
|
||||
} else if (isStem) {
|
||||
if (treeVariant == null) return null
|
||||
|
@ -1,10 +1,8 @@
|
||||
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.JsonArray
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.TypeAdapter
|
||||
@ -24,13 +22,11 @@ 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.json.builder.JsonFactory
|
||||
import ru.dbotthepony.kstarbound.json.pairAdapter
|
||||
import ru.dbotthepony.kstarbound.json.stream
|
||||
import ru.dbotthepony.kstarbound.util.binnedChoice
|
||||
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.random
|
||||
import java.util.random.RandomGenerator
|
||||
@ -100,13 +96,13 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
||||
val read = Starbound.gson.fromJson(data, StoreData::class.java)
|
||||
|
||||
primaryBiome = read.primaryBiome
|
||||
primarySurfaceLiquid = read.primarySurfaceLiquid
|
||||
surfaceLiquid = read.surfaceLiquid
|
||||
sizeName = read.sizeName
|
||||
hueShift = read.hueShift
|
||||
skyColoring = read.skyColoring
|
||||
dayLength = read.dayLength
|
||||
blockNoiseConfig = read.blockNoiseConfig
|
||||
blendNoiseConfig = read.blendNoiseConfig
|
||||
blockNoiseConfig = read.blockNoise
|
||||
blendNoiseConfig = read.blendNoise
|
||||
blendSize = read.blendSize
|
||||
spaceLayer = read.spaceLayer
|
||||
atmosphereLayer = read.atmosphereLayer
|
||||
@ -124,23 +120,23 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
||||
// original engine operate on liquids solely with IDs
|
||||
// and we also need to network this json to legacy clients.
|
||||
// what a shame :JC:.
|
||||
if (this.primarySurfaceLiquid == null) {
|
||||
if (this.surfaceLiquid == null) {
|
||||
primarySurfaceLiquid = if (isLegacy) Either.left(0) else null
|
||||
} 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 {
|
||||
primarySurfaceLiquid = this.primarySurfaceLiquid
|
||||
primarySurfaceLiquid = this.surfaceLiquid
|
||||
}
|
||||
|
||||
val store = StoreData(
|
||||
primaryBiome = primaryBiome,
|
||||
primarySurfaceLiquid = primarySurfaceLiquid,
|
||||
surfaceLiquid = primarySurfaceLiquid,
|
||||
sizeName = sizeName,
|
||||
hueShift = hueShift,
|
||||
skyColoring = skyColoring,
|
||||
dayLength = dayLength,
|
||||
blockNoiseConfig = blockNoiseConfig,
|
||||
blendNoiseConfig = blendNoiseConfig,
|
||||
blockNoise = blockNoiseConfig,
|
||||
blendNoise = blendNoiseConfig,
|
||||
blendSize = blendSize,
|
||||
spaceLayer = spaceLayer,
|
||||
atmosphereLayer = atmosphereLayer,
|
||||
@ -158,13 +154,13 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
||||
@JsonFactory
|
||||
data class StoreData(
|
||||
val primaryBiome: String,
|
||||
val primarySurfaceLiquid: Either<Int, String>? = null,
|
||||
val surfaceLiquid: Either<Int, String>? = null,
|
||||
val sizeName: String,
|
||||
val hueShift: Double,
|
||||
val skyColoring: SkyColoring,
|
||||
val dayLength: Double,
|
||||
val blockNoiseConfig: BlockNoiseConfig? = null,
|
||||
val blendNoiseConfig: PerlinNoiseParameters? = null,
|
||||
val blockNoise: BlockNoiseConfig? = null,
|
||||
val blendNoise: PerlinNoiseParameters? = null,
|
||||
val blendSize: Double,
|
||||
val spaceLayer: Layer,
|
||||
val atmosphereLayer: Layer,
|
||||
@ -176,7 +172,7 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
||||
|
||||
var primaryBiome: String by Delegates.notNull()
|
||||
private set
|
||||
var primarySurfaceLiquid: Either<Int, String>? = null
|
||||
var surfaceLiquid: Either<Int, String>? = null
|
||||
private set
|
||||
var sizeName: String by Delegates.notNull()
|
||||
private set
|
||||
@ -454,7 +450,7 @@ class TerrestrialWorldParameters : VisitableWorldParameters() {
|
||||
parameters.sizeName = sizeName
|
||||
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.dayLength = random.nextRange(params.dayLengthRange)
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package ru.dbotthepony.kstarbound.defs.world
|
||||
|
||||
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.Registries
|
||||
@ -24,11 +26,10 @@ data class TreeVariant(
|
||||
|
||||
val foliageDirectory: String,
|
||||
// AGAIN.
|
||||
val foliageSettings: FoliageData,
|
||||
val foliageSettings: JsonElement,
|
||||
val foliageHueShift: Double,
|
||||
|
||||
@JsonFlat
|
||||
val descriptions: ThingDescription,
|
||||
val descriptions: ImmutableMap<String, String> = ImmutableMap.of(),
|
||||
val ceiling: Boolean,
|
||||
|
||||
val ephemeral: Boolean,
|
||||
@ -78,11 +79,11 @@ data class TreeVariant(
|
||||
stemHueShift = stemHueShift,
|
||||
ceiling = data.value.ceiling,
|
||||
stemDropConfig = data.value.dropConfig.deepCopy(),
|
||||
descriptions = data.value.descriptions.fixDescription(data.key),
|
||||
descriptions = data.value.descriptions.fixDescription(data.key).toMap(),
|
||||
ephemeral = data.value.ephemeral,
|
||||
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
|
||||
|
||||
foliageSettings = FoliageData("", shape = ""),
|
||||
foliageSettings = JsonNull.INSTANCE,
|
||||
foliageDropConfig = JsonObject(),
|
||||
foliageName = "",
|
||||
foliageDirectory = "/",
|
||||
@ -105,11 +106,11 @@ data class TreeVariant(
|
||||
stemHueShift = stemHueShift,
|
||||
ceiling = data.value.ceiling,
|
||||
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,
|
||||
tileDamageParameters = (data.value.damageTable?.value ?: GlobalDefaults.treeDamage).copy(totalHealth = data.value.health),
|
||||
|
||||
foliageSettings = fdata.value,
|
||||
foliageSettings = fdata.json,
|
||||
foliageDropConfig = fdata.value.dropConfig.deepCopy(),
|
||||
foliageName = fdata.key,
|
||||
foliageDirectory = fdata.file?.computeDirectory() ?: "/",
|
||||
|
@ -51,7 +51,7 @@ enum class VisitableWorldParametersType(override val jsonName: String, val token
|
||||
if (value == null)
|
||||
out.nullValue()
|
||||
else
|
||||
out.value(value.toJson(false))
|
||||
out.value(value.toJson())
|
||||
}
|
||||
|
||||
override fun read(`in`: JsonReader): VisitableWorldParameters? {
|
||||
@ -140,7 +140,7 @@ abstract class VisitableWorldParameters {
|
||||
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(
|
||||
threatLevel,
|
||||
typeName,
|
||||
@ -164,7 +164,7 @@ abstract class VisitableWorldParameters {
|
||||
data["type"] = type.jsonName
|
||||
}
|
||||
|
||||
fun toJson(isLegacy: Boolean): JsonObject {
|
||||
fun toJson(isLegacy: Boolean = Starbound.IS_WRITING_LEGACY_JSON): JsonObject {
|
||||
val data = JsonObject()
|
||||
toJson(data, isLegacy)
|
||||
return data
|
||||
|
@ -4,12 +4,17 @@ import com.google.common.collect.ImmutableList
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.TypeAdapter
|
||||
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.ints.IntArrayList
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||
import ru.dbotthepony.kommons.gson.JsonArrayCollector
|
||||
import ru.dbotthepony.kommons.gson.consumeNull
|
||||
import ru.dbotthepony.kommons.gson.set
|
||||
import ru.dbotthepony.kommons.gson.value
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.kommons.util.AABBi
|
||||
import ru.dbotthepony.kommons.util.Either
|
||||
@ -202,11 +207,11 @@ class WorldLayout {
|
||||
val layers: JsonArray,
|
||||
)
|
||||
|
||||
fun toJson(isLegacy: Boolean): JsonObject {
|
||||
fun toJson(): JsonObject {
|
||||
return Starbound.gson.toJsonTree(SerializedForm(
|
||||
worldSize, regionBlending, blockNoise, blendNoise,
|
||||
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
|
||||
}
|
||||
|
||||
@ -410,4 +415,24 @@ class WorldLayout {
|
||||
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.gson.JsonElement
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import ru.dbotthepony.kommons.util.AABBi
|
||||
import ru.dbotthepony.kommons.util.Either
|
||||
import ru.dbotthepony.kommons.vector.Vector2d
|
||||
@ -15,7 +16,7 @@ import ru.dbotthepony.kstarbound.world.Direction1D
|
||||
data class WorldStructure(
|
||||
val region: AABBi = AABBi(Vector2i.ZERO, Vector2i.ZERO),
|
||||
val anchorPosition: Vector2i = Vector2i.ZERO,
|
||||
val config: JsonElement = JsonNull.INSTANCE,
|
||||
var config: JsonElement = JsonObject(),
|
||||
val backgroundOverlays: ImmutableList<Overlay> = ImmutableList.of(),
|
||||
val foregroundOverlays: ImmutableList<Overlay> = ImmutableList.of(),
|
||||
val backgroundBlocks: ImmutableList<Block> = ImmutableList.of(),
|
||||
@ -23,6 +24,13 @@ data class WorldStructure(
|
||||
val objects: ImmutableList<Obj> = ImmutableList.of(),
|
||||
val flaggedBlocks: ImmutableMap<String, ImmutableList<Vector2i>> = ImmutableMap.of(),
|
||||
) {
|
||||
init {
|
||||
if (config == JsonNull.INSTANCE) {
|
||||
// so it is not omitted
|
||||
config = JsonObject()
|
||||
}
|
||||
}
|
||||
|
||||
@JsonFactory
|
||||
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 seed: Long = 0L,
|
||||
val size: Either<WorldGeometry, Vector2i>,
|
||||
val regionData: JsonElement = JsonNull.INSTANCE,
|
||||
val regionData: WorldLayout? = null,
|
||||
//val customTerrainRegions:
|
||||
)
|
||||
|
||||
fun toJson(isLegacy: Boolean): JsonObject {
|
||||
fun toJson(): JsonObject {
|
||||
val data = Starbound.gson.toJsonTree(SerializedForm(
|
||||
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
|
||||
|
||||
data["regionData"] = worldLayout?.toJson(isLegacy) ?: JsonNull.INSTANCE
|
||||
return data
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ class WorldTemplate(val geometry: WorldGeometry) {
|
||||
template.worldParameters = load.worldParameters
|
||||
template.skyParameters = load.skyParameters
|
||||
template.seed = load.seed
|
||||
template.worldLayout = load.regionData.let { if (it is JsonObject) WorldLayout().fromJson(it) else null }
|
||||
template.worldLayout = load.regionData
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
out.beginObject()
|
||||
if (asJsonArray)
|
||||
out.beginArray()
|
||||
else
|
||||
out.beginObject()
|
||||
|
||||
for (type in types) {
|
||||
if (type.isFlat) {
|
||||
check(!asJsonArray)
|
||||
|
||||
val (field, adapter) = type
|
||||
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}")
|
||||
}
|
||||
|
||||
out.value(result)
|
||||
for ((k, v) in result.entrySet()) {
|
||||
out.name(k)
|
||||
out.value(v)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val (field, adapter) = type
|
||||
out.name(field.name)
|
||||
|
||||
if (!asJsonArray)
|
||||
out.name(field.name)
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
(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? {
|
||||
|
@ -121,6 +121,10 @@ class FloatingNetworkedElement(private var value: Double = 0.0, val ops: Ops, va
|
||||
}
|
||||
|
||||
queue.clear()
|
||||
|
||||
if (isInterpolating) {
|
||||
queue.add(currentTime to value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeInitial(data: DataOutputStream, isLegacy: Boolean) {
|
||||
|
@ -322,18 +322,23 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
|
||||
shipWorld = it
|
||||
shipWorld.thread.start()
|
||||
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) {
|
||||
if (conn.isLegacy && conn !== this) {
|
||||
conn.shipWorld.acceptPlayer(this)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
server.worlds.first().acceptPlayer(this)
|
||||
}.exceptionally {
|
||||
LOGGER.error("Shipworld of $this rejected to accept its owner", it)
|
||||
disconnect("Shipworld rejected player warp request: $it")
|
||||
null
|
||||
}
|
||||
}*/
|
||||
}.exceptionally {
|
||||
LOGGER.error("Error while initializing shipworld for $this", it)
|
||||
disconnect("Error while initializing shipworld for player: $it")
|
||||
|
@ -72,7 +72,7 @@ class ServerWorld private constructor(
|
||||
player.skyVersion = skyVersion
|
||||
|
||||
player.send(WorldStartPacket(
|
||||
templateData = template.toJson(true),
|
||||
templateData = Starbound.writeLegacyJson { template.toJson() },
|
||||
skyData = skyData.toByteArray(),
|
||||
weatherData = ByteArray(0),
|
||||
playerStart = playerSpawnPosition,
|
||||
@ -86,7 +86,9 @@ class ServerWorld private constructor(
|
||||
localInterpolationMode = false,
|
||||
))
|
||||
|
||||
player.sendAndFlush(CentralStructureUpdatePacket(Starbound.gson.toJsonTree(centralStructure)))
|
||||
Starbound.writeLegacyJson {
|
||||
player.sendAndFlush(CentralStructureUpdatePacket(Starbound.gson.toJsonTree(centralStructure)))
|
||||
}
|
||||
} else {
|
||||
player.sendAndFlush(JoinWorldPacket(this))
|
||||
}
|
||||
@ -97,7 +99,9 @@ class ServerWorld private constructor(
|
||||
unpause()
|
||||
|
||||
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) {
|
||||
return CompletableFuture.failedFuture(err)
|
||||
}
|
||||
@ -123,7 +127,10 @@ class ServerWorld private constructor(
|
||||
check(!isClosed.get()) { "$this is invalid" }
|
||||
|
||||
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) {
|
||||
return CompletableFuture.completedFuture(false)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ object AssetPathStack {
|
||||
push(value.substringBefore(':').substringBeforeLast('/'))
|
||||
}
|
||||
|
||||
fun last() = stack.lastOrNull()
|
||||
fun last() = stack.lastOrNull() ?: "/"
|
||||
fun pop() = stack.removeLast()
|
||||
|
||||
inline fun <T> block(path: String, block: (String) -> T): T {
|
||||
@ -44,11 +44,11 @@ object AssetPathStack {
|
||||
}
|
||||
|
||||
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 {
|
||||
return remap(last() ?: return path, path)
|
||||
return remap(last(), path)
|
||||
}
|
||||
|
||||
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) }
|
||||
|
||||
init {
|
||||
if (parameters.seed != null) {
|
||||
if (parameters.seed != null && parameters.type != PerlinNoiseParameters.Type.UNITIALIZED) {
|
||||
init(parameters.seed)
|
||||
}
|
||||
}
|
||||
|
||||
fun init(seed: Long) {
|
||||
if (parameters.type == PerlinNoiseParameters.Type.UNITIALIZED)
|
||||
return
|
||||
|
||||
isInitialized = true
|
||||
this.seed = seed
|
||||
|
||||
@ -218,6 +221,7 @@ abstract class AbstractPerlinNoise(val parameters: PerlinNoiseParameters) {
|
||||
PerlinNoiseParameters.Type.PERLIN -> PerlinNoise(parameters)
|
||||
PerlinNoiseParameters.Type.BILLOW -> BillowNoise(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