First day release changes
- add addon requirements - add addon modifiers - fix bug with incorrect dps, when armourPiercing more than 100 - fix bug, when dmg radius show on point weapon
This commit is contained in:
parent
fb94b26c83
commit
8f14dd9e62
@ -17,7 +17,7 @@ class AddonModifiers {
|
||||
@JsonIgnore
|
||||
var addon: BuildingAddon? = null
|
||||
|
||||
var references: String? = null
|
||||
var reference: String? = null
|
||||
var usageType: String? = null
|
||||
var value: String? = null
|
||||
var value: Double? = null
|
||||
}
|
||||
|
||||
@ -5,8 +5,8 @@ import jakarta.persistence.*
|
||||
|
||||
|
||||
@Entity
|
||||
@Table(name = "addon_requires")
|
||||
class AddonRequires {
|
||||
@Table(name = "addon_requirements")
|
||||
class AddonRequirements {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ -16,10 +16,7 @@ class AddonRequires {
|
||||
@JoinColumn(name = "addon_id", nullable = false)
|
||||
@JsonIgnore
|
||||
var addon: BuildingAddon? = null
|
||||
|
||||
var references: String? = null
|
||||
|
||||
var reference: String? = null
|
||||
var replaceWhenDone: Boolean = false
|
||||
|
||||
var value: String? = null
|
||||
var value: Double? = null
|
||||
}
|
||||
@ -31,7 +31,7 @@ class BuildingAddon {
|
||||
var addonModifiers: MutableSet<AddonModifiers>? = null
|
||||
|
||||
@OneToMany(mappedBy = "addon", cascade = [CascadeType.ALL])
|
||||
var addonRequires: MutableSet<AddonRequires>? = null
|
||||
var addonRequirements: MutableSet<AddonRequirements>? = null
|
||||
|
||||
var icon: String? = null
|
||||
|
||||
|
||||
@ -16,11 +16,11 @@ class DowUnit {
|
||||
@JoinColumn(name = "race_id", nullable = false)
|
||||
var race: Race? = null
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "armour_type_id", nullable = false)
|
||||
var armorType: ArmorType? = null
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "armour_type_2_id")
|
||||
var armorType2: ArmorType? = null
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import com.dowstats.configuration.StorageConfig
|
||||
import com.dowstats.data.dto.integration.AvailableMods
|
||||
import com.dowstats.data.entities.Mod
|
||||
import com.dowstats.data.repositories.ModRepository
|
||||
import com.dowstats.service.w40k.ModAttribPathService
|
||||
import com.dowstats.service.w40k.ModParserService
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
@ -17,7 +18,10 @@ import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.net.URL
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.zip.*
|
||||
|
||||
|
||||
@ -26,6 +30,7 @@ class ModStorageIntegrationService(
|
||||
val modStorageConfig: StorageConfig,
|
||||
val modRepository: ModRepository,
|
||||
val modParserService: ModParserService,
|
||||
val storageConfig: StorageConfig,
|
||||
) {
|
||||
|
||||
val objectMapper = jacksonObjectMapper()
|
||||
@ -64,7 +69,7 @@ class ModStorageIntegrationService(
|
||||
it.name = "Dowstats balance mod"
|
||||
it.technicalName = toSave.technicalName
|
||||
})
|
||||
modParserService.parceModFilesAndSaveToDb(savedMod)
|
||||
modParserService.parseModFilesAndSaveToDb(savedMod)
|
||||
} catch (e: Exception) {
|
||||
log.error("Error while download and extract mod", e)
|
||||
}
|
||||
@ -76,7 +81,8 @@ class ModStorageIntegrationService(
|
||||
fun reloadMod(modId: Long) {
|
||||
val mod = modRepository.findById(modId).orElseThrow { IllegalArgumentException("Mod not found") }
|
||||
modRepository.clearModData(modId)
|
||||
modParserService.parceModFilesAndSaveToDb(mod)
|
||||
checkSgaAndExtract(mod)
|
||||
modParserService.parseModFilesAndSaveToDb(mod)
|
||||
}
|
||||
|
||||
|
||||
@ -94,11 +100,35 @@ class ModStorageIntegrationService(
|
||||
val modDirectoryTo = "$name$version"
|
||||
val fileStream = file.bytes.inputStream()
|
||||
unzip(fileStream, modDirectoryTo)
|
||||
modParserService.parceModFilesAndSaveToDb(savedMod)
|
||||
modParserService.parseModFilesAndSaveToDb(savedMod)
|
||||
log.info("${file.originalFilename} successfull uploaded. Name: $name, version: $version")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSgaAndExtract(mod: Mod){
|
||||
val modDirectory = "${storageConfig.modStorage.replace("/", File.separator)}${File.separator}${mod.technicalName}${mod.version}"
|
||||
File(modDirectory).listFiles()?.forEach { sgaFolder ->
|
||||
if(sgaFolder.isDirectory && sgaFolder.name.endsWith(".sga")){
|
||||
// Перемещаем иконки
|
||||
val iconFolder = sgaFolder.path + "${File.separator}Data${File.separator}art${File.separator}ui${File.separator}ingame"
|
||||
if(File(iconFolder).exists()){
|
||||
val iconFolderDestination = iconFolder.replace(sgaFolder.name + File.separator, "")
|
||||
Files.createDirectories(Paths.get(iconFolderDestination))
|
||||
FileSystemUtils.copyRecursively(Paths.get(iconFolder),Paths.get(iconFolderDestination))
|
||||
}
|
||||
// Перемещаем атрибуты
|
||||
val attribFolder = sgaFolder.path + "${File.separator}Data${File.separator}attrib"
|
||||
if(File(attribFolder).exists()) {
|
||||
val attribFolderDestination = attribFolder.replace(sgaFolder.name + File.separator, "")
|
||||
Files.createDirectories(Paths.get(attribFolder))
|
||||
FileSystemUtils.copyRecursively(Paths.get(attribFolder),Paths.get(attribFolderDestination))
|
||||
}
|
||||
// Удаляем остальное
|
||||
FileSystemUtils.deleteRecursively(sgaFolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadAndExtractMod(modTechName: String, version: String) {
|
||||
log.info("Downloading mod $modTechName")
|
||||
val urlString = "http://crosspick.ru/dow_stats_client/dow_stats_balance_mod/$modTechName.zip"
|
||||
|
||||
@ -3,6 +3,7 @@ package com.dowstats.service.w40k
|
||||
import com.dowstats.data.dto.BuildCost
|
||||
import com.dowstats.data.entities.*
|
||||
import com.dowstats.data.rgd.RgdData
|
||||
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
|
||||
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
|
||||
import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
|
||||
import com.dowstats.data.rgd.RgdDataUtil.getStringByName
|
||||
@ -50,14 +51,50 @@ class BuildingAddonRgdExtractService @Autowired constructor(
|
||||
addon.addonCostFaith = buildCost.faith
|
||||
addon.addonCostSouls = buildCost.souls
|
||||
addon.addonCostTime = buildCost.time
|
||||
addon.addonModifiers = getAddonModifiers(addon, addonRgdData).toMutableSet()
|
||||
addon.addonRequirements = getAddonRequirements(addon, addonRgdData).toMutableSet()
|
||||
|
||||
val addonIcon = convertIconAndReturnPath(addonRgdData, modFolderData, mod.name)
|
||||
addon.icon = addonIcon
|
||||
|
||||
|
||||
return addon
|
||||
}
|
||||
|
||||
private fun getAddonModifiers(addon: BuildingAddon, addonData: List<RgdData>): List<AddonModifiers> {
|
||||
val modifiers = addonData.getRgdTableByName("modifiers")
|
||||
return modifiers?.mapNotNull { m ->
|
||||
if (m.name.contains("modifier_")) {
|
||||
val mTable = m.value as List<RgdData>
|
||||
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
|
||||
AddonModifiers().also {
|
||||
it.addon = addon
|
||||
it.reference = mTable.getStringByName("\$REF")
|
||||
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
|
||||
it.value = mTable.getDoubleByName("value")
|
||||
}
|
||||
}
|
||||
} else null
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
private fun getAddonRequirements(addon: BuildingAddon, addonData: List<RgdData>): List<AddonRequirements> {
|
||||
val requirements = addonData.getRgdTableByName("requirements")
|
||||
return requirements?.mapNotNull { r ->
|
||||
if (r.name.contains("required_")) {
|
||||
val rTable = r.value as List<RgdData>
|
||||
if (rTable.getStringByName("\$REF") == "requirements\\required_none.lua") null else {
|
||||
AddonRequirements().also {
|
||||
it.addon = addon
|
||||
it.reference = rTable.getStringByName("\$REF")
|
||||
it.replaceWhenDone = rTable.getBooleanByName("replace_when_done") == true
|
||||
it.value =
|
||||
if (it.reference == "requirements\\required_total_pop.lua") rTable.getDoubleByName("population_required") else null
|
||||
}
|
||||
}
|
||||
} else null
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
|
||||
private fun getAddonCost(addonData: List<RgdData>): BuildCost {
|
||||
|
||||
@ -79,16 +116,28 @@ class BuildingAddonRgdExtractService @Autowired constructor(
|
||||
val uiInfo = addonData.getRgdTableByName("ui_info")
|
||||
|
||||
val nameRef = uiInfo?.getStringByName("screen_name_id")?.replace("$", "")
|
||||
val name = nameRef?.let { try{modDictionary[it.toInt()]} catch (e: Exception) { null } }
|
||||
val name = nameRef?.let {
|
||||
try {
|
||||
modDictionary[it.toInt()]
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val descriptionRefs = uiInfo?.getRgdTableByName("help_text_list")
|
||||
?.map{(it.value as String).replace("$", "")}
|
||||
?.filter{it != "0" && it != "tables\\text_table.lua" && it != ""}
|
||||
?.sortedBy { try { it.toInt() } catch (e: Exception) { 0 } }
|
||||
?.map { (it.value as String).replace("$", "") }
|
||||
?.filter { it != "0" && it != "tables\\text_table.lua" && it != "" }
|
||||
?.sortedBy {
|
||||
try {
|
||||
it.toInt()
|
||||
} catch (e: Exception) {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
val description = try {
|
||||
descriptionRefs?.map { modDictionary[it.toInt()] }?.joinToString ( "\n" )
|
||||
} catch(e:Exception) {
|
||||
descriptionRefs?.map { modDictionary[it.toInt()] }?.joinToString("\n")
|
||||
} catch (e: Exception) {
|
||||
log.warn("Error parsing ui description", e)
|
||||
null
|
||||
}
|
||||
@ -97,7 +146,11 @@ class BuildingAddonRgdExtractService @Autowired constructor(
|
||||
}
|
||||
|
||||
|
||||
private fun convertIconAndReturnPath(buildingData: List<RgdData>, modFolderData: String, modName: String?): String? {
|
||||
private fun convertIconAndReturnPath(
|
||||
buildingData: List<RgdData>,
|
||||
modFolderData: String,
|
||||
modName: String?
|
||||
): String? {
|
||||
val iconPathInMod = buildingData
|
||||
.getRgdTableByName("ui_info")
|
||||
?.getStringByName("icon_name")
|
||||
@ -106,7 +159,7 @@ class BuildingAddonRgdExtractService @Autowired constructor(
|
||||
|
||||
val tgaIconPath = iconPathInMod?.let {
|
||||
val modIcon = modAttribPathService.getIconPath(modFolderData, it)
|
||||
if(Path.of(modIcon).exists()) modIcon else
|
||||
if (Path.of(modIcon).exists()) modIcon else
|
||||
modAttribPathService.getIconPath(modAttribPathService.pathToWanilaData, it)
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ class ModParserService @Autowired constructor(
|
||||
val log = LoggerFactory.getLogger(ModParserService::class.java)
|
||||
|
||||
@Transactional
|
||||
fun parceModFilesAndSaveToDb(mod: Mod) {
|
||||
fun parseModFilesAndSaveToDb(mod: Mod) {
|
||||
|
||||
log.info("Start parse mod files ${mod.technicalName}:${mod.version}")
|
||||
|
||||
|
||||
@ -169,7 +169,10 @@ class UnitRgdExtractService @Autowired constructor(
|
||||
?.getRgdTableByName(armorTypeTableName)
|
||||
?.getStringByName("\$REF")
|
||||
|
||||
return armorTypes.find { it.id == armorType?.replace("type_armour\\tp_", "")?.replace(".lua", "") }
|
||||
return armorTypes.find { it.id == armorType
|
||||
?.replace("TYPE_Armour\\tp_", "")
|
||||
?.replace("type_armour\\tp_", "")
|
||||
?.replace(".lua", "") }
|
||||
}
|
||||
|
||||
private fun getBuildCost(unitData: List<RgdData>, squadData: List<RgdData>): BuildCost {
|
||||
|
||||
@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Service
|
||||
import java.io.File
|
||||
import java.math.BigDecimal
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.exists
|
||||
|
||||
@ -107,7 +108,10 @@ class WeaponRgdExtractService @Autowired constructor(
|
||||
|
||||
private fun getAreaEffectData(weaponData: List<RgdData>, armorTypes: Set<ArmorType>, thisWeapon: Weapon): AreaEffectData {
|
||||
val areaEffect = weaponData.getRgdTableByName("area_effect")
|
||||
val damageRadius = areaEffect?.getRgdTableByName("area_effect_information")?.getDoubleByName("radius") ?: 0.0
|
||||
|
||||
val areaEffectInformation = areaEffect?.getRgdTableByName("area_effect_information")
|
||||
val cantHaveRadius = areaEffectInformation?.getRgdTableByName("area_type")?.getStringByName("\$REF")?.contains("tp_area_effect_point") == true
|
||||
val damageRadius = if(cantHaveRadius) 0.0 else areaEffectInformation?.getDoubleByName("radius") ?: 0.0
|
||||
|
||||
val throwData = areaEffect?.getRgdTableByName("throw_data")
|
||||
val forceMin = throwData?.getDoubleByName("force_min") ?: 0.0
|
||||
@ -137,7 +141,8 @@ class WeaponRgdExtractService @Autowired constructor(
|
||||
val weaponArmourPiercing = WeaponArmorPiercing()
|
||||
weaponArmourPiercing.weapon = thisWeapon
|
||||
weaponArmourPiercing.armorType = it
|
||||
weaponArmourPiercing.piercingValue = (weaponDmgMap[it.id] ?: defaultArmourPiercing)?.toBigDecimal()
|
||||
val piercingValue = (weaponDmgMap[it.id] ?: defaultArmourPiercing)?.toBigDecimal()
|
||||
weaponArmourPiercing.piercingValue = piercingValue?.let {pv -> if(pv <= BigDecimal(100)) pv else BigDecimal(100) }
|
||||
weaponArmourPiercing
|
||||
}
|
||||
|
||||
|
||||
72
src/main/resources/db/0.0.2/schema/addon.json
Normal file
72
src/main/resources/db/0.0.2/schema/addon.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"databaseChangeLog": [
|
||||
{
|
||||
"changeSet": {
|
||||
"id": "Rename addon columns",
|
||||
"author": "anibus",
|
||||
"changes": [
|
||||
{
|
||||
"renameColumn": {
|
||||
"newColumnName": "reference",
|
||||
"oldColumnName": "references",
|
||||
"tableName": "addon_modifiers"
|
||||
}
|
||||
},{
|
||||
"renameColumn": {
|
||||
"newColumnName": "reference",
|
||||
"oldColumnName": "references",
|
||||
"tableName": "addon_requires"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"changeSet": {
|
||||
"id": "Rename addon_requires table",
|
||||
"author": "anibus",
|
||||
"changes": [
|
||||
{
|
||||
"renameTable": {
|
||||
"oldTableName": "addon_requires",
|
||||
"newTableName": "addon_requirements"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"changeSet": {
|
||||
"id": "Change addon_requirements value type",
|
||||
"author": "anibus",
|
||||
"changes": [
|
||||
{
|
||||
"dropColumn": {
|
||||
"columns": [
|
||||
{
|
||||
"column": {
|
||||
"name": "value"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tableName": "addon_requirements"
|
||||
}
|
||||
},
|
||||
{
|
||||
"addColumn": {
|
||||
"columns": [
|
||||
{
|
||||
"column": {
|
||||
"name": "value",
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tableName": "addon_requirements"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -73,6 +73,10 @@
|
||||
"include": {
|
||||
"file": "db/0.0.1/schema/procedure_delete_mod_data.json"
|
||||
}
|
||||
},{
|
||||
"include": {
|
||||
"file": "db/0.0.2/schema/addon.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user