Skip to content
This repository has been archived by the owner on Jun 25, 2024. It is now read-only.

Commit

Permalink
Many updates for FS22 - one big UI change pending
Browse files Browse the repository at this point in the history
Backend for UI should be complete, but I'm out of willpower for the night.  See also #45 and #47
  • Loading branch information
jtsage committed Nov 23, 2021
1 parent 6483474 commit f1db76f
Show file tree
Hide file tree
Showing 16 changed files with 211 additions and 73 deletions.
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# FS19 Mod Install Checker
# FS Mod Install Checker

[![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/jtsage/FS19_Mod_Checker) [![Build/release](https://github.com/jtsage/FS19_Mod_Checker/actions/workflows/build.yml/badge.svg)](https://github.com/jtsage/FS19_Mod_Checker/actions/workflows/build.yml) ![GitHub Release Date](https://img.shields.io/github/release-date/jtsage/FS19_Mod_Checker) ![GitHub all releases](https://img.shields.io/github/downloads/jtsage/FS19_Mod_Checker/total) [![Crowdin](https://badges.crowdin.net/fs19-mod-checker/localized.svg)](https://crowdin.com/project/fs19-mod-checker)

Expand All @@ -24,7 +24,7 @@ _Optionally_, it will also allow you to remove mods from your install folder (at
* Suggest you move the contents of the folder if it looks like a mod pack
* Suggest you remove the folder if it looks like garbage

* If a mod is not intended for FS19 (i.e. FS17 mods)
* If a mod is not intended for FS19 or FS22 (configurable!) (i.e. FS17 mods)
* Warn that you can't use it with this version

* If a file exists that is not a mod at all
Expand Down Expand Up @@ -55,7 +55,7 @@ Here you can sort the list of good, installed mods to discover any number of thi

## Usage

Download the installer for your platform from the [Releases](https://github.com/jtsage/FS19_Mod_Checker/releases) page - the program
Download the installer for your platform from the [Releases](https://github.com/jtsage/FS_Mod_Checker/releases) page - the program
will install with 1-click, and auto-run when it's ready.

### Download options
Expand Down Expand Up @@ -102,47 +102,47 @@ I will not be exploring using the server API to check directly - The amount of c
### Configuration Screen, Mods Loaded

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/001-config.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/001-config.png">
</p>

### Bad Mods, Unzipped Mods, Extra Files

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/002-broken.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/002-broken.png">
</p>

### Missing Mods

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/003-missing.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/003-missing.png">
</p>

### Possible Conflicts

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/004-conflict.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/004-conflict.png">
</p>

### Explore Mods

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/005-explore.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/005-explore.png">
</p>

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/006-explore-options.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/006-explore-options.png">
</p>

### Detail Popup

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/010-detail.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/010-detail.png">
</p>

### User Preferences

<p align="center">
<img width="650" src="https://github.com/jtsage/FS19_Mod_Checker/raw/main/screen_shots/020-prefs.png">
<img width="650" src="https://github.com/jtsage/FS_Mod_Checker/raw/main/screen_shots/020-prefs.png">
</p>


Expand All @@ -161,7 +161,7 @@ Sadly, the primary developer only understands English. If you'd like to contrib

## In-Progress Improvements

* Note some of the more popular mod conflicts and suggest avoiding them: [GitHub Issue #2](https://github.com/jtsage/FS19_Mod_Checker/issues/2)
* Note some of the more popular mod conflicts and suggest avoiding them: [GitHub Issue #2](https://github.com/jtsage/FS_Mod_Checker/issues/2)

## A short note about the EXE

Expand Down
20 changes: 20 additions & 0 deletions lib/mod-checker-conflicts-2022.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* _______ __ ______ __ __
| | |.-----.--| | | |--.-----.----.| |--.-----.----.
| || _ | _ | ---| | -__| __|| <| -__| _|
|__|_|__||_____|_____|______|__|__|_____|____||__|__|_____|__| */

// Mod File Parser - Conflict Mods

// (c) 2021 JTSage. MIT License.

/*
These are mods that have often reported conflicts and
we want to warn the user of that.
This is really for the "big" or "common" conflicts.
One-off oddities is a waste of maintainer time.
2022 Version.
*/

module.exports.conflictMods = {}
8 changes: 8 additions & 0 deletions lib/mod-checker-conflicts.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ we want to warn the user of that.
This is really for the "big" or "common" conflicts.
One-off oddities is a waste of maintainer time.
2019 Version.
*/

module.exports.conflictMods = {
Expand Down Expand Up @@ -266,4 +268,10 @@ module.exports.conflictMods = {
fr : 'Ce mod fait partie d\'une liste de mods reconnus comme incompatibles avec la carte Hof Bergmann, comme stipulé dans le fichier PDF qui est joint avec la carte.',
},
},
'FS19_ProductionsForAnimals' : {
confWith : null,
message : {
en : 'In the absence of a compatible map, this mod is the reason for the lack of access to the animal menu.',
},
},
}
123 changes: 88 additions & 35 deletions lib/mod-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const decodeDXT = require('decode-dxt')
const parseDDS = require('parse-dds')
const PNG = require('pngjs').PNG

const conflictListData = require('./mod-checker-conflicts')
const conflictListData2019 = require('./mod-checker-conflicts')
const conflictListData2022 = require('./mod-checker-conflicts-2022')

/**
* Turn a truthy value into a boolean
Expand All @@ -29,26 +30,39 @@ const realBool = function(input) {
return (typeof input === 'boolean') ? input : Boolean(input)
}

/* False "isUsed" negatives. They are really script mods, but have some optional storeItems */
const falseIsUsedNegatives = [
'FS19_buyableLargeStackBales',
'FS19_RM_Seasons',
'FS19_GlobalCompany',
'FS19_precisionFarming',
const validFileTypes = [
'ogg', 'dds', 'i3d', 'pes', 'lua', 'xml'
]

/* False "isUsed" negatives. They are really script mods, but have some optional storeItems */
const falseIsUsedNegatives = {
19 : [
'FS19_buyableLargeStackBales',
'FS19_RM_Seasons',
'FS19_GlobalCompany',
'FS19_precisionFarming',
],
22 : [],
}

/* Known Paid DLC titles to check for cracked / pirated versions */
const knownPDLCTitlesEN = [
'Kverneland &amp; Vicon Equipment Pack',
'Grimme Pack',
'CLAAS Pack (Platinum Expansion)',
'Anderson Group Equipment Pack',
'Rottne Pack',
'BOURGAULT Pack',
'Alpine Farming Pack',
]
const knownPDLCTitlesEN = {
19 : [
'Kverneland &amp; Vicon Equipment Pack',
'Grimme Pack',
'CLAAS Pack (Platinum Expansion)',
'Anderson Group Equipment Pack',
'Rottne Pack',
'BOURGAULT Pack',
'Alpine Farming Pack',
],
22 : [],
}



class modReader {
gameVersion = 19
modFolder = null
gameFolder = null
fullList = {}
Expand All @@ -69,13 +83,16 @@ class modReader {
* @param {class} log=null Class to handle logging, should be an instance of mcLogger
* @param {function} locale=null Function that returns a string of the current locale (i.e. "en")
*/
constructor(gameFolder, modFolder, log = null, locale = null) {
constructor(gameFolder, modFolder, log = null, locale = null, gameVersion = 19) {
this.gameFolder = gameFolder
this.modFolder = modFolder
this.log = log
this.gameVersion = gameVersion

if ( typeof locale === 'function') { this.locale = locale }

this.log.notice('collection', `Setting parser version to ${gameVersion}`)

if ( this.log === null ) {
throw new Error('Logging is non-functional, cannot continue')
}
Expand Down Expand Up @@ -142,11 +159,12 @@ class modReader {
*/
async conflictList() {
return Promise.allSettled(this.#modsTesting).then(() => {
let checkEntriesFromFile = []
const returnArray = []
const checkList = Object.keys(this.fullList)

for (const [_key, modRecord] of Object.entries(this.fullList)) {
if ( modRecord.isFileConflict ) {
if ( modRecord.isFileConflict && modRecord.isNotMissing ) {
returnArray.push([
modRecord.shortName,
modRecord.title,
Expand All @@ -162,7 +180,19 @@ class modReader {
returnArray.push(...dupeArray)
}

for ( const [modName, conflictDetails] of Object.entries(conflictListData.conflictMods)) {
switch ( this.gameVersion ) {
case 19:
checkEntriesFromFile = Object.entries(conflictListData2019.conflictMods)
break
case 22:
checkEntriesFromFile = Object.entries(conflictListData2022.conflictMods)
break
default:
this.log.notice('collection', 'Conflicts Error - Unknown gameVersion')
break
}

for ( const [modName, conflictDetails] of checkEntriesFromFile) {
if ( checkList.includes(modName) && this.fullList[modName].isNotMissing ) {
let doesConflict = false
if ( conflictDetails.confWith === null ) {
Expand Down Expand Up @@ -463,7 +493,7 @@ class modReader {
const modFolderFiles = fs.readdirSync(this.modFolder, {withFileTypes : true})

modFolderFiles.forEach((thisFile) =>{
if ( ! thisFile.isDirectory() ) {
if ( ! thisFile.isDirectory() && ! thisFile.isSymbolicLink() ) {
try {
const shortName = path.parse(thisFile.name).name
this.fullList[shortName] = new modFile(
Expand Down Expand Up @@ -649,16 +679,20 @@ class modReader {
strictXMLParser.parseString(fileContents, (err, result) => {
if ( err === null ) {
const savegame = parseInt(thisFile.match(/savegame(\d+)/)[1])

result.items.item.forEach( (thisMod) => {
const thisModName = thisMod.$?.MODNAME || null

if ( thisModName !== null && ! ( typeof thisModName === 'undefined') && ! thisModName.startsWith('pdlc') ) {
if ( this.contains(thisModName) ) {
this.fullList[thisModName].usedGame = savegame

try {
result.items.item.forEach( (thisMod) => {
const thisModName = thisMod.$?.MODNAME || null

if ( thisModName !== null && ! ( typeof thisModName === 'undefined') && ! thisModName.startsWith('pdlc') ) {
if ( this.contains(thisModName) ) {
this.fullList[thisModName].usedGame = savegame
}
}
}
})
})
} catch (err) {
this.log.fileError('saveReader', `File not in expected format, empty? ${thisFile} : ${err}`)
}
} else {
this.log.notice('collection', `Could not parse save file ${thisFile}`)
}
Expand Down Expand Up @@ -686,6 +720,7 @@ class modFile {
#iconImageCache = false
#iconImageFail = false
#modImageFiles = []
#modExtraFiles = []

#activeGames = new Set()
#usedGames = new Set()
Expand Down Expand Up @@ -837,6 +872,13 @@ class modFile {
/** Ask how many scripts the mod includes */
get countScripts() { return this.#scriptFiles }

/** Ask if the mod includes scripts */
get hasExtras() { return ( this.#modExtraFiles.length > 0 ) }
/** Ask if the mod DOES NOT include scripts */
get hasNoExtras() { return ( this.#modExtraFiles.length < 1 ) }
/** Ask how many scripts the mod includes */
get getExtras() { return this.#modExtraFiles }

/** Get Array of filesize Array([Human Readable], [In Bytes]) */
get fileSizeMap() {
return [this.fileSizeString, this.fileSize]
Expand Down Expand Up @@ -926,7 +968,7 @@ class modFile {
/** Get / Set that mod is used in a save game. Get is an array of length 21, the 0th element is "any save game" */
set usedGame(value) { this.#usedGames.add(parseInt(value)) }
get usedGame() {
if ( falseIsUsedNegatives.includes(this.shortName) || ( this.isNotMissing && this.#storeItems === 0 && this.#usedGames.size === 0 ) ) {
if ( falseIsUsedNegatives[this.#modList.gameVersion].includes(this.shortName) || ( this.isNotMissing && this.#storeItems === 0 && this.#usedGames.size === 0 ) ) {
return this.activeGame
}

Expand Down Expand Up @@ -1068,6 +1110,9 @@ class modFile {
if ( entry.name.endsWith('.l64') || entry.name.endsWith('productID.dat') ) {
this.#fail.might_be_crack = true
}
if ( validFileTypes.includes(entry.name.substr(-3)) ) {
this.#modExtraFiles.push(entry.name)
}
}

zip.stream('modDesc.xml', (err, stm) => {
Expand Down Expand Up @@ -1181,10 +1226,18 @@ class modFile {
/* Get modDesc.xml version */
if ( this.#nestedXMLProperty('moddesc.$.DESCVERSION') ) {
this.desc_version = parseInt(this.XMLParsed.moddesc.$.DESCVERSION)

if ( this.desc_version < 40 ) {
this.#fail.bad_modDesc_ver = true
return false

if ( this.#modList.gameVersion === 19 ) {
if ( this.desc_version < 40 || this.desc_version > 59 ) {
this.#fail.bad_modDesc_ver = true
return false
}
}
if ( this.#modList.gameVersion === 22 ) {
if ( this.desc_version < 60 ) {
this.#fail.bad_modDesc_ver = true
return false
}
}
} else {
this.#fail.bad_modDesc_ver = true
Expand Down Expand Up @@ -1247,7 +1300,7 @@ class modFile {
try {
const titleCheck = this.XMLParsed.moddesc.title[0].en[0].trim()

if ( knownPDLCTitlesEN.includes(titleCheck) ) {
if ( knownPDLCTitlesEN[this.#modList.gameVersion].includes(titleCheck) ) {
this.#fail.might_be_crack = true
}
} catch {
Expand Down
Loading

0 comments on commit f1db76f

Please sign in to comment.