11package  fish .cichlidmc .cichlid_gradle .cache .mcmaven ;
22
3+ import  fish .cichlidmc .cichlid_gradle .cache .Artifact ;
34import  fish .cichlidmc .cichlid_gradle .cache .CichlidCache ;
4- import  fish .cichlidmc .cichlid_gradle .cache .storage .JarsStorage ;
5+ import  fish .cichlidmc .cichlid_gradle .cache .ManifestCache ;
6+ import  fish .cichlidmc .cichlid_gradle .cache .Transformers ;
7+ import  fish .cichlidmc .cichlid_gradle .cache .task .CacheTaskEnvironment ;
8+ import  fish .cichlidmc .cichlid_gradle .cache .task .impl .AssetsTask ;
9+ import  fish .cichlidmc .cichlid_gradle .cache .task .impl .DecompileTask ;
10+ import  fish .cichlidmc .cichlid_gradle .cache .task .impl .ReassembleTask ;
511import  fish .cichlidmc .cichlid_gradle .extension .def .MinecraftDefinition ;
612import  fish .cichlidmc .cichlid_gradle .extension .def .MinecraftDefinitionImpl ;
713import  fish .cichlidmc .cichlid_gradle .util .Distribution ;
14+ import  fish .cichlidmc .pistonmetaparser .FullVersion ;
15+ import  fish .cichlidmc .pistonmetaparser .manifest .Version ;
16+ import  org .gradle .api .InvalidUserDataException ;
817import  org .gradle .api .NamedDomainObjectContainer ;
918import  org .gradle .api .Project ;
1019import  org .gradle .api .logging .Logger ;
1120import  org .gradle .api .logging .Logging ;
1221import  org .jetbrains .annotations .Nullable ;
1322
23+ import  java .io .ByteArrayInputStream ;
1424import  java .io .File ;
25+ import  java .io .IOException ;
26+ import  java .io .InputStream ;
1527import  java .net .URI ;
28+ import  java .nio .charset .StandardCharsets ;
1629import  java .nio .file .Files ;
1730import  java .nio .file .Path ;
1831import  java .util .regex .Matcher ;
2336 * Provides Minecraft jars and pom files for each version. 
2437 */ 
2538public  final  class  MinecraftMaven  {
39+ 	public  static  final  String  GROUP  = "net.minecraft" ;
40+ 	public  static  final  String  MODULE  = "minecraft" ;
41+ 
2642	/** 
2743	 * Regex for files that could possibly be provided. 
2844	 */ 
@@ -41,40 +57,79 @@ public MinecraftMaven(NamedDomainObjectContainer<MinecraftDefinition> defs, Cich
4157		this .cache  = cache ;
4258	}
4359
44- 	/** 
45- 	 * Find a path corresponding to the file at the requested location. 
46- 	 * Returns null if one does not exist. 
47- 	 */ 
4860	@ Nullable 
49- 	public  Path   getFile (URI  uri ) {
61+ 	public  InputStream   get (URI  uri )  throws   IOException  {
5062		Request  request  = extractRequest (uri );
5163		if  (request  == null )
5264			return  null ;
5365
5466		MinecraftDefinitionImpl  def  = (MinecraftDefinitionImpl ) this .defs .findByName (request .def );
55- 		if  (def  == null )
56- 			return  null ;
67+ 		if  (def  == null ) {
68+ 			throw  new  InvalidUserDataException ("Minecraft definition '"  + request .def  + "' does not exist" );
69+ 		}
5770
5871		String  version  = def .getVersionOrThrow ();
5972
60- 		System .out .println ("resolving transformers" );
73+ 		Iterable <File > transformerFiles  = def .resolvableTransformers ().getIncoming ().getFiles ();
74+ 		Transformers  transformers  = new  Transformers (transformerFiles , request .hash );
75+ 
76+ 		return  this .getArtifact (version , def .dist (), transformers , request );
77+ 	}
78+ 
79+ 	@ Nullable 
80+ 	private  InputStream  getArtifact (String  versionId , Distribution  dist , Transformers  transformers , Request  request ) throws  IOException  {
81+ 		// see if this version actually exists 
82+ 		Version  version  = ManifestCache .getVersion (versionId );
83+ 		if  (version  == null )
84+ 			return  null ;
6185
62- 		for  (File  file  : def .resolvableTransformers ().getIncoming ().getFiles ()) {
63- 			logger .quiet ("Transformer: {}" , file );
86+ 		FullVersion  fullVersion  = ManifestCache .expand (version );
87+ 		// and the dist. all versions have a client, check for server 
88+ 		if  (dist  != Distribution .CLIENT  && fullVersion .downloads .server .isEmpty ())
89+ 			return  null ;
90+ 
91+ 		if  (fullVersion .downloads .clientMappings .isEmpty ()) {
92+ 			throw  new  InvalidUserDataException ("Versions pre-mojmap are not currently supported!" );
6493		}
6594
66- 		this .cache .ensureVersionIsCached (version );
67- 		JarsStorage  storage  = this .cache .getVersion (version ).jars ;
95+ 		if  (request .artifact  == Artifact .POM ) {
96+ 			return  this .getPom (fullVersion , dist , request );
97+ 		}
6898
69- 		Distribution  dist  = def .getDistribution ().get ();
99+ 		boolean  needsAssets  = dist .needsAssets () && !this .cache .assets .isComplete (fullVersion .assetIndex );
100+ 		Path  jar  = this .cache .reassembledJars .get (versionId , transformers .hash (), dist , request .artifact );
101+ 		boolean  needsJar  = !Files .exists (jar );
70102
71- 		Path  path  = switch  (request .type ) {
72- 			case  JAR  -> storage .path (dist );
73- 			case  SOURCES  -> storage .sources (dist );
74- 			case  POM  -> storage .metadata (dist );
75- 		};
103+ 		if  (!needsAssets  && !needsJar ) {
104+ 			return  Files .newInputStream (jar );
105+ 		}
106+ 
107+ 		CacheTaskEnvironment .Builder  builder  = new  CacheTaskEnvironment .Builder (fullVersion , this .cache , dist , transformers );
108+ 
109+ 		if  (needsAssets ) {
110+ 			builder .add (AssetsTask ::new );
111+ 		}
112+ 
113+ 		if  (needsJar ) {
114+ 			builder .add (env  -> new  ReassembleTask (env , request .artifact  == Artifact .SOURCES ));
115+ 		}
116+ 
117+ 		builder .start ().report ();
76118
77- 		return  Files .exists (path ) ? path  : null ;
119+ 		// all tasks are done. If an exception wasn't thrown by report, everything was successful. 
120+ 		return  Files .newInputStream (jar );
121+ 	}
122+ 
123+ 	private  InputStream  getPom (FullVersion  version , Distribution  dist , Request  request ) throws  IOException  {
124+ 		Path  template  = this .cache .pomTemplates .get (version .id , dist );
125+ 		if  (!Files .exists (template )) {
126+ 			PomGenerator .generate (version , template );
127+ 		}
128+ 
129+ 		// file should now exist 
130+ 		String  content  = Files .readString (template );
131+ 		String  filled  = content .replace (PomGenerator .VERSION_PLACEHOLDER , request .gradleRequestedVersion ());
132+ 		return  new  ByteArrayInputStream (filled .getBytes (StandardCharsets .UTF_8 ));
78133	}
79134
80135	@ Nullable 
@@ -97,22 +152,26 @@ private static Request extractRequest(URI uri) {
97152		if  (!version1 .equals (version2 ))
98153			return  null ;
99154
100- 		// version is defName_hash , extract the name 
101- 		int  underscore  = version1 .indexOf ('_ ' );
102- 		if  (underscore  == -1 )
155+ 		// version is defName$hash , extract the name 
156+ 		int  separator  = version1 .indexOf ('$ ' );
157+ 		if  (separator  == -1 )
103158			return  null ;
104159
105- 		String  defName  = version1 .substring (0 , underscore );
160+ 		String  defName  = version1 .substring (0 , separator );
161+ 		String  hash  = version1 .substring (separator  + 1 );
106162
107- 		Request . Type   type  = switch  (matcher .group (3 )) {
108- 			case  "jar"  -> sources  ? Request . Type . SOURCES  : Request . Type .JAR ;
109- 			case  "pom"  -> Request . Type .POM ;
110- 			default  -> throw   new   RuntimeException ( "Invalid Type" ) ;
163+ 		Artifact   artifact  = switch  (matcher .group (3 )) {
164+ 			case  "jar"  -> sources  ? Artifact . SOURCES  : Artifact .JAR ;
165+ 			case  "pom"  -> Artifact .POM ;
166+ 			default  -> null ;
111167		};
112168
113- 		logger .quiet ("Intercepted request for Minecraft definition {}, {}" , defName , type );
169+ 		if  (artifact  == null )
170+ 			return  null ;
171+ 
172+ 		logger .quiet ("Intercepted request for Minecraft definition {}, {}" , defName , artifact );
114173
115- 		return  new  Request (defName , type );
174+ 		return  new  Request (defName , hash ,  artifact );
116175	}
117176
118177	public  static  String  createProtocol (Project  project ) {
@@ -135,9 +194,10 @@ private static char filterChar(char c) {
135194		return  (c  >= 'a'  && c  <= 'z' ) || (c  >= 'A'  && c  <= 'Z' ) || (c  >= '0'  && c  <= '9' ) || (c  == '+'  || c  == '-'  || c  == '.' ) ? c  : '-' ;
136195	}
137196
138- 	private  record  Request (String  def , Type  type ) {
139- 		private  enum  Type  {
140- 			JAR , SOURCES , POM 
197+ 	private  record  Request (String  def , String  hash , Artifact  artifact ) {
198+ 		// the version specified in the pom needs to match what gradle requested exactly (defName$hash) or it'll be rejected 
199+ 		private  String  gradleRequestedVersion () {
200+ 			return  this .def  + '$'  + this .hash ;
141201		}
142202	}
143203}
0 commit comments