species
This commit is contained in:
parent
2dd84318cc
commit
c57558af20
@ -124,6 +124,7 @@ object Starbound {
|
|||||||
private val projectiles = Object2ObjectOpenHashMap<String, ConfiguredProjectile>()
|
private val projectiles = Object2ObjectOpenHashMap<String, ConfiguredProjectile>()
|
||||||
private val parallax = Object2ObjectOpenHashMap<String, ParallaxPrototype>()
|
private val parallax = Object2ObjectOpenHashMap<String, ParallaxPrototype>()
|
||||||
private val functions = Object2ObjectOpenHashMap<String, JsonFunction>()
|
private val functions = Object2ObjectOpenHashMap<String, JsonFunction>()
|
||||||
|
private val species = Object2ObjectOpenHashMap<String, Species>()
|
||||||
|
|
||||||
private val items = Object2ObjectOpenHashMap<String, IItemDefinition>()
|
private val items = Object2ObjectOpenHashMap<String, IItemDefinition>()
|
||||||
|
|
||||||
@ -141,17 +142,18 @@ object Starbound {
|
|||||||
val STRING_INTERNER: Interner<String> = Interners.newWeakInterner()
|
val STRING_INTERNER: Interner<String> = Interners.newWeakInterner()
|
||||||
|
|
||||||
val STRING_ADAPTER: TypeAdapter<String> = object : TypeAdapter<String>() {
|
val STRING_ADAPTER: TypeAdapter<String> = object : TypeAdapter<String>() {
|
||||||
override fun write(out: JsonWriter, value: String) {
|
override fun write(out: JsonWriter, value: String?) {
|
||||||
out.value(value)
|
if (value == null)
|
||||||
|
out.nullValue()
|
||||||
|
else
|
||||||
|
out.value(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(`in`: JsonReader): String {
|
override fun read(`in`: JsonReader): String? {
|
||||||
return STRING_INTERNER.intern(TypeAdapters.STRING.read(`in`))
|
return STRING_INTERNER.intern(TypeAdapters.STRING.read(`in`) ?: return null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val NULLABLE_STRING_ADAPTER: TypeAdapter<String?> = STRING_ADAPTER.nullSafe()
|
|
||||||
|
|
||||||
val GSON: Gson = GsonBuilder()
|
val GSON: Gson = GsonBuilder()
|
||||||
.enableComplexMapKeySerialization()
|
.enableComplexMapKeySerialization()
|
||||||
.serializeNulls()
|
.serializeNulls()
|
||||||
@ -160,7 +162,7 @@ object Starbound {
|
|||||||
.setPrettyPrinting()
|
.setPrettyPrinting()
|
||||||
|
|
||||||
// чтоб строки всегда intern'ились
|
// чтоб строки всегда intern'ились
|
||||||
.registerTypeAdapter(NULLABLE_STRING_ADAPTER)
|
.registerTypeAdapter(STRING_ADAPTER)
|
||||||
|
|
||||||
// Обработчик @JsonImplementation
|
// Обработчик @JsonImplementation
|
||||||
.registerTypeAdapterFactory(JsonImplementationTypeFactory)
|
.registerTypeAdapterFactory(JsonImplementationTypeFactory)
|
||||||
@ -190,6 +192,7 @@ object Starbound {
|
|||||||
.add(parallax::get)
|
.add(parallax::get)
|
||||||
.add(functions::get)
|
.add(functions::get)
|
||||||
.add(items::get)
|
.add(items::get)
|
||||||
|
.add(species::get)
|
||||||
)
|
)
|
||||||
|
|
||||||
.create()
|
.create()
|
||||||
@ -199,11 +202,11 @@ object Starbound {
|
|||||||
return when (type) {
|
return when (type) {
|
||||||
Float::class.java -> TypeAdapters.FLOAT as TypeAdapter<T>
|
Float::class.java -> TypeAdapters.FLOAT as TypeAdapter<T>
|
||||||
Double::class.java -> TypeAdapters.DOUBLE as TypeAdapter<T>
|
Double::class.java -> TypeAdapters.DOUBLE as TypeAdapter<T>
|
||||||
String::class.java -> NULLABLE_STRING_ADAPTER as TypeAdapter<T>
|
String::class.java -> STRING_ADAPTER as TypeAdapter<T>
|
||||||
Int::class.java -> TypeAdapters.INTEGER as TypeAdapter<T>
|
Int::class.java -> TypeAdapters.INTEGER as TypeAdapter<T>
|
||||||
Long::class.java -> TypeAdapters.LONG as TypeAdapter<T>
|
Long::class.java -> TypeAdapters.LONG as TypeAdapter<T>
|
||||||
Boolean::class.java -> TypeAdapters.BOOLEAN as TypeAdapter<T>
|
Boolean::class.java -> TypeAdapters.BOOLEAN as TypeAdapter<T>
|
||||||
else -> GSON.getAdapter(type)
|
else -> GSON.getAdapter(type) as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +350,7 @@ object Starbound {
|
|||||||
loadStage(callback, this::loadMaterialModifiers, "material modifier definitions")
|
loadStage(callback, this::loadMaterialModifiers, "material modifier definitions")
|
||||||
loadStage(callback, this::loadLiquidDefinitions, "liquid definitions")
|
loadStage(callback, this::loadLiquidDefinitions, "liquid definitions")
|
||||||
loadStage(callback, this::loadItemDefinitions, "item definitions")
|
loadStage(callback, this::loadItemDefinitions, "item definitions")
|
||||||
|
loadStage(callback, this::loadSpecies, "species")
|
||||||
|
|
||||||
assetFolder = "/"
|
assetFolder = "/"
|
||||||
playerDefinition = GSON.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
playerDefinition = GSON.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
||||||
@ -531,6 +535,28 @@ object Starbound {
|
|||||||
assetFolder = null
|
assetFolder = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadSpecies(callback: (String) -> Unit) {
|
||||||
|
for (fs in fileSystems) {
|
||||||
|
for (listedFile in fs.explore().filter { it.isFile }.filter { it.name.endsWith(".species") }) {
|
||||||
|
try {
|
||||||
|
callback("Loading $listedFile")
|
||||||
|
|
||||||
|
assetFolder = listedFile.computeDirectory()
|
||||||
|
val def = GSON.fromJson(listedFile.reader(), Species::class.java)
|
||||||
|
check(species.put(def.kind, def) == null) { "Already has liquid with name ${def.kind} loaded!" }
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
LOGGER.error("Loading species definition file $listedFile", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terminateLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assetFolder = null
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadItemDefinitions(callback: (String) -> Unit) {
|
private fun loadItemDefinitions(callback: (String) -> Unit) {
|
||||||
val files = linkedMapOf(
|
val files = linkedMapOf(
|
||||||
".item" to ItemPrototype::class.java,
|
".item" to ItemPrototype::class.java,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.dbotthepony.kstarbound
|
package ru.dbotthepony.kstarbound
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
|
import ru.dbotthepony.kstarbound.defs.ColorReplacements
|
||||||
import ru.dbotthepony.kstarbound.defs.DamageType
|
import ru.dbotthepony.kstarbound.defs.DamageType
|
||||||
import ru.dbotthepony.kstarbound.defs.JsonFunction
|
import ru.dbotthepony.kstarbound.defs.JsonFunction
|
||||||
import ru.dbotthepony.kstarbound.defs.MaterialReference
|
import ru.dbotthepony.kstarbound.defs.MaterialReference
|
||||||
@ -13,6 +14,7 @@ import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
|
|||||||
import ru.dbotthepony.kstarbound.defs.item.LeveledStatusEffect
|
import ru.dbotthepony.kstarbound.defs.item.LeveledStatusEffect
|
||||||
import ru.dbotthepony.kstarbound.defs.parallax.ParallaxPrototype
|
import ru.dbotthepony.kstarbound.defs.parallax.ParallaxPrototype
|
||||||
import ru.dbotthepony.kstarbound.defs.parallax.ParallaxPrototypeLayer
|
import ru.dbotthepony.kstarbound.defs.parallax.ParallaxPrototypeLayer
|
||||||
|
import ru.dbotthepony.kstarbound.defs.player.BlueprintLearnList
|
||||||
import ru.dbotthepony.kstarbound.defs.projectile.ActionActions
|
import ru.dbotthepony.kstarbound.defs.projectile.ActionActions
|
||||||
import ru.dbotthepony.kstarbound.defs.projectile.ActionConfig
|
import ru.dbotthepony.kstarbound.defs.projectile.ActionConfig
|
||||||
import ru.dbotthepony.kstarbound.defs.projectile.ActionLoop
|
import ru.dbotthepony.kstarbound.defs.projectile.ActionLoop
|
||||||
@ -37,6 +39,9 @@ fun addStarboundJsonAdapters(builder: GsonBuilder) {
|
|||||||
with(builder) {
|
with(builder) {
|
||||||
registerTypeAdapterFactory(SBPattern.Companion)
|
registerTypeAdapterFactory(SBPattern.Companion)
|
||||||
|
|
||||||
|
registerTypeAdapter(ColorReplacements.Companion)
|
||||||
|
registerTypeAdapterFactory(BlueprintLearnList.Companion)
|
||||||
|
|
||||||
registerTypeAdapter(ColorTypeAdapter.nullSafe())
|
registerTypeAdapter(ColorTypeAdapter.nullSafe())
|
||||||
|
|
||||||
// математические классы
|
// математические классы
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.defs
|
||||||
|
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap
|
||||||
|
|
||||||
|
class ColorReplacements private constructor(private val mapping: Int2IntOpenHashMap) {
|
||||||
|
constructor(mapping: Map<Int, Int>) : this(Int2IntOpenHashMap(mapping))
|
||||||
|
|
||||||
|
fun replace(color: Int): Int {
|
||||||
|
return mapping.getOrDefault(color, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : TypeAdapter<ColorReplacements>() {
|
||||||
|
val EMPTY = ColorReplacements(Int2IntOpenHashMap())
|
||||||
|
|
||||||
|
override fun write(out: JsonWriter, value: ColorReplacements?) {
|
||||||
|
if (value == null)
|
||||||
|
out.nullValue()
|
||||||
|
else {
|
||||||
|
out.beginObject()
|
||||||
|
|
||||||
|
for ((k, v) in value.mapping) {
|
||||||
|
out.name(k.toString(16))
|
||||||
|
out.value(v.toString(16))
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): ColorReplacements? {
|
||||||
|
if (`in`.peek() == JsonToken.NULL)
|
||||||
|
return null
|
||||||
|
else if (`in`.peek() == JsonToken.STRING) {
|
||||||
|
if (`in`.nextString() != "")
|
||||||
|
throw JsonSyntaxException("Invalid color replacement definition near ${`in`.path}")
|
||||||
|
|
||||||
|
return ColorReplacements.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
val mapping = Int2IntOpenHashMap()
|
||||||
|
|
||||||
|
`in`.beginObject()
|
||||||
|
|
||||||
|
while (`in`.peek() != JsonToken.END_OBJECT) {
|
||||||
|
val k = `in`.nextName()
|
||||||
|
val v = `in`.nextString()
|
||||||
|
|
||||||
|
mapping[k.toInt(16)] = v.toInt(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
`in`.endObject()
|
||||||
|
|
||||||
|
return ColorReplacements(mapping)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs
|
package ru.dbotthepony.kstarbound.defs
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.ImmutableSet
|
||||||
|
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
||||||
|
import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
|
||||||
|
import ru.dbotthepony.kstarbound.defs.player.BlueprintLearnList
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
@ -8,11 +12,35 @@ data class Species(
|
|||||||
val kind: String,
|
val kind: String,
|
||||||
val charCreationTooltip: Tooltip,
|
val charCreationTooltip: Tooltip,
|
||||||
val nameGen: ImmutableList<String>,
|
val nameGen: ImmutableList<String>,
|
||||||
val ouchNoises: OuchNoises,
|
val ouchNoises: ImmutableList<String>,
|
||||||
|
val charGenTextLabels: ImmutableList<String>,
|
||||||
|
val skull: String,
|
||||||
|
val defaultBlueprints: BlueprintLearnList,
|
||||||
|
val headOptionAsFacialhair: Boolean = false,
|
||||||
|
val altOptionAsUndyColor: Boolean = false,
|
||||||
|
val altOptionAsHairColor: Boolean = false,
|
||||||
|
val bodyColorAsFacialMaskSubColor: Boolean = false,
|
||||||
|
val hairColorAsBodySubColor: Boolean = false,
|
||||||
|
val bodyColor: ImmutableList<ColorReplacements>,
|
||||||
|
val undyColor: ImmutableList<ColorReplacements>,
|
||||||
|
val hairColor: ImmutableList<ColorReplacements>,
|
||||||
|
val genders: ImmutableList<Gender>,
|
||||||
) {
|
) {
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
data class Tooltip(val title: String, val subTitle: String, val description: String)
|
data class Tooltip(val title: String, val subTitle: String, val description: String)
|
||||||
|
|
||||||
@JsonFactory(asList = true)
|
@JsonFactory
|
||||||
data class OuchNoises(val male: String, val female: String)
|
data class Gender(
|
||||||
|
val name: String,
|
||||||
|
val image: SpriteReference,
|
||||||
|
val characterImage: SpriteReference,
|
||||||
|
val hairGroup: String? = null,
|
||||||
|
val hair: ImmutableSet<String>,
|
||||||
|
val shirt: ImmutableSet<RegistryReference<IItemDefinition>>,
|
||||||
|
val pants: ImmutableSet<RegistryReference<IItemDefinition>>,
|
||||||
|
val facialHairGroup: String? = null,
|
||||||
|
val facialHair: ImmutableSet<String> = ImmutableSet.of(),
|
||||||
|
val facialMaskGroup: String? = null,
|
||||||
|
val facialMask: ImmutableList<String> = ImmutableList.of(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.defs.player
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
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.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap
|
||||||
|
import ru.dbotthepony.kstarbound.defs.RegistryReference
|
||||||
|
import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
|
||||||
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
||||||
|
|
||||||
|
class BlueprintLearnList private constructor(private val tiers: Int2ObjectArrayMap<ImmutableList<Entry>>) {
|
||||||
|
constructor(tiers: Map<Int, List<Entry>>) : this(Int2ObjectArrayMap<ImmutableList<Entry>>().also { for ((k, v) in tiers.entries) it.put(k, ImmutableList.copyOf(v)) })
|
||||||
|
|
||||||
|
@JsonFactory
|
||||||
|
data class Entry(val item: RegistryReference<IItemDefinition>)
|
||||||
|
|
||||||
|
operator fun get(tier: Int): List<Entry> {
|
||||||
|
return tiers.getOrDefault(tier, ImmutableList.of())
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : TypeAdapterFactory {
|
||||||
|
private val token = TypeToken.getParameterized(ImmutableList::class.java, Entry::class.java)
|
||||||
|
|
||||||
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
|
if (type.rawType == BlueprintLearnList::class.java) {
|
||||||
|
return object : TypeAdapter<BlueprintLearnList>() {
|
||||||
|
private val listCodec = gson.getAdapter(token) as TypeAdapter<ImmutableList<Entry>>
|
||||||
|
|
||||||
|
override fun write(out: JsonWriter, value: BlueprintLearnList?) {
|
||||||
|
if (value == null)
|
||||||
|
out.nullValue()
|
||||||
|
else {
|
||||||
|
out.beginObject()
|
||||||
|
|
||||||
|
for ((tier, list) in value.tiers) {
|
||||||
|
out.name("tier$tier")
|
||||||
|
listCodec.write(out, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): BlueprintLearnList? {
|
||||||
|
if (`in`.peek() == JsonToken.NULL)
|
||||||
|
return null
|
||||||
|
|
||||||
|
val tiers = Int2ObjectArrayMap<ImmutableList<Entry>>()
|
||||||
|
|
||||||
|
`in`.beginObject()
|
||||||
|
|
||||||
|
while (`in`.peek() != JsonToken.END_OBJECT) {
|
||||||
|
val name = `in`.nextName()
|
||||||
|
|
||||||
|
if (name.startsWith("tier")) {
|
||||||
|
val tier = name.substring(4).toIntOrNull() ?: throw JsonSyntaxException("Invalid tier: $name")
|
||||||
|
tiers[tier] = listCodec.read(`in`)
|
||||||
|
} else {
|
||||||
|
throw JsonSyntaxException("Invalid tier: $name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
`in`.endObject()
|
||||||
|
return BlueprintLearnList(tiers)
|
||||||
|
}
|
||||||
|
} as TypeAdapter<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableMap
|
|||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import ru.dbotthepony.kstarbound.defs.RegistryReference
|
import ru.dbotthepony.kstarbound.defs.RegistryReference
|
||||||
|
import ru.dbotthepony.kstarbound.defs.Species
|
||||||
import ru.dbotthepony.kstarbound.util.SBPattern
|
import ru.dbotthepony.kstarbound.util.SBPattern
|
||||||
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
|
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
|
import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
|
||||||
@ -20,12 +21,12 @@ data class PlayerDefinition(
|
|||||||
val blueprintAlreadyKnown: SBPattern,
|
val blueprintAlreadyKnown: SBPattern,
|
||||||
val collectableUnlock: SBPattern,
|
val collectableUnlock: SBPattern,
|
||||||
|
|
||||||
val species: ImmutableSet<String>,
|
val species: ImmutableSet<RegistryReference<Species>>,
|
||||||
val nametagColor: Color,
|
val nametagColor: Color,
|
||||||
val ageItemsEvery: Int,
|
val ageItemsEvery: Int,
|
||||||
val defaultItems: ImmutableSet<RegistryReference<IItemDefinition>>,
|
val defaultItems: ImmutableSet<RegistryReference<IItemDefinition>>,
|
||||||
|
|
||||||
val defaultBlueprints: ImmutableMap<String, ImmutableList<BlueprintUnlock>>,
|
val defaultBlueprints: BlueprintLearnList,
|
||||||
|
|
||||||
val defaultCodexes: ImmutableMap<String, ImmutableList<RegistryReference<IItemDefinition>>>,
|
val defaultCodexes: ImmutableMap<String, ImmutableList<RegistryReference<IItemDefinition>>>,
|
||||||
val metaBoundBox: AABB,
|
val metaBoundBox: AABB,
|
||||||
@ -72,7 +73,4 @@ data class PlayerDefinition(
|
|||||||
val genericScriptContexts: ImmutableMap<String, String>,
|
val genericScriptContexts: ImmutableMap<String, String>,
|
||||||
val inventory: InventoryConfig,
|
val inventory: InventoryConfig,
|
||||||
val inventoryFilters: ImmutableMap<String, InventoryFilterConfig>,
|
val inventoryFilters: ImmutableMap<String, InventoryFilterConfig>,
|
||||||
) {
|
)
|
||||||
@JsonFactory
|
|
||||||
data class BlueprintUnlock(val item: RegistryReference<IItemDefinition>)
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user