Избавляемся от ненужного дублирования кода
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.JsonWriter
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||
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
|
||||
@ -47,6 +48,11 @@ import ru.dbotthepony.kstarbound.util.WriteOnce
|
||||
import java.io.*
|
||||
import java.text.DateFormat
|
||||
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
|
||||
|
||||
const val METRES_IN_STARBOUND_UNIT = 0.5
|
||||
@ -273,6 +279,9 @@ object Starbound {
|
||||
loader: ((String) -> Unit) -> Unit,
|
||||
name: String,
|
||||
) {
|
||||
if (terminateLoading)
|
||||
return
|
||||
|
||||
val time = System.currentTimeMillis()
|
||||
callback(false, false, "Loading $name...")
|
||||
LOGGER.info("Loading $name...")
|
||||
@ -289,6 +298,150 @@ object Starbound {
|
||||
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) {
|
||||
if (initializing) {
|
||||
throw IllegalStateException("Already initializing!")
|
||||
@ -299,39 +452,7 @@ object Starbound {
|
||||
}
|
||||
|
||||
initializing = true
|
||||
|
||||
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()
|
||||
Thread({ doInitialize(callback) }, "Asset Loader").start()
|
||||
}
|
||||
|
||||
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) {
|
||||
for (fs in fileSystems) {
|
||||
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) {
|
||||
val files = linkedMapOf(
|
||||
".item" to ItemPrototype::class.java,
|
||||
|
Loading…
Reference in New Issue
Block a user