1
1
use crate :: models:: merge:: { self , Merge } ;
2
2
3
+ use crate :: models:: GradleSpecifier ;
3
4
use serde:: { Deserialize , Serialize } ;
4
5
use serde_valid:: Validate ;
5
6
use serde_with:: skip_serializing_none;
@@ -494,6 +495,7 @@ pub enum ForgeInstallerManifestVersion {
494
495
}
495
496
496
497
#[ derive( Deserialize , Serialize , Clone , Debug , Validate , Merge ) ]
498
+ #[ serde( deny_unknown_fields) ]
497
499
pub struct ForgeFile {
498
500
#[ merge( strategy = merge:: overwrite) ]
499
501
pub classifier : String ,
@@ -504,14 +506,14 @@ pub struct ForgeFile {
504
506
}
505
507
506
508
impl ForgeFile {
507
- fn filename ( & self , long_version : & str ) -> String {
509
+ pub fn filename ( & self , long_version : & str ) -> String {
508
510
format ! (
509
511
"{}-{}-{}.{}" ,
510
512
"forge" , long_version, self . classifier, self . extension
511
513
)
512
514
}
513
515
514
- fn url ( & self , long_version : & str ) -> String {
516
+ pub fn url ( & self , long_version : & str ) -> String {
515
517
format ! (
516
518
"https://maven.minecraftforge.net/net/minecraftforge/forge/{}/{}" ,
517
519
long_version,
@@ -522,6 +524,7 @@ impl ForgeFile {
522
524
523
525
#[ skip_serializing_none]
524
526
#[ derive( Deserialize , Serialize , Clone , Debug , Validate , Merge , Default ) ]
527
+ #[ serde( deny_unknown_fields) ]
525
528
pub struct ForgeEntry {
526
529
#[ serde( rename = "longversion" ) ]
527
530
#[ merge( strategy = merge:: overwrite) ]
@@ -533,23 +536,30 @@ pub struct ForgeEntry {
533
536
pub version : String ,
534
537
#[ merge( strategy = merge:: overwrite) ]
535
538
pub build : i32 ,
539
+ #[ merge( strategy = merge:: option:: overwrite_some) ]
536
540
pub branch : Option < String > ,
541
+ #[ merge( strategy = merge:: option:: overwrite_some) ]
537
542
pub latest : Option < bool > ,
543
+ #[ merge( strategy = merge:: option:: overwrite_some) ]
538
544
pub recommended : Option < bool > ,
539
- #[ merge( strategy = merge:: hashmap :: recurse_some) ]
545
+ #[ merge( strategy = merge:: option_hashmap :: recurse_some) ]
540
546
pub files : Option < HashMap < String , ForgeFile > > ,
541
547
}
542
548
543
549
#[ skip_serializing_none]
544
550
#[ derive( Deserialize , Serialize , Clone , Debug , Validate , Merge , Default ) ]
551
+ #[ serde( deny_unknown_fields) ]
545
552
pub struct ForgeMCVersionInfo {
553
+ #[ merge( strategy = merge:: option:: overwrite_some) ]
546
554
pub latest : Option < String > ,
555
+ #[ merge( strategy = merge:: option:: overwrite_some) ]
547
556
pub recommended : Option < String > ,
548
557
#[ merge( strategy = merge:: vec:: append) ]
549
558
pub versions : Vec < String > ,
550
559
}
551
560
552
561
#[ derive( Deserialize , Serialize , Clone , Debug , Validate , Merge , Default ) ]
562
+ #[ serde( deny_unknown_fields) ]
553
563
pub struct DerivedForgeIndex {
554
564
#[ merge( strategy = merge:: hashmap:: recurse) ]
555
565
pub versions : HashMap < String , ForgeEntry > ,
@@ -558,6 +568,261 @@ pub struct DerivedForgeIndex {
558
568
pub by_mc_version : HashMap < String , ForgeMCVersionInfo > ,
559
569
}
560
570
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
+
561
826
#[ cfg( test) ]
562
827
mod tests {
563
828
#[ test]
0 commit comments