Skip to content

Commit 37c01fd

Browse files
committed
feat: add meta models
Signed-off-by: Rachel Powers <[email protected]>
1 parent ef9e6a9 commit 37c01fd

File tree

11 files changed

+966
-115
lines changed

11 files changed

+966
-115
lines changed

libmcmeta/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#[macro_use]
22
extern crate custom_error;
3-
#[macro_use]
4-
extern crate lazy_static;
3+
// #[macro_use]
4+
// extern crate lazy_static;
55

66
pub mod models;

libmcmeta/src/models/forge.rs

Lines changed: 268 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::models::merge::{self, Merge};
22

3+
use crate::models::GradleSpecifier;
34
use serde::{Deserialize, Serialize};
45
use serde_valid::Validate;
56
use serde_with::skip_serializing_none;
@@ -494,6 +495,7 @@ pub enum ForgeInstallerManifestVersion {
494495
}
495496

496497
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge)]
498+
#[serde(deny_unknown_fields)]
497499
pub struct ForgeFile {
498500
#[merge(strategy = merge::overwrite)]
499501
pub classifier: String,
@@ -504,14 +506,14 @@ pub struct ForgeFile {
504506
}
505507

506508
impl ForgeFile {
507-
fn filename(&self, long_version: &str) -> String {
509+
pub fn filename(&self, long_version: &str) -> String {
508510
format!(
509511
"{}-{}-{}.{}",
510512
"forge", long_version, self.classifier, self.extension
511513
)
512514
}
513515

514-
fn url(&self, long_version: &str) -> String {
516+
pub fn url(&self, long_version: &str) -> String {
515517
format!(
516518
"https://maven.minecraftforge.net/net/minecraftforge/forge/{}/{}",
517519
long_version,
@@ -522,6 +524,7 @@ impl ForgeFile {
522524

523525
#[skip_serializing_none]
524526
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
527+
#[serde(deny_unknown_fields)]
525528
pub struct ForgeEntry {
526529
#[serde(rename = "longversion")]
527530
#[merge(strategy = merge::overwrite)]
@@ -533,23 +536,30 @@ pub struct ForgeEntry {
533536
pub version: String,
534537
#[merge(strategy = merge::overwrite)]
535538
pub build: i32,
539+
#[merge(strategy = merge::option::overwrite_some)]
536540
pub branch: Option<String>,
541+
#[merge(strategy = merge::option::overwrite_some)]
537542
pub latest: Option<bool>,
543+
#[merge(strategy = merge::option::overwrite_some)]
538544
pub recommended: Option<bool>,
539-
#[merge(strategy = merge::hashmap::recurse_some)]
545+
#[merge(strategy = merge::option_hashmap::recurse_some)]
540546
pub files: Option<HashMap<String, ForgeFile>>,
541547
}
542548

543549
#[skip_serializing_none]
544550
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
551+
#[serde(deny_unknown_fields)]
545552
pub struct ForgeMCVersionInfo {
553+
#[merge(strategy = merge::option::overwrite_some)]
546554
pub latest: Option<String>,
555+
#[merge(strategy = merge::option::overwrite_some)]
547556
pub recommended: Option<String>,
548557
#[merge(strategy = merge::vec::append)]
549558
pub versions: Vec<String>,
550559
}
551560

552561
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
562+
#[serde(deny_unknown_fields)]
553563
pub struct DerivedForgeIndex {
554564
#[merge(strategy = merge::hashmap::recurse)]
555565
pub versions: HashMap<String, ForgeEntry>,
@@ -558,6 +568,261 @@ pub struct DerivedForgeIndex {
558568
pub by_mc_version: HashMap<String, ForgeMCVersionInfo>,
559569
}
560570

571+
/// Example content
572+
/// ```json
573+
/// "install": {
574+
/// "profileName": "Forge",
575+
/// "target":"Forge8.9.0.753",
576+
/// "path":"net.minecraftforge:minecraftforge:8.9.0.753",
577+
/// "version":"Forge 8.9.0.753",
578+
/// "filePath":"minecraftforge-universal-1.6.1-8.9.0.753.jar",
579+
/// "welcome":"Welcome to the simple Forge installer.",
580+
/// "minecraft":"1.6.1",
581+
/// "logo":"/big_logo.png",
582+
/// "mirrorList": "http://files.minecraftforge.net/mirror-brand.list"
583+
/// },
584+
/// "install": {
585+
/// "profileName": "forge",
586+
/// "target":"1.11-forge1.11-13.19.0.2141",
587+
/// "path":"net.minecraftforge:forge:1.11-13.19.0.2141",
588+
/// "version":"forge 1.11-13.19.0.2141",
589+
/// "filePath":"forge-1.11-13.19.0.2141-universal.jar",
590+
/// "welcome":"Welcome to the simple forge installer.",
591+
/// "minecraft":"1.11",
592+
/// "mirrorList" : "http://files.minecraftforge.net/mirror-brand.list",
593+
/// "logo":"/big_logo.png",
594+
/// "modList":"none"
595+
/// },
596+
/// ```
597+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
598+
#[serde(deny_unknown_fields, rename_all = "camelCase")]
599+
pub struct ForgeInstallerProfileInstallSection {
600+
#[merge(strategy = merge::overwrite)]
601+
pub profile_name: String,
602+
#[merge(strategy = merge::overwrite)]
603+
pub target: String,
604+
pub path: GradleSpecifier,
605+
#[merge(strategy = merge::overwrite)]
606+
pub version: String,
607+
#[merge(strategy = merge::overwrite)]
608+
pub file_path: String,
609+
#[merge(strategy = merge::overwrite)]
610+
pub welcome: String,
611+
#[merge(strategy = merge::overwrite)]
612+
pub minecraft: String,
613+
#[merge(strategy = merge::overwrite)]
614+
pub logo: String,
615+
#[merge(strategy = merge::overwrite)]
616+
pub mirror_list: String,
617+
#[merge(strategy = merge::option::overwrite_some)]
618+
pub mod_list: Option<String>,
619+
}
620+
621+
#[skip_serializing_none]
622+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
623+
#[serde(deny_unknown_fields)]
624+
pub struct ForgeLibrary {
625+
#[merge(strategy = merge::overwrite)]
626+
pub url: Option<String>,
627+
#[serde(rename = "serverreq")]
628+
#[merge(strategy = merge::option::overwrite_some)]
629+
pub server_req: Option<bool>,
630+
#[serde(rename = "clientreq")]
631+
#[merge(strategy = merge::option::overwrite_some)]
632+
pub client_req: Option<bool>,
633+
#[merge(strategy = merge::option_vec::append_some)]
634+
pub checksums: Option<Vec<String>>,
635+
#[merge(strategy = merge::option::overwrite_some)]
636+
pub comment: Option<String>,
637+
}
638+
639+
#[skip_serializing_none]
640+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
641+
#[serde(deny_unknown_fields, rename_all = "camelCase")]
642+
pub struct ForgeVersionFile {
643+
#[merge(strategy = merge::option_vec::append_some)]
644+
pub libraries: Option<Vec<ForgeLibrary>>, // overrides Mojang libraries
645+
#[merge(strategy = merge::option::overwrite_some)]
646+
pub inherits_from: Option<String>,
647+
#[merge(strategy = merge::option::overwrite_some)]
648+
pub jar: Option<String>,
649+
}
650+
651+
/// Example content:
652+
/// ```json
653+
/// "optionals": [
654+
/// {
655+
/// "name": "Mercurius",
656+
/// "client": true,
657+
/// "server": true,
658+
/// "default": true,
659+
/// "inject": true,
660+
/// "desc": "A mod that collects statistics about Minecraft and your system.<br>Useful for Forge to understand how Minecraft/Forge are used.",
661+
/// "url": "http://www.minecraftforge.net/forum/index.php?topic=43278.0",
662+
/// "artifact": "net.minecraftforge:MercuriusUpdater:1.11.2",
663+
/// "maven": "http://maven.minecraftforge.net/"
664+
/// }
665+
/// ]
666+
/// ```
667+
#[skip_serializing_none]
668+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
669+
#[serde(deny_unknown_fields, rename_all = "camelCase")]
670+
pub struct ForgeOptional {
671+
#[merge(strategy = merge::option::overwrite_some)]
672+
pub name: Option<String>,
673+
#[merge(strategy = merge::option::overwrite_some)]
674+
pub client: Option<bool>,
675+
#[merge(strategy = merge::option::overwrite_some)]
676+
pub server: Option<bool>,
677+
#[merge(strategy = merge::option::overwrite_some)]
678+
pub default: Option<bool>,
679+
#[merge(strategy = merge::option::overwrite_some)]
680+
pub inject: Option<bool>,
681+
#[merge(strategy = merge::option::overwrite_some)]
682+
pub desc: Option<String>,
683+
#[merge(strategy = merge::option::overwrite_some)]
684+
pub url: Option<String>,
685+
#[merge(strategy = merge::option::recurse)]
686+
pub artifact: Option<GradleSpecifier>,
687+
#[merge(strategy = merge::option::overwrite_some)]
688+
pub maven: Option<String>,
689+
}
690+
691+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
692+
pub struct ForgeInstallerProfile {
693+
pub install: ForgeInstallerProfileInstallSection,
694+
#[serde(rename = "versionInfo")]
695+
pub version_info: ForgeVersionFile,
696+
#[merge(strategy = merge::option_vec::append_some)]
697+
pub optionals: Option<Vec<ForgeOptional>>,
698+
}
699+
700+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
701+
pub struct ForgeLegacyInfo {
702+
#[serde(rename = "releaseTime")]
703+
#[merge(strategy = merge::option::overwrite_some)]
704+
pub release_time: Option<String>,
705+
#[merge(strategy = merge::option::overwrite_some)]
706+
pub size: Option<i32>,
707+
#[merge(strategy = merge::option::overwrite_some)]
708+
pub sha256: Option<String>,
709+
#[merge(strategy = merge::option::overwrite_some)]
710+
pub sha1: Option<String>,
711+
}
712+
713+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
714+
pub struct ForgeLegacyInfoList {
715+
#[merge(strategy = merge::hashmap::recurse)]
716+
pub number: HashMap<String, ForgeLegacyInfo>,
717+
}
718+
719+
pub struct ForgeProcessedVersion {
720+
pub build: i32,
721+
pub raw_version: String,
722+
pub mc_version: String,
723+
pub mv_version_sane: String,
724+
pub branch: Option<String>,
725+
pub installer_filename: Option<String>,
726+
pub installer_url: Option<String>,
727+
pub universal_filename: Option<String>,
728+
pub universal_url: Option<String>,
729+
pub changelog_url: Option<String>,
730+
pub long_version: String,
731+
}
732+
733+
impl ForgeProcessedVersion {
734+
pub fn new(entry: &ForgeEntry) -> Self {
735+
let mut ver = Self {
736+
build: entry.build,
737+
raw_version: entry.version.clone(),
738+
mc_version: entry.mc_version.clone(),
739+
mv_version_sane: entry.mc_version.replacen("_pre", "-pre", 1),
740+
branch: entry.branch.clone(),
741+
installer_filename: None,
742+
installer_url: None,
743+
universal_filename: None,
744+
universal_url: None,
745+
changelog_url: None,
746+
long_version: format!("{}-{}", entry.mc_version, entry.version),
747+
};
748+
if let Some(branch) = &ver.branch {
749+
ver.long_version += &format!("-{}", branch);
750+
}
751+
752+
// to quote Scrumplex: "this comment's whole purpose is to say this: cringe"
753+
if let Some(files) = &entry.files {
754+
for (classifier, file) in files {
755+
let extension = &file.extension;
756+
let filename = file.filename(&ver.long_version);
757+
let url = file.url(&ver.long_version);
758+
759+
if (classifier == "installer") && (extension == "jar") {
760+
ver.installer_filename = Some(filename);
761+
ver.installer_url = Some(url);
762+
} else if (classifier == "universal" || classifier == "client")
763+
&& (extension == "jar" || extension == "zip")
764+
{
765+
ver.universal_filename = Some(filename);
766+
ver.universal_url = Some(url);
767+
} else if (classifier == "changelog") && (extension == "txt") {
768+
ver.changelog_url = Some(url);
769+
}
770+
}
771+
}
772+
773+
ver
774+
}
775+
776+
pub fn name(&self) -> String {
777+
format!("Forge {}", self.build)
778+
}
779+
780+
pub fn uses_installer(&self) -> bool {
781+
!(self.installer_url.is_none() || self.mc_version == "1.5.2")
782+
}
783+
784+
pub fn filename(&self) -> Option<String> {
785+
if self.uses_installer() {
786+
self.installer_filename.clone()
787+
} else {
788+
self.universal_filename.clone()
789+
}
790+
}
791+
792+
pub fn url(&self) -> Option<String> {
793+
if self.uses_installer() {
794+
self.installer_url.clone()
795+
} else {
796+
self.universal_url.clone()
797+
}
798+
}
799+
800+
pub fn is_supported(&self) -> bool {
801+
if self.url().is_none() {
802+
return false;
803+
}
804+
805+
let mut version_parts = self.raw_version.split(".");
806+
let num_version_parts = self.raw_version.split(".").count();
807+
if num_version_parts < 1 {
808+
return false;
809+
}
810+
811+
let major_version_str = version_parts.next().expect("Missing major version");
812+
let major_version = major_version_str.parse::<i32>();
813+
814+
if let Ok(major_version) = major_version {
815+
if major_version >= 37 {
816+
return false;
817+
}
818+
} else {
819+
return false;
820+
}
821+
822+
true
823+
}
824+
}
825+
561826
#[cfg(test)]
562827
mod tests {
563828
#[test]

0 commit comments

Comments
 (0)