Избавляемся от ненужного дублирования кода
This commit is contained in:
parent
d7c16697be
commit
8042cd0a22
@ -7,6 +7,7 @@ import com.google.gson.internal.bind.TypeAdapters
|
|||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.kstarbound.api.IStarboundFile
|
import ru.dbotthepony.kstarbound.api.IStarboundFile
|
||||||
@ -47,6 +48,11 @@ import ru.dbotthepony.kstarbound.util.WriteOnce
|
|||||||
import java.io.*
|
import java.io.*
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.function.BiConsumer
|
||||||
|
import java.util.function.BinaryOperator
|
||||||
|
import java.util.function.Function
|
||||||
|
import java.util.function.Supplier
|
||||||
|
import java.util.stream.Collector
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
const val METRES_IN_STARBOUND_UNIT = 0.5
|
const val METRES_IN_STARBOUND_UNIT = 0.5
|
||||||
@ -273,6 +279,9 @@ object Starbound {
|
|||||||
loader: ((String) -> Unit) -> Unit,
|
loader: ((String) -> Unit) -> Unit,
|
||||||
name: String,
|
name: String,
|
||||||
) {
|
) {
|
||||||
|
if (terminateLoading)
|
||||||
|
return
|
||||||
|
|
||||||
val time = System.currentTimeMillis()
|
val time = System.currentTimeMillis()
|
||||||
callback(false, false, "Loading $name...")
|
callback(false, false, "Loading $name...")
|
||||||
LOGGER.info("Loading $name...")
|
LOGGER.info("Loading $name...")
|
||||||
@ -289,6 +298,150 @@ object Starbound {
|
|||||||
LOGGER.info("Loaded $name in ${System.currentTimeMillis() - time}ms")
|
LOGGER.info("Loaded $name in ${System.currentTimeMillis() - time}ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T, K : Any> loadStage(
|
||||||
|
callback: (Boolean, Boolean, String) -> Unit,
|
||||||
|
clazz: Class<T>,
|
||||||
|
getKey: (T) -> K,
|
||||||
|
put: (K, T) -> T?,
|
||||||
|
files: List<IStarboundFile>,
|
||||||
|
name: String,
|
||||||
|
) {
|
||||||
|
loadStage(callback, loader = {
|
||||||
|
for (listedFile in files) {
|
||||||
|
try {
|
||||||
|
it("Loading $listedFile")
|
||||||
|
val def = pathStack(listedFile.computeDirectory()) { GSON.fromJson(listedFile.reader(), clazz) }
|
||||||
|
val key = getKey.invoke(def)
|
||||||
|
check(put.invoke(key, def) == null) { "Already has $name with name $key loaded!" }
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
LOGGER.error("Loading $name definition file $listedFile", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terminateLoading) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T, K0 : Any, K1 : Any> loadStage(
|
||||||
|
callback: (Boolean, Boolean, String) -> Unit,
|
||||||
|
clazz: Class<T>,
|
||||||
|
getKey0: (T) -> K0,
|
||||||
|
put0: (K0, T) -> T?,
|
||||||
|
getKey1: (T) -> K1,
|
||||||
|
put1: (K1, T) -> T?,
|
||||||
|
files: List<IStarboundFile>,
|
||||||
|
name: String,
|
||||||
|
) {
|
||||||
|
loadStage(callback, loader = {
|
||||||
|
for (listedFile in files) {
|
||||||
|
try {
|
||||||
|
it("Loading $listedFile")
|
||||||
|
val def = pathStack(listedFile.computeDirectory()) { GSON.fromJson(listedFile.reader(), clazz) }
|
||||||
|
val key0 = getKey0.invoke(def)
|
||||||
|
val key1 = getKey1.invoke(def)
|
||||||
|
check(put0.invoke(key0, def) == null) { "Already has $name with name $key0 loaded!" }
|
||||||
|
check(put1.invoke(key1, def) == null) { "Already has $name with ID $key1 loaded!" }
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
LOGGER.error("Loading $name definition file $listedFile", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terminateLoading) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doInitialize(callback: (finished: Boolean, replaceStatus: Boolean, status: String) -> Unit) {
|
||||||
|
var time = System.currentTimeMillis()
|
||||||
|
|
||||||
|
if (archivePaths.isNotEmpty()) {
|
||||||
|
callback(false, false, "Reading pak archives...".also(LOGGER::info))
|
||||||
|
|
||||||
|
for (path in archivePaths) {
|
||||||
|
callback(false, false, "Reading ${path.name}...".also(LOGGER::info))
|
||||||
|
|
||||||
|
addPak(StarboundPak(path) { _, status ->
|
||||||
|
callback(false, true, "${path.name}: $status")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(false, false, "Finished reading pak archives in ${System.currentTimeMillis() - time}ms".also(LOGGER::info))
|
||||||
|
time = System.currentTimeMillis()
|
||||||
|
callback(false, false, "Building file index...".also(LOGGER::info))
|
||||||
|
|
||||||
|
val ext2files = fileSystems.parallelStream()
|
||||||
|
.flatMap { it.explore() }
|
||||||
|
.filter { it.isFile }
|
||||||
|
.collect(object :
|
||||||
|
Collector<IStarboundFile, Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>,
|
||||||
|
Map<String, List<IStarboundFile>>>,
|
||||||
|
Supplier<Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>>,
|
||||||
|
BiConsumer<Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>, IStarboundFile>,
|
||||||
|
BinaryOperator<Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>>
|
||||||
|
{
|
||||||
|
override fun accept(t: Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>, u: IStarboundFile) {
|
||||||
|
t.computeIfAbsent(u.name.substringAfterLast('.'), Object2ObjectFunction { ArrayList() }).add(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(): Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>> {
|
||||||
|
return Object2ObjectOpenHashMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun supplier(): Supplier<Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>> {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun accumulator(): BiConsumer<Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>, IStarboundFile> {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun apply(
|
||||||
|
t: Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>,
|
||||||
|
u: Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>
|
||||||
|
): Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>> {
|
||||||
|
t.putAll(u)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun combiner(): BinaryOperator<Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>> {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finisher(): Function<Object2ObjectOpenHashMap<String, ArrayList<IStarboundFile>>, Map<String, List<IStarboundFile>>> {
|
||||||
|
return Function { it }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun characteristics(): Set<Collector.Characteristics> {
|
||||||
|
return setOf(Collector.Characteristics.IDENTITY_FINISH, Collector.Characteristics.UNORDERED)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
callback(false, false, "Finished building file index in ${System.currentTimeMillis() - time}ms".also(LOGGER::info))
|
||||||
|
|
||||||
|
loadStage(callback, this::loadFunctions, "functions")
|
||||||
|
loadStage(callback, this::loadProjectiles, "projectiles")
|
||||||
|
loadStage(callback, this::loadParallax, "parallax definitions")
|
||||||
|
loadStage(callback, this::loadItemDefinitions, "item definitions")
|
||||||
|
|
||||||
|
loadStage(callback, TileDefinition::class.java, TileDefinition::materialName, tiles::put, TileDefinition::materialId, tilesByMaterialID::put, ext2files["material"] ?: listOf(), "materials")
|
||||||
|
loadStage(callback, MaterialModifier::class.java, MaterialModifier::modName, tileModifiers::put, MaterialModifier::modId, tileModifiersByID::put, ext2files["matmod"] ?: listOf(), "material modifier definitions")
|
||||||
|
loadStage(callback, LiquidDefinition::class.java, LiquidDefinition::name, liquid::put, LiquidDefinition::liquidId, liquidByID::put, ext2files["liquid"] ?: listOf(), "liquid definitions")
|
||||||
|
loadStage(callback, StatusEffectDefinition::class.java, StatusEffectDefinition::name, statusEffects::put, ext2files["statuseffect"] ?: listOf(), "status effects")
|
||||||
|
loadStage(callback, Species::class.java, Species::kind, species::put, ext2files["species"] ?: listOf(), "species")
|
||||||
|
|
||||||
|
pathStack.block("/") {
|
||||||
|
playerDefinition = GSON.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
initializing = false
|
||||||
|
initialized = true
|
||||||
|
callback(true, false, "Finished loading in ${System.currentTimeMillis() - time}ms")
|
||||||
|
}
|
||||||
|
|
||||||
fun initializeGame(callback: (finished: Boolean, replaceStatus: Boolean, status: String) -> Unit) {
|
fun initializeGame(callback: (finished: Boolean, replaceStatus: Boolean, status: String) -> Unit) {
|
||||||
if (initializing) {
|
if (initializing) {
|
||||||
throw IllegalStateException("Already initializing!")
|
throw IllegalStateException("Already initializing!")
|
||||||
@ -299,39 +452,7 @@ object Starbound {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initializing = true
|
initializing = true
|
||||||
|
Thread({ doInitialize(callback) }, "Asset Loader").start()
|
||||||
Thread({
|
|
||||||
val time = System.currentTimeMillis()
|
|
||||||
|
|
||||||
if (archivePaths.isNotEmpty()) {
|
|
||||||
callback(false, false, "Reading pak archives...")
|
|
||||||
|
|
||||||
for (path in archivePaths) {
|
|
||||||
callback(false, false, "Reading ${path.name}...")
|
|
||||||
|
|
||||||
addPak(StarboundPak(path) { _, status ->
|
|
||||||
callback(false, true, "${path.name}: $status")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loadStage(callback, this::loadFunctions, "functions")
|
|
||||||
loadStage(callback, this::loadTileMaterials, "materials")
|
|
||||||
loadStage(callback, this::loadProjectiles, "projectiles")
|
|
||||||
loadStage(callback, this::loadParallax, "parallax definitions")
|
|
||||||
loadStage(callback, this::loadMaterialModifiers, "material modifier definitions")
|
|
||||||
loadStage(callback, this::loadLiquidDefinitions, "liquid definitions")
|
|
||||||
loadStage(callback, this::loadItemDefinitions, "item definitions")
|
|
||||||
loadStage(callback, this::loadSpecies, "species")
|
|
||||||
|
|
||||||
pathStack.block("/") {
|
|
||||||
playerDefinition = GSON.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
initializing = false
|
|
||||||
initialized = true
|
|
||||||
callback(true, false, "Finished loading in ${System.currentTimeMillis() - time}ms")
|
|
||||||
}, "Asset Loader").start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onInitialize(callback: () -> Unit) {
|
fun onInitialize(callback: () -> Unit) {
|
||||||
@ -352,29 +473,6 @@ object Starbound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadTileMaterials(callback: (String) -> Unit) {
|
|
||||||
for (fs in fileSystems) {
|
|
||||||
for (listedFile in fs.explore().filter { it.isFile }.filter { it.name.endsWith(".material") }) {
|
|
||||||
try {
|
|
||||||
callback("Loading $listedFile")
|
|
||||||
|
|
||||||
val tileDef = pathStack(listedFile.computeDirectory()) { GSON.fromJson(listedFile.reader(), TileDefinition::class.java) }
|
|
||||||
check(tiles[tileDef.materialName] == null) { "Already has material with name ${tileDef.materialName} loaded!" }
|
|
||||||
check(tilesByMaterialID[tileDef.materialId] == null) { "Already has material with ID ${tileDef.materialId} loaded!" }
|
|
||||||
tilesByMaterialID[tileDef.materialId] = tileDef
|
|
||||||
tiles[tileDef.materialName] = tileDef
|
|
||||||
} catch (err: Throwable) {
|
|
||||||
//throw TileDefLoadingException("Loading tile file $listedFile", err)
|
|
||||||
LOGGER.error("Loading tile file $listedFile", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (terminateLoading) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadProjectiles(callback: (String) -> Unit) {
|
private fun loadProjectiles(callback: (String) -> Unit) {
|
||||||
for (fs in fileSystems) {
|
for (fs in fileSystems) {
|
||||||
for (listedFile in fs.explore().filter { it.isFile }.filter { it.name.endsWith(".projectile") }) {
|
for (listedFile in fs.explore().filter { it.isFile }.filter { it.name.endsWith(".projectile") }) {
|
||||||
@ -437,66 +535,6 @@ object Starbound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadMaterialModifiers(callback: (String) -> Unit) {
|
|
||||||
for (fs in fileSystems) {
|
|
||||||
for (listedFile in fs.explore().filter { it.isFile }.filter { it.name.endsWith(".matmod") }) {
|
|
||||||
try {
|
|
||||||
callback("Loading $listedFile")
|
|
||||||
val tileDef = pathStack(listedFile.computeDirectory()) { GSON.fromJson(listedFile.reader(), MaterialModifier::class.java) }
|
|
||||||
check(tileModifiers[tileDef.modName] == null) { "Already has material with name ${tileDef.modName} loaded!" }
|
|
||||||
check(tileModifiersByID[tileDef.modId] == null) { "Already has material with ID ${tileDef.modId} loaded!" }
|
|
||||||
tileModifiersByID[tileDef.modId] = tileDef
|
|
||||||
tileModifiers[tileDef.modName] = tileDef
|
|
||||||
} catch (err: Throwable) {
|
|
||||||
//throw TileDefLoadingException("Loading tile file $listedFile", err)
|
|
||||||
LOGGER.error("Loading tile modifier file $listedFile", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (terminateLoading) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadLiquidDefinitions(callback: (String) -> Unit) {
|
|
||||||
for (fs in fileSystems) {
|
|
||||||
for (listedFile in fs.explore().filter { it.isFile }.filter { it.name.endsWith(".liquid") }) {
|
|
||||||
try {
|
|
||||||
callback("Loading $listedFile")
|
|
||||||
val liquidDef = pathStack(listedFile.computeDirectory()) { GSON.fromJson(listedFile.reader(), LiquidDefinition::class.java) }
|
|
||||||
check(liquid.put(liquidDef.name, liquidDef) == null) { "Already has liquid with name ${liquidDef.name} loaded!" }
|
|
||||||
check(liquidByID.put(liquidDef.liquidId, liquidDef) == null) { "Already has liquid with ID ${liquidDef.liquidId} loaded!" }
|
|
||||||
} catch (err: Throwable) {
|
|
||||||
//throw TileDefLoadingException("Loading tile file $listedFile", err)
|
|
||||||
LOGGER.error("Loading liquid definition file $listedFile", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (terminateLoading) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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")
|
|
||||||
val def = pathStack(listedFile.computeDirectory()) { 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
|
Loading…
Reference in New Issue
Block a user