Move stuff around to reduce stress on main starbound class
This commit is contained in:
parent
86782e259e
commit
ccf696a156
src/main/kotlin/ru/dbotthepony/kstarbound
58
src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt
Normal file
58
src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt
Normal file
@ -0,0 +1,58 @@
|
||||
package ru.dbotthepony.kstarbound
|
||||
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kstarbound.defs.MovementParameters
|
||||
import java.util.concurrent.ForkJoinPool
|
||||
import java.util.concurrent.ForkJoinTask
|
||||
import java.util.concurrent.Future
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
object GlobalDefaults {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
|
||||
var defaultMovementParameters = MovementParameters()
|
||||
private set
|
||||
|
||||
private object EmptyTask : ForkJoinTask<Unit>() {
|
||||
private fun readResolve(): Any = EmptyTask
|
||||
override fun getRawResult() {
|
||||
}
|
||||
|
||||
override fun setRawResult(value: Unit?) {
|
||||
}
|
||||
|
||||
override fun exec(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> load(path: String, accept: KMutableProperty0<T>, executor: ForkJoinPool): ForkJoinTask<*> {
|
||||
val file = Starbound.locate(path)
|
||||
|
||||
if (!file.exists) {
|
||||
LOGGER.fatal("$path does not exist, expect bad things to happen!")
|
||||
return EmptyTask
|
||||
} else if (!file.isFile) {
|
||||
LOGGER.fatal("$path is not a file, expect bad things to happen!")
|
||||
return EmptyTask
|
||||
} else {
|
||||
return executor.submit {
|
||||
accept.set(Starbound.gson.fromJson(file.jsonReader(), T::class.java))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun load(log: ILoadingLog, executor: ForkJoinPool): List<ForkJoinTask<*>> {
|
||||
val tasks = ArrayList<ForkJoinTask<*>>()
|
||||
|
||||
tasks.add(load("/default_actor_movement.config", ::defaultMovementParameters, executor))
|
||||
|
||||
return listOf(executor.submit {
|
||||
val line = log.line("Loading global defaults...")
|
||||
val time = System.nanoTime()
|
||||
tasks.forEach { it.fork() }
|
||||
tasks.forEach { it.join() }
|
||||
line.text = "Loaded global defaults in ${((System.nanoTime() - time) / 1_000_000.0).toLong()}ms"
|
||||
})
|
||||
}
|
||||
}
|
@ -79,7 +79,7 @@ fun main() {
|
||||
if (cell == null) {
|
||||
IChunkCell.skip(reader)
|
||||
} else {
|
||||
cell.read(Starbound.tilesByID::get, Starbound.tileModifiersByID::get, Starbound.liquidByID::get, reader)
|
||||
cell.read(reader)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,8 +111,8 @@ fun main() {
|
||||
|
||||
//client.world!!.parallax = Starbound.parallaxAccess["garden"]
|
||||
|
||||
val item = Starbound.items.values.random()
|
||||
val rand = java.util.Random()
|
||||
val item = Registries.items.values.random()
|
||||
val rand = Random()
|
||||
|
||||
client.world!!.physics.gravity = Vector2d.ZERO
|
||||
|
||||
@ -131,7 +131,7 @@ fun main() {
|
||||
val def = Starbound.gson.fromJson(Starbound.locate("/animations/dust4/dust4.animation").reader(), AnimationDefinition::class.java)
|
||||
AssetPathStack.pop()
|
||||
|
||||
val avatar = Avatar(Starbound, UUID.randomUUID())
|
||||
val avatar = Avatar(UUID.randomUUID())
|
||||
val quest = QuestInstance(avatar, descriptor = QuestDescriptor("floran_mission1"))
|
||||
quest.init()
|
||||
quest.start()
|
||||
@ -145,7 +145,7 @@ fun main() {
|
||||
}
|
||||
}
|
||||
|
||||
println(Starbound.treasurePools["motherpoptopTreasure"]!!.value.evaluate(Random(), 2.0))
|
||||
println(Registries.treasurePools["motherpoptopTreasure"]!!.value.evaluate(Random(), 2.0))
|
||||
}
|
||||
|
||||
//ent.position += Vector2d(y = 14.0, x = -10.0)
|
||||
|
@ -17,6 +17,7 @@ import ru.dbotthepony.kstarbound.util.AssetPathStack
|
||||
import ru.dbotthepony.kstarbound.util.set
|
||||
import ru.dbotthepony.kstarbound.util.traverseJsonPath
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
inline fun <reified T : Any> ObjectRegistry(name: String, noinline key: ((T) -> String)? = null, noinline intKey: ((T) -> Int)? = null): ObjectRegistry<T> {
|
||||
@ -123,11 +124,15 @@ class RegistryObject<T : Any>(
|
||||
}
|
||||
|
||||
class ObjectRegistry<T : Any>(val clazz: KClass<T>, val name: String, val key: ((T) -> String)? = null, val intKey: ((T) -> Int)? = null) {
|
||||
private val objects = Object2ObjectOpenHashMap<String, RegistryObject<T>>()
|
||||
private val intObjects = Int2ObjectOpenHashMap<RegistryObject<T>>()
|
||||
val objects = Object2ObjectOpenHashMap<String, RegistryObject<T>>()
|
||||
val intObjects = Int2ObjectOpenHashMap<RegistryObject<T>>()
|
||||
|
||||
val view: Map<String, RegistryObject<T>> = Collections.unmodifiableMap(objects)
|
||||
val intView: Int2ObjectMap<RegistryObject<T>> = Int2ObjectMaps.unmodifiable(intObjects)
|
||||
val values get() = objects.values
|
||||
|
||||
operator fun get(index: String) = objects[index]
|
||||
operator fun get(index: Int): RegistryObject<T>? = intObjects[index]
|
||||
operator fun contains(index: String) = index in objects
|
||||
operator fun contains(index: Int) = index in intObjects
|
||||
|
||||
fun clear() {
|
||||
objects.clear()
|
||||
|
@ -1,15 +1,24 @@
|
||||
package ru.dbotthepony.kstarbound
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.internal.bind.JsonTreeReader
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kstarbound.api.IStarboundFile
|
||||
import ru.dbotthepony.kstarbound.defs.player.RecipeDefinition
|
||||
import java.util.Collections
|
||||
import java.util.LinkedList
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.ForkJoinPool
|
||||
import java.util.concurrent.ForkJoinTask
|
||||
import java.util.concurrent.Future
|
||||
|
||||
object RecipeRegistry {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
|
||||
class RecipeRegistry {
|
||||
private val recipesInternal = ArrayList<RegistryObject<RecipeDefinition>>()
|
||||
private val group2recipesInternal = Object2ObjectOpenHashMap<String, LinkedList<RegistryObject<RecipeDefinition>>>()
|
||||
private val group2recipesBacking = Object2ObjectOpenHashMap<String, List<RegistryObject<RecipeDefinition>>>()
|
||||
@ -49,4 +58,30 @@ class RecipeRegistry {
|
||||
}).add(recipe)
|
||||
}
|
||||
}
|
||||
|
||||
fun load(log: ILoadingLog, fileTree: Map<String, List<IStarboundFile>>, executor: ForkJoinPool): List<ForkJoinTask<*>> {
|
||||
val files = fileTree["recipe"] ?: return emptyList()
|
||||
|
||||
return listOf(executor.submit(Runnable {
|
||||
val line = log.line("Loading recipes...")
|
||||
val time = System.nanoTime()
|
||||
|
||||
for (listedFile in files) {
|
||||
try {
|
||||
line.text = ("Loading $listedFile")
|
||||
val json = Starbound.gson.fromJson(listedFile.reader(), JsonElement::class.java)
|
||||
val value = Starbound.gson.fromJson<RecipeDefinition>(JsonTreeReader(json), RecipeDefinition::class.java)
|
||||
add(RegistryObject(value, json, listedFile))
|
||||
} catch (err: Throwable) {
|
||||
LOGGER.error("Loading recipe definition file $listedFile", err)
|
||||
}
|
||||
|
||||
if (Starbound.terminateLoading) {
|
||||
return@Runnable
|
||||
}
|
||||
}
|
||||
|
||||
line.text = "Loaded recipes in ${((System.nanoTime() - time) / 1_000_000.0).toLong()}ms"
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
257
src/main/kotlin/ru/dbotthepony/kstarbound/Registries.kt
Normal file
257
src/main/kotlin/ru/dbotthepony/kstarbound/Registries.kt
Normal file
@ -0,0 +1,257 @@
|
||||
package ru.dbotthepony.kstarbound
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.internal.bind.JsonTreeReader
|
||||
import com.google.gson.stream.JsonReader
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kstarbound.api.IStarboundFile
|
||||
import ru.dbotthepony.kstarbound.defs.Json2Function
|
||||
import ru.dbotthepony.kstarbound.defs.JsonFunction
|
||||
import ru.dbotthepony.kstarbound.defs.Species
|
||||
import ru.dbotthepony.kstarbound.defs.StatusEffectDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.TreasurePoolDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.BackArmorItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.ChestArmorItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.CurrencyItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.FlashlightDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.HarvestingToolPrototype
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.HeadArmorItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.ItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.LegsArmorItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.LiquidItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.item.impl.MaterialItemDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.monster.MonsterSkillDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.monster.MonsterTypeDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.npc.NpcTypeDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.npc.TenantDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.`object`.ObjectDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.particle.ParticleDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.player.TechDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.projectile.ProjectileDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.quest.QuestTemplate
|
||||
import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition
|
||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.ForkJoinPool
|
||||
import java.util.concurrent.ForkJoinTask
|
||||
import java.util.concurrent.Future
|
||||
|
||||
object Registries {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
|
||||
val tiles = ObjectRegistry("tiles", TileDefinition::materialName, TileDefinition::materialId)
|
||||
val tileModifiers = ObjectRegistry("tile modifiers", MaterialModifier::modName, MaterialModifier::modId)
|
||||
val liquid = ObjectRegistry("liquid", LiquidDefinition::name, LiquidDefinition::liquidId)
|
||||
val species = ObjectRegistry("species", Species::kind)
|
||||
val statusEffects = ObjectRegistry("status effects", StatusEffectDefinition::name)
|
||||
val particles = ObjectRegistry("particles", ParticleDefinition::kind)
|
||||
val items = ObjectRegistry("items", IItemDefinition::itemName)
|
||||
val questTemplates = ObjectRegistry("quest templates", QuestTemplate::id)
|
||||
val techs = ObjectRegistry("techs", TechDefinition::name)
|
||||
val jsonFunctions = ObjectRegistry<JsonFunction>("json functions")
|
||||
val json2Functions = ObjectRegistry<Json2Function>("json 2functions")
|
||||
val npcTypes = ObjectRegistry("npc types", NpcTypeDefinition::type)
|
||||
val projectiles = ObjectRegistry("projectiles", ProjectileDefinition::projectileName)
|
||||
val tenants = ObjectRegistry("tenants", TenantDefinition::name)
|
||||
val treasurePools = ObjectRegistry("treasure pools", TreasurePoolDefinition::name)
|
||||
val monsterSkills = ObjectRegistry("monster skills", MonsterSkillDefinition::name)
|
||||
val monsterTypes = ObjectRegistry("monster types", MonsterTypeDefinition::type)
|
||||
val worldObjects = ObjectRegistry("objects", ObjectDefinition::objectName)
|
||||
|
||||
private fun loadStage(
|
||||
log: ILoadingLog,
|
||||
loader: ((String) -> Unit) -> Unit,
|
||||
name: String,
|
||||
) {
|
||||
if (Starbound.terminateLoading)
|
||||
return
|
||||
|
||||
val time = System.currentTimeMillis()
|
||||
val line = log.line("Loading $name...".also(LOGGER::info))
|
||||
|
||||
loader {
|
||||
if (Starbound.terminateLoading) {
|
||||
throw InterruptedException("Game is terminating")
|
||||
}
|
||||
|
||||
line.text = it
|
||||
}
|
||||
|
||||
line.text = ("Loaded $name in ${System.currentTimeMillis() - time}ms".also(LOGGER::info))
|
||||
}
|
||||
|
||||
private fun <T : Any> loadStage(
|
||||
log: ILoadingLog,
|
||||
registry: ObjectRegistry<T>,
|
||||
files: List<IStarboundFile>,
|
||||
) {
|
||||
loadStage(log, loader = {
|
||||
for (listedFile in files) {
|
||||
try {
|
||||
it("Loading $listedFile")
|
||||
registry.add(listedFile)
|
||||
} catch (err: Throwable) {
|
||||
LOGGER.error("Loading ${registry.name} definition file $listedFile", err)
|
||||
}
|
||||
|
||||
if (Starbound.terminateLoading) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}, registry.name)
|
||||
}
|
||||
|
||||
fun load(log: ILoadingLog, fileTree: Map<String, List<IStarboundFile>>, executor: ForkJoinPool): List<ForkJoinTask<*>> {
|
||||
val tasks = ArrayList<ForkJoinTask<*>>()
|
||||
|
||||
tasks.addAll(loadItemDefinitions(log, fileTree, executor))
|
||||
|
||||
tasks.add(executor.submit { loadStage(log, { loadJsonFunctions(it, fileTree["functions"] ?: listOf()) }, "json functions") })
|
||||
tasks.add(executor.submit { loadStage(log, { loadJson2Functions(it, fileTree["2functions"] ?: listOf()) }, "json 2functions") })
|
||||
tasks.add(executor.submit { loadStage(log, { loadTreasurePools(it, fileTree["treasurepools"] ?: listOf()) }, "treasure pools") })
|
||||
|
||||
tasks.add(executor.submit { loadStage(log, tiles, fileTree["material"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, tileModifiers, fileTree["matmod"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, liquid, fileTree["liquid"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, worldObjects, fileTree["object"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, statusEffects, fileTree["statuseffect"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, species, fileTree["species"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, particles, fileTree["particle"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, questTemplates, fileTree["questtemplate"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, techs, fileTree["tech"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, npcTypes, fileTree["npctype"] ?: listOf()) })
|
||||
// tasks.add(executor.submit { loadStage(log, projectiles, ext2files["projectile"] ?: listOf()) })
|
||||
// tasks.add(executor.submit { loadStage(log, tenants, ext2files["tenant"] ?: listOf()) })
|
||||
tasks.add(executor.submit { loadStage(log, monsterSkills, fileTree["monsterskill"] ?: listOf()) })
|
||||
// tasks.add(executor.submit { loadStage(log, _monsterTypes, ext2files["monstertype"] ?: listOf()) })
|
||||
|
||||
return tasks
|
||||
}
|
||||
|
||||
private fun loadItemDefinitions(log: ILoadingLog, files: Map<String, Collection<IStarboundFile>>, executor: ForkJoinPool): List<ForkJoinTask<*>> {
|
||||
val fileMap = mapOf(
|
||||
"item" to ItemDefinition::class.java,
|
||||
"currency" to CurrencyItemDefinition::class.java,
|
||||
"liqitem" to LiquidItemDefinition::class.java,
|
||||
"matitem" to MaterialItemDefinition::class.java,
|
||||
"flashlight" to FlashlightDefinition::class.java,
|
||||
"harvestingtool" to HarvestingToolPrototype::class.java,
|
||||
"head" to HeadArmorItemDefinition::class.java,
|
||||
"chest" to ChestArmorItemDefinition::class.java,
|
||||
"legs" to LegsArmorItemDefinition::class.java,
|
||||
"back" to BackArmorItemDefinition::class.java,
|
||||
)
|
||||
|
||||
val tasks = ArrayList<ForkJoinTask<*>>()
|
||||
|
||||
for ((ext, clazz) in fileMap) {
|
||||
val fileList = files[ext] ?: continue
|
||||
|
||||
tasks.add(executor.submit {
|
||||
val line = log.line("Loading items '$ext'")
|
||||
val time = System.nanoTime()
|
||||
|
||||
for (listedFile in fileList) {
|
||||
try {
|
||||
line.text = "Loading $listedFile"
|
||||
val json = Starbound.gson.fromJson(listedFile.reader(), JsonObject::class.java)
|
||||
val def: IItemDefinition = AssetPathStack(listedFile.computeDirectory()) { Starbound.gson.fromJson(JsonTreeReader(json), clazz) }
|
||||
items.add(def, json, listedFile)
|
||||
} catch (err: Throwable) {
|
||||
LOGGER.error("Loading item definition file $listedFile", err)
|
||||
}
|
||||
|
||||
if (Starbound.terminateLoading) {
|
||||
return@submit
|
||||
}
|
||||
}
|
||||
|
||||
line.text = "Loaded items '$ext' in ${((System.nanoTime() - time) / 1_000_000.0).toLong()}ms"
|
||||
})
|
||||
}
|
||||
|
||||
return tasks
|
||||
}
|
||||
|
||||
private fun loadJsonFunctions(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
|
||||
for (listedFile in files) {
|
||||
callback("Loading $listedFile")
|
||||
try {
|
||||
val json = Starbound.gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
|
||||
|
||||
for ((k, v) in json.entrySet()) {
|
||||
try {
|
||||
callback("Loading $k from $listedFile")
|
||||
val fn = Starbound.gson.fromJson<JsonFunction>(JsonTreeReader(v), JsonFunction::class.java)
|
||||
Registries.jsonFunctions.add(fn, v, listedFile, k)
|
||||
} catch (err: Exception) {
|
||||
LOGGER.error("Loading json function definition $k from file $listedFile", err)
|
||||
}
|
||||
}
|
||||
} catch (err: Exception) {
|
||||
LOGGER.error("Loading json function definition $listedFile", err)
|
||||
}
|
||||
|
||||
if (Starbound.terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadJson2Functions(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
|
||||
for (listedFile in files) {
|
||||
callback("Loading $listedFile")
|
||||
|
||||
try {
|
||||
val json = Starbound.gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
|
||||
|
||||
for ((k, v) in json.entrySet()) {
|
||||
try {
|
||||
callback("Loading $k from $listedFile")
|
||||
val fn = Starbound.gson.fromJson<Json2Function>(JsonTreeReader(v), Json2Function::class.java)
|
||||
Registries.json2Functions.add(fn, v, listedFile, k)
|
||||
} catch (err: Throwable) {
|
||||
LOGGER.error("Loading json 2function definition $k from file $listedFile", err)
|
||||
}
|
||||
}
|
||||
} catch (err: Exception) {
|
||||
LOGGER.error("Loading json 2function definition $listedFile", err)
|
||||
}
|
||||
|
||||
if (Starbound.terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadTreasurePools(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
|
||||
for (listedFile in files) {
|
||||
callback("Loading $listedFile")
|
||||
|
||||
try {
|
||||
val json = Starbound.gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
|
||||
|
||||
for ((k, v) in json.entrySet()) {
|
||||
try {
|
||||
callback("Loading $k from $listedFile")
|
||||
val result = Starbound.gson.fromJson<TreasurePoolDefinition>(JsonTreeReader(v), TreasurePoolDefinition::class.java)
|
||||
result.name = k
|
||||
Registries.treasurePools.add(result, v, listedFile)
|
||||
} catch (err: Throwable) {
|
||||
LOGGER.error("Loading treasure pool definition $k from file $listedFile", err)
|
||||
}
|
||||
}
|
||||
} catch (err: Exception) {
|
||||
LOGGER.error("Loading treasure pool definition $listedFile", err)
|
||||
}
|
||||
|
||||
if (Starbound.terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -86,8 +86,11 @@ import ru.dbotthepony.kstarbound.util.set
|
||||
import ru.dbotthepony.kstarbound.util.traverseJsonPath
|
||||
import java.io.*
|
||||
import java.text.DateFormat
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ForkJoinPool
|
||||
import java.util.concurrent.ForkJoinTask
|
||||
import java.util.concurrent.Future
|
||||
import java.util.function.BiConsumer
|
||||
import java.util.function.BinaryOperator
|
||||
import java.util.function.Function
|
||||
@ -101,82 +104,16 @@ object Starbound : ISBFileLocator {
|
||||
const val TICK_TIME_ADVANCE = 0.01666666666666664
|
||||
const val TICK_TIME_ADVANCE_NANOS = 16_666_666L
|
||||
|
||||
// currently it saves only 4 megabytes of ram on pretty big modpack
|
||||
// currently Caffeine one saves only 4 megabytes of RAM on pretty big modpack
|
||||
// Hrm.
|
||||
// val strings: Interner<String> = Interner.newWeakInterner()
|
||||
// val strings: Interner<String> = Interner { it }
|
||||
|
||||
// custom-made on other hand is stupidly fast,
|
||||
// and provide double the memory improvement over Caffeine one
|
||||
// Only downside is that congestion is predefined on interner creation
|
||||
// by no means this approach is the best, but it works great for this usecase
|
||||
// This is the reason why JDK is not providing "the best" tools for one specific case,
|
||||
// but the best possible tool for all possible usecases
|
||||
val strings: Interner<String> = HashTableInterner(5)
|
||||
|
||||
private val polyfill by lazy { loadInternalScript("polyfill") }
|
||||
|
||||
private val logger = LogManager.getLogger()
|
||||
|
||||
private val _tiles = ObjectRegistry("tiles", TileDefinition::materialName, TileDefinition::materialId)
|
||||
val tiles = _tiles.view
|
||||
val tilesByID = _tiles.intView
|
||||
|
||||
private val _tileModifiers = ObjectRegistry("tile modifiers", MaterialModifier::modName, MaterialModifier::modId)
|
||||
val tileModifiers = _tileModifiers.view
|
||||
val tileModifiersByID = _tileModifiers.intView
|
||||
|
||||
private val _liquid = ObjectRegistry("liquid", LiquidDefinition::name, LiquidDefinition::liquidId)
|
||||
val liquid = _liquid.view
|
||||
val liquidByID = _liquid.intView
|
||||
|
||||
private val _species = ObjectRegistry("species", Species::kind)
|
||||
val species = _species.view
|
||||
|
||||
private val _statusEffects = ObjectRegistry("status effects", StatusEffectDefinition::name)
|
||||
val statusEffects = _statusEffects.view
|
||||
|
||||
private val _particles = ObjectRegistry("particles", ParticleDefinition::kind)
|
||||
val particles = _particles.view
|
||||
|
||||
private val _items = ObjectRegistry("items", IItemDefinition::itemName)
|
||||
val items = _items.view
|
||||
|
||||
private val _questTemplates = ObjectRegistry("quest templates", QuestTemplate::id)
|
||||
val questTemplates = _questTemplates.view
|
||||
|
||||
private val _techs = ObjectRegistry("techs", TechDefinition::name)
|
||||
val techs = _techs.view
|
||||
|
||||
private val _jsonFunctions = ObjectRegistry<JsonFunction>("json functions")
|
||||
val jsonFunctions = _jsonFunctions.view
|
||||
|
||||
private val _json2Functions = ObjectRegistry<Json2Function>("json 2functions")
|
||||
val json2Functions = _json2Functions.view
|
||||
|
||||
private val _npcTypes = ObjectRegistry("npc types", NpcTypeDefinition::type)
|
||||
val npcTypes = _npcTypes.view
|
||||
|
||||
private val _projectiles = ObjectRegistry("projectiles", ProjectileDefinition::projectileName)
|
||||
val projectiles = _projectiles.view
|
||||
|
||||
private val _tenants = ObjectRegistry("tenants", TenantDefinition::name)
|
||||
val tenants = _tenants.view
|
||||
|
||||
val recipeRegistry = RecipeRegistry()
|
||||
|
||||
private val _treasurePools = ObjectRegistry("treasure pools", TreasurePoolDefinition::name)
|
||||
val treasurePools = _treasurePools.view
|
||||
|
||||
private val _monsterSkills = ObjectRegistry("monster skills", MonsterSkillDefinition::name)
|
||||
val monsterSkills = _monsterSkills.view
|
||||
|
||||
private val _monsterTypes = ObjectRegistry("monster types", MonsterTypeDefinition::type)
|
||||
val monsterTypes = _monsterTypes.view
|
||||
|
||||
private val _worldObjects = ObjectRegistry("objects", ObjectDefinition::objectName)
|
||||
val worldObjects = _worldObjects.view
|
||||
|
||||
val gson: Gson = with(GsonBuilder()) {
|
||||
serializeNulls()
|
||||
setDateFormat(DateFormat.LONG)
|
||||
@ -273,24 +210,24 @@ object Starbound : ISBFileLocator {
|
||||
registerTypeAdapterFactory(TreasurePoolDefinition.Companion)
|
||||
|
||||
registerTypeAdapterFactory(with(RegistryReferenceFactory()) {
|
||||
add(_tiles)
|
||||
add(_tileModifiers)
|
||||
add(_liquid)
|
||||
add(_items)
|
||||
add(_species)
|
||||
add(_statusEffects)
|
||||
add(_particles)
|
||||
add(_questTemplates)
|
||||
add(_techs)
|
||||
add(_jsonFunctions)
|
||||
add(_json2Functions)
|
||||
add(_npcTypes)
|
||||
add(_projectiles)
|
||||
add(_tenants)
|
||||
add(_treasurePools)
|
||||
add(_monsterSkills)
|
||||
add(_monsterTypes)
|
||||
add(_worldObjects)
|
||||
add(Registries.tiles)
|
||||
add(Registries.tileModifiers)
|
||||
add(Registries.liquid)
|
||||
add(Registries.items)
|
||||
add(Registries.species)
|
||||
add(Registries.statusEffects)
|
||||
add(Registries.particles)
|
||||
add(Registries.questTemplates)
|
||||
add(Registries.techs)
|
||||
add(Registries.jsonFunctions)
|
||||
add(Registries.json2Functions)
|
||||
add(Registries.npcTypes)
|
||||
add(Registries.projectiles)
|
||||
add(Registries.tenants)
|
||||
add(Registries.treasurePools)
|
||||
add(Registries.monsterSkills)
|
||||
add(Registries.monsterTypes)
|
||||
add(Registries.worldObjects)
|
||||
})
|
||||
|
||||
registerTypeAdapter(LongRangeAdapter)
|
||||
@ -302,26 +239,26 @@ object Starbound : ISBFileLocator {
|
||||
val f = NonExistingFile("/metamaterials.config")
|
||||
|
||||
for (material in BuiltinMetaMaterials.MATERIALS) {
|
||||
_tiles.add(material, JsonNull.INSTANCE, f)
|
||||
Registries.tiles.add(material, JsonNull.INSTANCE, f)
|
||||
}
|
||||
}
|
||||
|
||||
fun item(name: String): ItemStack {
|
||||
return ItemStack(items[name] ?: return ItemStack.EMPTY)
|
||||
return ItemStack(Registries.items[name] ?: return ItemStack.EMPTY)
|
||||
}
|
||||
|
||||
fun item(name: String, count: Long): ItemStack {
|
||||
if (count <= 0L)
|
||||
return ItemStack.EMPTY
|
||||
|
||||
return ItemStack(items[name] ?: return ItemStack.EMPTY, count = count)
|
||||
return ItemStack(Registries.items[name] ?: return ItemStack.EMPTY, count = count)
|
||||
}
|
||||
|
||||
fun item(name: String, count: Long, parameters: JsonObject): ItemStack {
|
||||
if (count <= 0L)
|
||||
return ItemStack.EMPTY
|
||||
|
||||
return ItemStack(items[name] ?: return ItemStack.EMPTY, count = count, parameters = parameters)
|
||||
return ItemStack(Registries.items[name] ?: return ItemStack.EMPTY, count = count, parameters = parameters)
|
||||
}
|
||||
|
||||
fun item(descriptor: JsonObject): ItemStack {
|
||||
@ -350,9 +287,6 @@ object Starbound : ISBFileLocator {
|
||||
@Volatile
|
||||
var terminateLoading = false
|
||||
|
||||
var defaultMovementParameters = MovementParameters()
|
||||
private set
|
||||
|
||||
fun loadJsonAsset(path: String): JsonElement? {
|
||||
val filename: String
|
||||
val jsonPath: String?
|
||||
@ -425,14 +359,14 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
state.setTableFunction("evalFunction", this) {args ->
|
||||
val name = args.getString()
|
||||
val fn = jsonFunctions[name] ?: throw NoSuchElementException("No such function $name")
|
||||
val fn = Registries.jsonFunctions[name] ?: throw NoSuchElementException("No such function $name")
|
||||
args.push(fn.value.evaluate(args.getDouble()))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("evalFunction2", this) {args ->
|
||||
val name = args.getString()
|
||||
val fn = json2Functions[name] ?: throw NoSuchElementException("No such 2function $name")
|
||||
val fn = Registries.json2Functions[name] ?: throw NoSuchElementException("No such 2function $name")
|
||||
args.push(fn.value.evaluate(args.getDouble(), args.getDouble()))
|
||||
1
|
||||
}
|
||||
@ -469,7 +403,7 @@ object Starbound : ISBFileLocator {
|
||||
state.setTableFunction("npcConfig", this) { args ->
|
||||
// Json root.npcConfig(String npcType)
|
||||
val name = args.getString()
|
||||
args.push(npcTypes[name] ?: throw NoSuchElementException("No such NPC type $name"))
|
||||
args.push(Registries.npcTypes[name] ?: throw NoSuchElementException("No such NPC type $name"))
|
||||
1
|
||||
}
|
||||
|
||||
@ -486,13 +420,13 @@ object Starbound : ISBFileLocator {
|
||||
state.setTableFunction("projectileConfig", this) { args ->
|
||||
// Json root.projectileConfig(String projectileName)
|
||||
val name = args.getString()
|
||||
args.lua.push(projectiles[name]?.json ?: throw kotlin.NoSuchElementException("No such Projectile type $name"))
|
||||
args.lua.push(Registries.projectiles[name]?.json ?: throw kotlin.NoSuchElementException("No such Projectile type $name"))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("recipesForItem", this) { args ->
|
||||
args.lua.push(JsonArray().also { a ->
|
||||
recipeRegistry.output2recipes[args.getString()]?.stream()?.map { it.toJson() }?.forEach {
|
||||
RecipeRegistry.output2recipes[args.getString()]?.stream()?.map { it.toJson() }?.forEach {
|
||||
a.add(it)
|
||||
}
|
||||
})
|
||||
@ -502,20 +436,20 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
state.setTableFunction("itemType", this) { args ->
|
||||
val name = args.getString()
|
||||
args.lua.push(items[name]?.value?.itemType ?: throw NoSuchElementException("No such item $name"))
|
||||
args.lua.push(Registries.items[name]?.value?.itemType ?: throw NoSuchElementException("No such item $name"))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("itemTags", this) { args ->
|
||||
val name = args.getString()
|
||||
args.lua.pushStrings(items[name]?.value?.itemTags ?: throw NoSuchElementException("No such item $name"))
|
||||
args.lua.pushStrings(Registries.items[name]?.value?.itemTags ?: throw NoSuchElementException("No such item $name"))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("itemHasTag", this) { args ->
|
||||
val name = args.getString()
|
||||
val tag = args.getString()
|
||||
args.push((items[name]?.value?.itemTags ?: throw NoSuchElementException("No such item $name")).contains(tag))
|
||||
args.push((Registries.items[name]?.value?.itemTags ?: throw NoSuchElementException("No such item $name")).contains(tag))
|
||||
1
|
||||
}
|
||||
|
||||
@ -562,7 +496,7 @@ object Starbound : ISBFileLocator {
|
||||
state.setTableFunction("tenantConfig", this) { args ->
|
||||
// Json root.tenantConfig(String tenantName)
|
||||
val name = args.getString()
|
||||
tenants[name]?.push(args) ?: throw NoSuchElementException("No such tenant $name")
|
||||
Registries.tenants[name]?.push(args) ?: throw NoSuchElementException("No such tenant $name")
|
||||
1
|
||||
}
|
||||
|
||||
@ -577,7 +511,7 @@ object Starbound : ISBFileLocator {
|
||||
}
|
||||
}
|
||||
|
||||
args.push(tenants.values
|
||||
args.push(Registries.tenants.values
|
||||
.stream()
|
||||
.filter { it.value.test(actualTags) }
|
||||
.sorted { a, b -> b.value.compareTo(a.value) }
|
||||
@ -592,10 +526,10 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
if (args.isStringAt()) {
|
||||
val name = args.getString()
|
||||
liquid = this.liquid[name]?.value ?: throw NoSuchElementException("No such liquid with name $name")
|
||||
liquid = Registries.liquid[name]?.value ?: throw NoSuchElementException("No such liquid with name $name")
|
||||
} else {
|
||||
val id = args.getInt()
|
||||
liquid = this.liquidByID[id]?.value ?: throw NoSuchElementException("No such liquid with ID $id")
|
||||
liquid = Registries.liquid[id]?.value ?: throw NoSuchElementException("No such liquid with ID $id")
|
||||
}
|
||||
|
||||
args.lua.pushStrings(liquid.statusEffects.stream().map { it.value?.value?.name }.filterNotNull().toList())
|
||||
@ -641,7 +575,7 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
state.setTableFunction("questConfig", this) { args ->
|
||||
val name = args.getString()
|
||||
args.push(questTemplates[name] ?: throw NoSuchElementException("No such quest template $name"))
|
||||
args.push(Registries.questTemplates[name] ?: throw NoSuchElementException("No such quest template $name"))
|
||||
1
|
||||
}
|
||||
|
||||
@ -658,7 +592,7 @@ object Starbound : ISBFileLocator {
|
||||
}
|
||||
|
||||
state.setTableFunction("isTreasurePool", this) { args ->
|
||||
args.push(args.getString() in treasurePools)
|
||||
args.push(args.getString() in Registries.treasurePools)
|
||||
1
|
||||
}
|
||||
|
||||
@ -666,19 +600,19 @@ object Starbound : ISBFileLocator {
|
||||
val name = args.getString()
|
||||
val level = args.getDouble()
|
||||
val rand = if (args.hasSomethingAt()) java.util.Random(args.getLong()) else java.util.Random()
|
||||
args.push(treasurePools[name]?.value?.evaluate(rand, level)?.stream()?.map { it.toJson() }?.filterNotNull()?.collect(JsonArrayCollector) ?: throw NoSuchElementException("No such treasure pool $name"))
|
||||
args.push(Registries.treasurePools[name]?.value?.evaluate(rand, level)?.stream()?.map { it.toJson() }?.filterNotNull()?.collect(JsonArrayCollector) ?: throw NoSuchElementException("No such treasure pool $name"))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("materialMiningSound", this) { args ->
|
||||
val name = args.getString()
|
||||
val mod = if (args.hasSomethingAt()) args.getString() else null
|
||||
val mat = tiles[name] ?: throw NoSuchElementException("No such material $name")
|
||||
val mat = Registries.tiles[name] ?: throw NoSuchElementException("No such material $name")
|
||||
|
||||
if (mod == null) {
|
||||
args.push(mat.value.miningSounds.firstOrNull())
|
||||
} else {
|
||||
val getMod = tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
|
||||
val getMod = Registries.tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
|
||||
args.push(getMod.value.miningSounds.firstOrNull() ?: mat.value.miningSounds.firstOrNull())
|
||||
}
|
||||
|
||||
@ -688,12 +622,12 @@ object Starbound : ISBFileLocator {
|
||||
state.setTableFunction("materialFootstepSound", this) { args ->
|
||||
val name = args.getString()
|
||||
val mod = if (args.hasSomethingAt()) args.getString() else null
|
||||
val mat = tiles[name] ?: throw NoSuchElementException("No such material $name")
|
||||
val mat = Registries.tiles[name] ?: throw NoSuchElementException("No such material $name")
|
||||
|
||||
if (mod == null) {
|
||||
args.push(mat.value.footstepSound)
|
||||
} else {
|
||||
val getMod = tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
|
||||
val getMod = Registries.tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
|
||||
args.push(getMod.value.footstepSound ?: mat.value.footstepSound)
|
||||
}
|
||||
|
||||
@ -703,12 +637,12 @@ object Starbound : ISBFileLocator {
|
||||
state.setTableFunction("materialHealth", this) { args ->
|
||||
val name = args.getString()
|
||||
val mod = if (args.hasSomethingAt()) args.getString() else null
|
||||
val mat = tiles[name] ?: throw NoSuchElementException("No such material $name")
|
||||
val mat = Registries.tiles[name] ?: throw NoSuchElementException("No such material $name")
|
||||
|
||||
if (mod == null) {
|
||||
args.push(mat.value.health)
|
||||
} else {
|
||||
val getMod = tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
|
||||
val getMod = Registries.tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
|
||||
args.push(getMod.value.health + mat.value.health)
|
||||
}
|
||||
|
||||
@ -717,23 +651,23 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
state.setTableFunction("materialConfig", this) { args ->
|
||||
val name = args.getString()
|
||||
args.pushFull(tiles[name])
|
||||
args.pushFull(Registries.tiles[name])
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("modConfig", this) { args ->
|
||||
val name = args.getString()
|
||||
args.pushFull(tileModifiers[name])
|
||||
args.pushFull(Registries.tileModifiers[name])
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("liquidConfig", this) { args ->
|
||||
if (args.isNumberAt()) {
|
||||
val id = args.getLong().toInt()
|
||||
args.pushFull(liquidByID[id])
|
||||
args.pushFull(Registries.liquid[id])
|
||||
} else {
|
||||
val name = args.getString()
|
||||
args.pushFull(liquid[name])
|
||||
args.pushFull(Registries.liquid[name])
|
||||
}
|
||||
|
||||
1
|
||||
@ -741,13 +675,13 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
state.setTableFunction("liquidName", this) { args ->
|
||||
val id = args.getLong().toInt()
|
||||
args.push(liquidByID[id]?.value?.name ?: throw NoSuchElementException("No such liquid with ID $id"))
|
||||
args.push(Registries.liquid[id]?.value?.name ?: throw NoSuchElementException("No such liquid with ID $id"))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("liquidId", this) { args ->
|
||||
val name = args.getString()
|
||||
args.push(liquid[name]?.value?.name ?: throw NoSuchElementException("No such liquid $name"))
|
||||
args.push(Registries.liquid[name]?.value?.name ?: throw NoSuchElementException("No such liquid $name"))
|
||||
1
|
||||
}
|
||||
|
||||
@ -755,20 +689,20 @@ object Starbound : ISBFileLocator {
|
||||
val name = args.getString()
|
||||
val param = args.getString()
|
||||
// parity: если скила не существует, то оригинальный движок просто возвращает nil
|
||||
args.push(monsterSkills[name]?.value?.config?.get(param))
|
||||
args.push(Registries.monsterSkills[name]?.value?.config?.get(param))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("monsterParameters", this) { args ->
|
||||
val name = args.getString()
|
||||
val monster = monsterTypes[name] ?: throw NoSuchElementException("No such monster type $name")
|
||||
val monster = Registries.monsterTypes[name] ?: throw NoSuchElementException("No such monster type $name")
|
||||
args.push(monster.traverseJsonPath("baseParameters"))
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("monsterMovementSettings", this) { args ->
|
||||
val name = args.getString()
|
||||
val monster = monsterTypes[name] ?: throw NoSuchElementException("No such monster type $name")
|
||||
val monster = Registries.monsterTypes[name] ?: throw NoSuchElementException("No such monster type $name")
|
||||
args.push(gson.toJsonTree(monster.value.baseParameters.movementSettings))
|
||||
1
|
||||
}
|
||||
@ -778,20 +712,20 @@ object Starbound : ISBFileLocator {
|
||||
}
|
||||
|
||||
state.setTableFunction("hasTech", this) { args ->
|
||||
args.push(args.getString() in techs)
|
||||
args.push(args.getString() in Registries.techs)
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("techType", this) { args ->
|
||||
val name = args.getString()
|
||||
val tech = techs[name] ?: throw NoSuchElementException("No such tech $name")
|
||||
val tech = Registries.techs[name] ?: throw NoSuchElementException("No such tech $name")
|
||||
args.push(tech.value.type)
|
||||
1
|
||||
}
|
||||
|
||||
state.setTableFunction("techConfig", this) { args ->
|
||||
val name = args.getString()
|
||||
val tech = techs[name] ?: throw NoSuchElementException("No such tech $name")
|
||||
val tech = Registries.techs[name] ?: throw NoSuchElementException("No such tech $name")
|
||||
tech.push(args)
|
||||
1
|
||||
}
|
||||
@ -908,50 +842,7 @@ object Starbound : ISBFileLocator {
|
||||
var playerDefinition: PlayerDefinition by WriteOnce()
|
||||
private set
|
||||
|
||||
private fun loadStage(
|
||||
log: ILoadingLog,
|
||||
loader: ((String) -> Unit) -> Unit,
|
||||
name: String,
|
||||
) {
|
||||
if (terminateLoading)
|
||||
return
|
||||
|
||||
val time = System.currentTimeMillis()
|
||||
val line = log.line("Loading $name...".also(logger::info))
|
||||
|
||||
loader {
|
||||
if (terminateLoading) {
|
||||
throw InterruptedException("Game is terminating")
|
||||
}
|
||||
|
||||
line.text = it
|
||||
}
|
||||
|
||||
line.text = ("Loaded $name in ${System.currentTimeMillis() - time}ms".also(logger::info))
|
||||
}
|
||||
|
||||
private fun <T : Any> loadStage(
|
||||
log: ILoadingLog,
|
||||
registry: ObjectRegistry<T>,
|
||||
files: List<IStarboundFile>,
|
||||
) {
|
||||
loadStage(log, loader = {
|
||||
for (listedFile in files) {
|
||||
try {
|
||||
it("Loading $listedFile")
|
||||
registry.add(listedFile)
|
||||
} catch (err: Throwable) {
|
||||
logger.error("Loading ${registry.name} definition file $listedFile", err)
|
||||
}
|
||||
|
||||
if (terminateLoading) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}, registry.name)
|
||||
}
|
||||
|
||||
private fun doInitialize(log: ILoadingLog) {
|
||||
private fun doInitialize(log: ILoadingLog, parallel: Boolean = true) {
|
||||
var time = System.currentTimeMillis()
|
||||
|
||||
if (archivePaths.isNotEmpty()) {
|
||||
@ -1006,30 +897,12 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
log.line("Finished building file index in ${System.currentTimeMillis() - time}ms".also(logger::info))
|
||||
|
||||
val pool = ForkJoinPool.commonPool()
|
||||
val tasks = ArrayList<ForkJoinTask<*>>()
|
||||
val pool = if (parallel) ForkJoinPool.commonPool() else ForkJoinPool(1)
|
||||
|
||||
tasks.add(pool.submit { loadStage(log, { loadItemDefinitions(it, ext2files) }, "item definitions") })
|
||||
|
||||
tasks.add(pool.submit { loadStage(log, { loadJsonFunctions(it, ext2files["functions"] ?: listOf()) }, "json functions") })
|
||||
tasks.add(pool.submit { loadStage(log, { loadJson2Functions(it, ext2files["2functions"] ?: listOf()) }, "json 2functions") })
|
||||
tasks.add(pool.submit { loadStage(log, { loadRecipes(it, ext2files["recipe"] ?: listOf()) }, "recipes") })
|
||||
tasks.add(pool.submit { loadStage(log, { loadTreasurePools(it, ext2files["treasurepools"] ?: listOf()) }, "treasure pools") })
|
||||
|
||||
tasks.add(pool.submit { loadStage(log, _tiles, ext2files["material"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _tileModifiers, ext2files["matmod"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _liquid, ext2files["liquid"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _worldObjects, ext2files["object"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _statusEffects, ext2files["statuseffect"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _species, ext2files["species"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _particles, ext2files["particle"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _questTemplates, ext2files["questtemplate"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _techs, ext2files["tech"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _npcTypes, ext2files["npctype"] ?: listOf()) })
|
||||
// tasks.add(pool.submit { loadStage(log, _projectiles, ext2files["projectile"] ?: listOf()) })
|
||||
// tasks.add(pool.submit { loadStage(log, _tenants, ext2files["tenant"] ?: listOf()) })
|
||||
tasks.add(pool.submit { loadStage(log, _monsterSkills, ext2files["monsterskill"] ?: listOf()) })
|
||||
// tasks.add(pool.submit { loadStage(log, _monsterTypes, ext2files["monstertype"] ?: listOf()) })
|
||||
tasks.addAll(Registries.load(log, ext2files, pool))
|
||||
tasks.addAll(RecipeRegistry.load(log, ext2files, pool))
|
||||
tasks.addAll(GlobalDefaults.load(log, pool))
|
||||
|
||||
AssetPathStack.block("/") {
|
||||
//playerDefinition = gson.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
||||
@ -1037,7 +910,8 @@ object Starbound : ISBFileLocator {
|
||||
|
||||
tasks.forEach { it.join() }
|
||||
|
||||
defaultMovementParameters = gson.fromJson(jsonReader("/default_actor_movement.config"))!!
|
||||
if (!parallel)
|
||||
pool.shutdown()
|
||||
|
||||
initializing = false
|
||||
initialized = true
|
||||
@ -1077,134 +951,5 @@ object Starbound : ISBFileLocator {
|
||||
initCallbacks.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadItemDefinitions(callback: (String) -> Unit, files: Map<String, Collection<IStarboundFile>>) {
|
||||
val fileMap = mapOf(
|
||||
"item" to ItemDefinition::class.java,
|
||||
"currency" to CurrencyItemDefinition::class.java,
|
||||
"liqitem" to LiquidItemDefinition::class.java,
|
||||
"matitem" to MaterialItemDefinition::class.java,
|
||||
"flashlight" to FlashlightDefinition::class.java,
|
||||
"harvestingtool" to HarvestingToolPrototype::class.java,
|
||||
"head" to HeadArmorItemDefinition::class.java,
|
||||
"chest" to ChestArmorItemDefinition::class.java,
|
||||
"legs" to LegsArmorItemDefinition::class.java,
|
||||
"back" to BackArmorItemDefinition::class.java,
|
||||
)
|
||||
|
||||
for ((ext, clazz) in fileMap) {
|
||||
val fileList = files[ext] ?: continue
|
||||
|
||||
for (listedFile in fileList) {
|
||||
try {
|
||||
callback("Loading $listedFile")
|
||||
val json = gson.fromJson(listedFile.reader(), JsonObject::class.java)
|
||||
val def: IItemDefinition = AssetPathStack(listedFile.computeDirectory()) { gson.fromJson(JsonTreeReader(json), clazz) }
|
||||
_items.add(def, json, listedFile)
|
||||
} catch (err: Throwable) {
|
||||
logger.error("Loading item definition file $listedFile", err)
|
||||
}
|
||||
|
||||
if (terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadJsonFunctions(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
|
||||
for (listedFile in files) {
|
||||
callback("Loading $listedFile")
|
||||
try {
|
||||
val json = gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
|
||||
|
||||
for ((k, v) in json.entrySet()) {
|
||||
try {
|
||||
callback("Loading $k from $listedFile")
|
||||
val fn = gson.fromJson<JsonFunction>(JsonTreeReader(v), JsonFunction::class.java)
|
||||
_jsonFunctions.add(fn, v, listedFile, k)
|
||||
} catch (err: Exception) {
|
||||
logger.error("Loading json function definition $k from file $listedFile", err)
|
||||
}
|
||||
}
|
||||
} catch (err: Exception) {
|
||||
logger.error("Loading json function definition $listedFile", err)
|
||||
}
|
||||
|
||||
if (terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadJson2Functions(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
|
||||
for (listedFile in files) {
|
||||
callback("Loading $listedFile")
|
||||
|
||||
try {
|
||||
val json = gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
|
||||
|
||||
for ((k, v) in json.entrySet()) {
|
||||
try {
|
||||
callback("Loading $k from $listedFile")
|
||||
val fn = gson.fromJson<Json2Function>(JsonTreeReader(v), Json2Function::class.java)
|
||||
_json2Functions.add(fn, v, listedFile, k)
|
||||
} catch (err: Throwable) {
|
||||
logger.error("Loading json 2function definition $k from file $listedFile", err)
|
||||
}
|
||||
}
|
||||
} catch (err: Exception) {
|
||||
logger.error("Loading json 2function definition $listedFile", err)
|
||||
}
|
||||
|
||||
if (terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadTreasurePools(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
|
||||
for (listedFile in files) {
|
||||
callback("Loading $listedFile")
|
||||
|
||||
try {
|
||||
val json = gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
|
||||
|
||||
for ((k, v) in json.entrySet()) {
|
||||
try {
|
||||
callback("Loading $k from $listedFile")
|
||||
val result = gson.fromJson<TreasurePoolDefinition>(JsonTreeReader(v), TreasurePoolDefinition::class.java)
|
||||
result.name = k
|
||||
_treasurePools.add(result, v, listedFile)
|
||||
} catch (err: Throwable) {
|
||||
logger.error("Loading treasure pool definition $k from file $listedFile", err)
|
||||
}
|
||||
}
|
||||
} catch (err: Exception) {
|
||||
logger.error("Loading treasure pool definition $listedFile", err)
|
||||
}
|
||||
|
||||
if (terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadRecipes(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
|
||||
for (listedFile in files) {
|
||||
try {
|
||||
callback("Loading $listedFile")
|
||||
val json = gson.fromJson(listedFile.reader(), JsonElement::class.java)
|
||||
val value = gson.fromJson<RecipeDefinition>(JsonTreeReader(json), RecipeDefinition::class.java)
|
||||
recipeRegistry.add(RegistryObject(value, json, listedFile))
|
||||
} catch (err: Throwable) {
|
||||
logger.error("Loading recipe definition file $listedFile", err)
|
||||
}
|
||||
|
||||
if (terminateLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import com.github.benmanes.caffeine.cache.Scheduler
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.lwjgl.opengl.GL45.*
|
||||
import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf
|
||||
import ru.dbotthepony.kstarbound.Registries
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.client.StarboundClient
|
||||
import ru.dbotthepony.kstarbound.client.gl.*
|
||||
@ -49,14 +50,14 @@ class TileRenderers(val client: StarboundClient) {
|
||||
|
||||
fun getMaterialRenderer(defName: String): TileRenderer {
|
||||
return matCache.get(defName) {
|
||||
val def = Starbound.tiles[defName] // TODO: Пустой рендерер
|
||||
val def = Registries.tiles[defName] // TODO: Пустой рендерер
|
||||
TileRenderer(this, def!!.value)
|
||||
}
|
||||
}
|
||||
|
||||
fun getModifierRenderer(defName: String): TileRenderer {
|
||||
return modCache.get(defName) {
|
||||
val def = Starbound.tileModifiers[defName] // TODO: Пустой рендерер
|
||||
val def = Registries.tileModifiers[defName] // TODO: Пустой рендерер
|
||||
TileRenderer(this, def!!.value)
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class RegistryReferenceFactory : TypeAdapterFactory {
|
||||
}
|
||||
|
||||
fun <T : Any> add(registry: ObjectRegistry<T>): RegistryReferenceFactory {
|
||||
return add(registry.clazz.java, registry.view::get, registry.name)
|
||||
return add(registry.clazz.java, registry::get, registry.name)
|
||||
}
|
||||
|
||||
inline fun <reified T: Any> add(noinline resolver: (String) -> RegistryObject<T>?, name: String) = add(T::class.java, resolver, name)
|
||||
|
@ -6,6 +6,7 @@ import com.google.gson.JsonPrimitive
|
||||
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||
import ru.dbotthepony.kstarbound.Registries
|
||||
import ru.dbotthepony.kstarbound.RegistryObject
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.defs.player.TechDefinition
|
||||
@ -21,7 +22,7 @@ import kotlin.collections.ArrayList
|
||||
*
|
||||
* [Avatar] реализует Lua интерфейс `player`.
|
||||
*/
|
||||
class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
class Avatar(val uniqueId: UUID) {
|
||||
enum class EssentialSlot {
|
||||
BEAM_AXE,
|
||||
WIRE_TOOL,
|
||||
@ -61,7 +62,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
* Teaches the player any recipes which can be used to craft the specified item.
|
||||
*/
|
||||
fun giveBlueprint(name: String): Boolean {
|
||||
val item = starbound.item(name).conciseToNull() ?: return false
|
||||
val item = Starbound.item(name).conciseToNull() ?: return false
|
||||
|
||||
if (knownBlueprints.add(item)) {
|
||||
newBlueprints.add(item)
|
||||
@ -75,7 +76,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
* Returns `true` if the player knows one or more recipes to create the specified item and `false` otherwise.
|
||||
*/
|
||||
fun blueprintKnown(name: String): Boolean {
|
||||
return (starbound.item(name).conciseToNull() ?: return false) in knownBlueprints
|
||||
return (Starbound.item(name).conciseToNull() ?: return false) in knownBlueprints
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,9 +84,9 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
*/
|
||||
private fun blueprintKnown(name: JsonElement): Boolean {
|
||||
if (name is JsonPrimitive) {
|
||||
return (starbound.item(name.asString).conciseToNull() ?: return false) in knownBlueprints
|
||||
return (Starbound.item(name.asString).conciseToNull() ?: return false) in knownBlueprints
|
||||
} else if (name is JsonObject) {
|
||||
return (starbound.item(name).conciseToNull() ?: return false) in knownBlueprints
|
||||
return (Starbound.item(name).conciseToNull() ?: return false) in knownBlueprints
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@ -98,9 +99,9 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
val item: ItemStack
|
||||
|
||||
if (name is JsonPrimitive) {
|
||||
item = starbound.item(name.asString).conciseToNull() ?: return false
|
||||
item = Starbound.item(name.asString).conciseToNull() ?: return false
|
||||
} else if (name is JsonObject) {
|
||||
item = starbound.item(name).conciseToNull() ?: return false
|
||||
item = Starbound.item(name).conciseToNull() ?: return false
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@ -117,14 +118,14 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
* Adds the specified tech to the player's list of available (unlockable) techs.
|
||||
*/
|
||||
fun makeTechAvailable(name: String): Boolean {
|
||||
return availableTechs.add(starbound.techs[name] ?: return false)
|
||||
return availableTechs.add(Registries.techs[name] ?: return false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified tech from player's list of available (unlockable) techs.
|
||||
*/
|
||||
fun makeTechUnavailable(name: String): Boolean {
|
||||
val tech = starbound.techs[name] ?: return false
|
||||
val tech = Registries.techs[name] ?: return false
|
||||
|
||||
if (availableTechs.remove(tech)) {
|
||||
enabledTechs.remove(tech)
|
||||
@ -139,7 +140,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
* Unlocks the specified tech, allowing it to be equipped through the tech GUI.
|
||||
*/
|
||||
fun enableTech(name: String): Boolean {
|
||||
val tech = starbound.techs[name] ?: return false
|
||||
val tech = Registries.techs[name] ?: return false
|
||||
availableTechs.add(tech)
|
||||
return enabledTechs.add(tech)
|
||||
}
|
||||
@ -148,7 +149,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
* Equips the specified tech.
|
||||
*/
|
||||
fun equipTech(name: String): Boolean {
|
||||
val tech = starbound.techs[name] ?: return false
|
||||
val tech = Registries.techs[name] ?: return false
|
||||
availableTechs.add(tech)
|
||||
enabledTechs.add(tech)
|
||||
return equippedTechs.put(tech.value.type, tech) != tech
|
||||
@ -158,7 +159,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
* Unequips the specified tech.
|
||||
*/
|
||||
fun unequipTech(name: String): Boolean {
|
||||
val tech = starbound.techs[name] ?: return false
|
||||
val tech = Registries.techs[name] ?: return false
|
||||
return equippedTechs.remove(tech.value.type) == tech
|
||||
}
|
||||
|
||||
@ -323,20 +324,20 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
lua.setTableClosure("addCurrency", this) { addCurrency(it.getString(), it.getLong()) }
|
||||
lua.setTableFunction("consumeCurrency", this) { it.lua.push(consumeCurrency(it.getString(), it.getLong())); 1 }
|
||||
lua.setTableClosure("cleanupItems", this) { cleanupItems() }
|
||||
lua.setTableClosure("giveItem", this) { giveItem(starbound.item(it.getValue())) }
|
||||
lua.setTableClosure("giveItem", this) { giveItem(Starbound.item(it.getValue())) }
|
||||
|
||||
lua.setTableFunction("hasItem", this) {
|
||||
it.lua.push(hasItem(starbound.item(it.getValue()), it.getBoolOrNull() ?: false))
|
||||
it.lua.push(hasItem(Starbound.item(it.getValue()), it.getBoolOrNull() ?: false))
|
||||
1
|
||||
}
|
||||
|
||||
lua.setTableFunction("hasCountOfItem", this) {
|
||||
it.lua.push(hasCountOfItem(starbound.item(it.getValue()), it.getBoolOrNull() ?: false))
|
||||
it.lua.push(hasCountOfItem(Starbound.item(it.getValue()), it.getBoolOrNull() ?: false))
|
||||
1
|
||||
}
|
||||
|
||||
lua.setTableFunction("consumeItem", this) {
|
||||
it.lua.push(consumeItem(starbound.item(it.getValue()), it.getBoolOrNull() ?: false, it.getBoolOrNull() ?: false).toJson())
|
||||
it.lua.push(consumeItem(Starbound.item(it.getValue()), it.getBoolOrNull() ?: false, it.getBoolOrNull() ?: false).toJson())
|
||||
1
|
||||
}
|
||||
|
||||
@ -415,7 +416,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
|
||||
lua.setTableClosure("giveEssentialItem", this) {
|
||||
val name = it.getString()
|
||||
val item = starbound.item(it.getValue())
|
||||
val item = Starbound.item(it.getValue())
|
||||
val slot = essentialSlotsMap[name] ?: throw IllegalArgumentException("Invalid slot '$name'")
|
||||
giveEssentialItem(slot, item)
|
||||
}
|
||||
@ -435,7 +436,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
|
||||
lua.setTableClosure("setEquippedItem", this) {
|
||||
val name = it.getString()
|
||||
val item = starbound.item(it.getValue())
|
||||
val item = Starbound.item(it.getValue())
|
||||
val slot = equipmentSlotsMap[name] ?: throw IllegalArgumentException("Invalid slot '$name'")
|
||||
setEquippedItem(slot, item)
|
||||
}
|
||||
@ -446,7 +447,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) {
|
||||
}
|
||||
|
||||
lua.setTableClosure("setSwapSlotItem", this) {
|
||||
cursorItem = starbound.item(it.getValue())
|
||||
cursorItem = Starbound.item(it.getValue())
|
||||
}
|
||||
|
||||
lua.setTableFunction("startQuest", this) {
|
||||
|
@ -5,6 +5,8 @@ import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kstarbound.Registries
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.defs.quest.QuestTemplate
|
||||
import ru.dbotthepony.kstarbound.lua.LuaState
|
||||
import ru.dbotthepony.kstarbound.lua.MessageHandler
|
||||
@ -20,7 +22,7 @@ class QuestInstance(
|
||||
val serverID: UUID? = null,
|
||||
val worldID: String? = null
|
||||
) {
|
||||
val template: QuestTemplate = avatar.starbound.questTemplates[descriptor.templateId]?.value ?: throw IllegalArgumentException("No such quest template ${descriptor.templateId}")
|
||||
val template: QuestTemplate = Registries.questTemplates[descriptor.templateId]?.value ?: throw IllegalArgumentException("No such quest template ${descriptor.templateId}")
|
||||
val id get() = descriptor.questId
|
||||
|
||||
val lua = LuaState()
|
||||
@ -70,7 +72,7 @@ class QuestInstance(
|
||||
}
|
||||
|
||||
private fun addReward(value: JsonElement) {
|
||||
val item = avatar.starbound.item(value)
|
||||
val item = Starbound.item(value)
|
||||
|
||||
if (!item.isEmpty) {
|
||||
rewards.add(item)
|
||||
@ -101,7 +103,7 @@ class QuestInstance(
|
||||
lua.setTableClosure("complete", this) { complete() }
|
||||
lua.setTableClosure("fail", this) { fail() }
|
||||
lua.setTableClosure("setCanTurnIn", this) { canTurnIn = it.getBool() }
|
||||
lua.setTableFunction("questDescriptor", this) { it.lua.push(avatar.starbound.gson.toJsonTree(descriptor)); 1 }
|
||||
lua.setTableFunction("questDescriptor", this) { it.lua.push(Starbound.gson.toJsonTree(descriptor)); 1 }
|
||||
lua.setTableFunction("questId", this) { it.lua.push(id); 1 }
|
||||
lua.setTableFunction("templateId", this) { it.lua.push(template.id); 1 }
|
||||
lua.setTableFunction("seed", this) { it.lua.push(seed); 1 }
|
||||
@ -120,7 +122,7 @@ class QuestInstance(
|
||||
|
||||
lua.pop()
|
||||
|
||||
avatar.starbound.pushLuaAPI(lua)
|
||||
Starbound.pushLuaAPI(lua)
|
||||
avatar.pushLuaAPI(lua)
|
||||
lua.exposeConfig(template.scriptConfig)
|
||||
}
|
||||
@ -162,7 +164,7 @@ class QuestInstance(
|
||||
if (!isInitialized) {
|
||||
isInitialized = true
|
||||
|
||||
val script = avatar.starbound.locate(template.script.fullPath)
|
||||
val script = Starbound.locate(template.script.fullPath)
|
||||
|
||||
if (!script.isFile) {
|
||||
LOGGER.error("Quest ${template.id} specifies ${template.script.fullPath} as its script, but it is not a file or does not exist!")
|
||||
|
@ -35,15 +35,10 @@ interface IChunkCell : IStruct2i {
|
||||
var envBiome: Int
|
||||
var isIndestructible: Boolean
|
||||
|
||||
fun read(
|
||||
materialAccess: (Int) -> RegistryObject<TileDefinition>?,
|
||||
modifierAccess: (Int) -> RegistryObject<MaterialModifier>?,
|
||||
liquidAccess: (Int) -> RegistryObject<LiquidDefinition>?,
|
||||
stream: DataInputStream
|
||||
) {
|
||||
foreground.read(materialAccess, modifierAccess, stream)
|
||||
background.read(materialAccess, modifierAccess, stream)
|
||||
liquid.read(liquidAccess, stream)
|
||||
fun read(stream: DataInputStream) {
|
||||
foreground.read(stream)
|
||||
background.read(stream)
|
||||
liquid.read(stream)
|
||||
|
||||
stream.skipNBytes(1) // collisionMap
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.kstarbound.world.api
|
||||
|
||||
import ru.dbotthepony.kstarbound.Registries
|
||||
import ru.dbotthepony.kstarbound.RegistryObject
|
||||
import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition
|
||||
import java.io.DataInputStream
|
||||
@ -10,11 +11,8 @@ interface ILiquidState {
|
||||
var pressure: Float
|
||||
var isInfinite: Boolean
|
||||
|
||||
fun read(
|
||||
liquidAccess: (Int) -> RegistryObject<LiquidDefinition>?,
|
||||
stream: DataInputStream
|
||||
) {
|
||||
def = liquidAccess(stream.readUnsignedByte())?.value
|
||||
fun read(stream: DataInputStream) {
|
||||
def = Registries.liquid[stream.readUnsignedByte()]?.value
|
||||
level = stream.readFloat()
|
||||
pressure = stream.readFloat()
|
||||
isInfinite = stream.readBoolean()
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.kstarbound.world.api
|
||||
|
||||
import ru.dbotthepony.kstarbound.Registries
|
||||
import ru.dbotthepony.kstarbound.RegistryObject
|
||||
import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
|
||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||
@ -33,15 +34,11 @@ interface ITileState {
|
||||
}
|
||||
}
|
||||
|
||||
fun read(
|
||||
materialAccess: (Int) -> RegistryObject<TileDefinition>?,
|
||||
modifierAccess: (Int) -> RegistryObject<MaterialModifier>?,
|
||||
stream: DataInputStream
|
||||
) {
|
||||
material = materialAccess(stream.readUnsignedShort())?.value ?: BuiltinMetaMaterials.EMPTY
|
||||
fun read(stream: DataInputStream) {
|
||||
material = Registries.tiles[stream.readUnsignedShort()]?.value ?: BuiltinMetaMaterials.EMPTY
|
||||
setHueShift(stream.read())
|
||||
color = TileColor.of(stream.read())
|
||||
modifier = modifierAccess(stream.readUnsignedShort())?.value
|
||||
modifier = Registries.tileModifiers[stream.readUnsignedShort()]?.value
|
||||
setModHueShift(stream.read())
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.google.gson.JsonObject
|
||||
import com.google.gson.TypeAdapter
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||
import ru.dbotthepony.kstarbound.Registries
|
||||
import ru.dbotthepony.kstarbound.RegistryObject
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.client.world.ClientWorld
|
||||
@ -29,7 +30,7 @@ open class WorldObject(
|
||||
) : JsonDriven(prototype.file.computeDirectory()) {
|
||||
constructor(world: World<*, *>, data: JsonObject) : this(
|
||||
world,
|
||||
Starbound.worldObjects[data["name"]?.asString ?: throw IllegalArgumentException("Missing object name")] ?: throw IllegalArgumentException("No such object defined for '${data["name"]}'"),
|
||||
Registries.worldObjects[data["name"]?.asString ?: throw IllegalArgumentException("Missing object name")] ?: throw IllegalArgumentException("No such object defined for '${data["name"]}'"),
|
||||
data.get("tilePosition", vectors) { throw IllegalArgumentException("No tilePosition was present in saved data") }
|
||||
) {
|
||||
direction = data.get("direction", directions) { Side.LEFT }
|
||||
|
Loading…
Reference in New Issue
Block a user