212 lines
8.6 KiB
Kotlin
212 lines
8.6 KiB
Kotlin
package com.dowstats.service.w40k
|
|
|
|
import com.dowstats.data.entities.*
|
|
import com.dowstats.data.repositories.*
|
|
import com.dowstats.data.rgd.RgdData
|
|
import org.springframework.beans.factory.annotation.Autowired
|
|
import org.springframework.stereotype.Service
|
|
import java.lang.Exception
|
|
import jakarta.transaction.Transactional
|
|
import org.slf4j.LoggerFactory
|
|
import java.io.File
|
|
import java.nio.file.Files
|
|
import kotlin.io.path.Path
|
|
import kotlin.io.path.name
|
|
|
|
@Service
|
|
class ModParserService @Autowired constructor(
|
|
val rgdParserService: RgdParserService,
|
|
val unitRgdExtractService: UnitRgdExtractService,
|
|
val raceRepository: RaceRepository,
|
|
val armorTypeRepository: ArmorTypeRepository,
|
|
val unitRepository: UnitRepository,
|
|
val sergeantRepository: SergeantRepository,
|
|
val weaponRgdExtractService: WeaponRgdExtractService,
|
|
val weaponRepository: WeaponRepository,
|
|
val modAttribPathService: ModAttribPathService,
|
|
) {
|
|
|
|
val defaultDictionary: MutableMap<Int, String> = mutableMapOf()
|
|
|
|
init {
|
|
RgdParserService::class.java.getClassLoader().getResourceAsStream("DXP2.ucs").bufferedReader(Charsets.UTF_8).lines().forEach {
|
|
val kv = it.split("\\s+".toRegex())
|
|
if (kv.size < 2) return@forEach
|
|
val key = kv.first().filter { it.isDigit() }.toInt()
|
|
val value = kv.drop(1).joinToString(" ").replace("\u0000","")
|
|
defaultDictionary[key] = value
|
|
}
|
|
|
|
RgdParserService::class.java.getClassLoader().getResourceAsStream("W40k.ucs").bufferedReader(Charsets.UTF_8).lines().forEach {
|
|
val kv = it.split("\\s+".toRegex())
|
|
if (kv.size < 2) return@forEach
|
|
val key = kv.first().filter { it.isDigit() }.toInt()
|
|
val value = kv.drop(1).joinToString(" ").replace("\u0000","")
|
|
defaultDictionary[key] = value
|
|
}
|
|
}
|
|
|
|
val log = LoggerFactory.getLogger(ModParserService::class.java)
|
|
|
|
@Transactional
|
|
fun parceModFilesAndSaveToDb(mod: Mod) {
|
|
|
|
log.info("Start parse mod files ${mod.technicalName}:${mod.version}")
|
|
|
|
val modId = mod.id!!
|
|
|
|
val modFolderData = modAttribPathService.getModFolderData(mod.technicalName!!, mod.version!!)
|
|
val racesList = Files.walk(Path(modAttribPathService.getSbpsAttribsFolderPath(modFolderData)), 1)
|
|
.toList()
|
|
.drop(1)
|
|
.filter { Files.isDirectory(it) }.map { it.name }.toList()
|
|
|
|
racesList.forEach{
|
|
unitRepository.deleteAllByModIdAndRaceId(modId, it)
|
|
}
|
|
|
|
|
|
val modDictionary: MutableMap<Int, String> = mutableMapOf()
|
|
|
|
log.info("Extract dictionaries from $modFolderData")
|
|
File(modAttribPathService.getUcsFolder(modFolderData)).listFiles().forEach {
|
|
it.bufferedReader(Charsets.UTF_8).lines().forEach {
|
|
val kv = it.split("\\s+".toRegex())
|
|
if (kv.size < 2) return@forEach
|
|
val key = kv.first().filter { it.isDigit() }.toInt()
|
|
val value = kv.drop(1).joinToString(" ").replace("\u0000","")
|
|
modDictionary[key] = value
|
|
}
|
|
}
|
|
|
|
val enrichedModDictionary = modDictionary + defaultDictionary
|
|
|
|
val weapons = saveWeapons(modFolderData, modId, enrichedModDictionary)
|
|
saveUnits(modFolderData, weapons, racesList, modId, enrichedModDictionary)
|
|
|
|
}
|
|
|
|
fun saveUnits(modFolderData: String, weapons: Set<Weapon>, racesList: List<String>, modId: Long, modDictionary: Map<Int, String>) {
|
|
|
|
val races = raceRepository.findAll().toList()
|
|
val armorTypes = armorTypeRepository.findAll().toList()
|
|
|
|
racesList.forEach { raceFolder ->
|
|
|
|
if( raceRepository.findById(raceFolder) == null){
|
|
val race = Race().also { it.id = raceFolder; it.name = raceFolder }
|
|
raceRepository.save(race)
|
|
}
|
|
|
|
println(raceFolder)
|
|
|
|
val classicRgdDataSquads =
|
|
rgdParserService.parseFolderToRgdFiles(modAttribPathService.getSbpsAttribsPath(modAttribPathService.pathToWanilaData, raceFolder))
|
|
val modRgdDataSquads =
|
|
rgdParserService.parseFolderToRgdFiles(modAttribPathService.getSbpsAttribsPath(modFolderData, raceFolder))
|
|
|
|
val classicRgdDataUnits =
|
|
rgdParserService.parseFolderToRgdFiles(modAttribPathService.getEbpsTroopsAttribsPath(modAttribPathService.pathToWanilaData, raceFolder))
|
|
val modRgdDataUnits =
|
|
rgdParserService.parseFolderToRgdFiles(modAttribPathService.getEbpsTroopsAttribsPath(modFolderData, raceFolder))
|
|
|
|
val modSquadsFull = classicRgdDataSquads + modRgdDataSquads
|
|
val modUnitsFull = classicRgdDataUnits + modRgdDataUnits
|
|
|
|
modSquadsFull.forEach { squadRgdData ->
|
|
|
|
val baseUnitName = unitRgdExtractService.getUnitRgdFileNameFromSquadData(squadRgdData.value)
|
|
?: throw Exception("Can't extract unit name from squad ${squadRgdData.key}")
|
|
log.info("Start extracting $raceFolder: $baseUnitName")
|
|
val unitRgdData: List<RgdData> =
|
|
modUnitsFull[baseUnitName] ?: emptyList()
|
|
|
|
if(unitRgdData.isEmpty()){
|
|
log.warn("Can't find rgd data for unit $baseUnitName")
|
|
return@forEach
|
|
}
|
|
|
|
val unitDataToSave =
|
|
try {
|
|
unitRgdExtractService.extractToUnitEntity(
|
|
squadRgdData.key,
|
|
modDictionary,
|
|
squadRgdData.value,
|
|
unitRgdData,
|
|
weapons,
|
|
raceFolder,
|
|
modFolderData,
|
|
modId,
|
|
races,
|
|
armorTypes,
|
|
modUnitsFull
|
|
)
|
|
} catch (e: Exception) {
|
|
log.error("Can't extract $baseUnitName", e)
|
|
return@forEach
|
|
}
|
|
|
|
try {
|
|
val unit = unitRepository.save(unitDataToSave.unit)
|
|
unit.weapons = unitDataToSave.unitWeapons.map {weapon ->
|
|
UnitWeapon().also {
|
|
it.unit = unit
|
|
it.weapon = weapon
|
|
it.hardpoint = weapon.hardpoint
|
|
it.hardpointOrder = weapon.hardpointOrder
|
|
it.unitWeaponKey = UnitWeaponKey().also {
|
|
it.unitId = unit.id
|
|
it.weaponId = weapon.id
|
|
}
|
|
}
|
|
}.toMutableSet()
|
|
unitRepository.save(unit)
|
|
|
|
|
|
unitDataToSave.sergeants?.forEach { sergeantToSave ->
|
|
val sergeant = sergeantRepository.save(sergeantToSave.first.also {
|
|
it.unit = unit
|
|
})
|
|
sergeant.weapons = sergeantToSave.second.map {weapon ->
|
|
SergeantWeapon().also {
|
|
it.sergeant = sergeant
|
|
it.weapon = weapon
|
|
it.hardpoint = weapon.hardpoint
|
|
it.hardpointOrder = weapon.hardpointOrder
|
|
it.sergeantWeaponKey = SergeantWeaponKey().also { swk ->
|
|
swk.sergeantId = sergeant.id
|
|
swk.weaponId = weapon.id
|
|
}
|
|
}
|
|
}.toMutableSet()
|
|
sergeantRepository.save(sergeant)
|
|
}
|
|
} catch (e: Exception) {
|
|
throw e
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fun saveWeapons(modFolderData: String, modId: Long, modDictionary: Map<Int, String>): Set<Weapon> {
|
|
|
|
val classicWeapons = rgdParserService.parseFolderToRgdFiles("${modAttribPathService.pathToWanilaData}/attrib/weapon")
|
|
|
|
val modWeapons =
|
|
rgdParserService.parseFolderToRgdFiles(modAttribPathService.getWeaponAttribsPath(modFolderData))
|
|
|
|
val allWeapons = classicWeapons + modWeapons
|
|
|
|
val weaponsToSave = allWeapons.mapNotNull {
|
|
weaponRgdExtractService.extractToWeaponEntity(it.key, it.value, modId, modFolderData, modDictionary)
|
|
}
|
|
|
|
return try {
|
|
weaponRepository.saveAll(weaponsToSave).toSet()
|
|
} catch (e: Exception) {
|
|
throw e
|
|
}
|
|
}
|
|
|
|
}
|