11package platinpython .rgbblocks .util .pack ;
22
3+ import com .google .common .collect .ImmutableMap ;
34import com .google .common .collect .ImmutableSet ;
45import com .google .gson .JsonObject ;
56import com .mojang .blaze3d .platform .NativeImage ;
6- import com . mojang . datafixers . util . Pair ;
7+ import net . minecraft . SharedConstants ;
78import net .minecraft .client .Minecraft ;
89import net .minecraft .network .chat .Component ;
910import net .minecraft .resources .ResourceLocation ;
1314import net .minecraft .server .packs .metadata .pack .PackMetadataSection ;
1415import net .minecraft .server .packs .metadata .pack .PackMetadataSectionSerializer ;
1516import net .minecraft .server .packs .resources .IoSupplier ;
16- import net .minecraft .server .packs .resources .PreparableReloadListener ;
1717import net .minecraft .server .packs .resources .ResourceManager ;
1818import net .minecraft .util .GsonHelper ;
19- import net .minecraft . util . profiling . ProfilerFiller ;
20- import org .apache . commons . io . IOUtils ;
19+ import net .minecraftforge . fml . ModList ;
20+ import org .jspecify . annotations . Nullable ;
2121import platinpython .rgbblocks .RGBBlocks ;
2222import platinpython .rgbblocks .util .Color ;
2323
2929import java .nio .charset .StandardCharsets ;
3030import java .util .HashMap ;
3131import java .util .Map ;
32- import java .util .NoSuchElementException ;
33- import java .util .Optional ;
3432import java .util .Set ;
35- import java .util .concurrent .CompletableFuture ;
36- import java .util .concurrent .Executor ;
33+ import java .util .stream .Stream ;
3734
38- public class RGBBlocksPack extends AbstractPackResources implements PreparableReloadListener {
35+ public class RGBBlocksPack extends AbstractPackResources {
3936 public static final String TEXTURE_DIRECTORY = "textures/" ;
4037 public static final String BLOCK_DIRECTORY = "block/" ;
4138 public static final Set <String > NAMESPACES = ImmutableSet .of (RGBBlocks .MOD_ID );
4239
40+ private static final ImmutableMap <ResourceLocation , ResourceLocation > RESOURCES =
41+ Stream .<Map .Entry <String , String >>builder ()
42+ .add (Map .entry ("concrete" , "white_concrete" ))
43+ .add (Map .entry ("concrete_powder" , "white_concrete_powder" ))
44+ .add (Map .entry ("wool" , "white_wool" ))
45+ .add (Map .entry ("planks" , "birch_planks" ))
46+ .add (Map .entry ("terracotta" , "white_terracotta" ))
47+ .add (Map .entry ("glass" , "white_stained_glass" ))
48+ .add (Map .entry ("glass_pane_top" , "white_stained_glass_pane_top" ))
49+ .add (Map .entry ("glowstone" , "glowstone" ))
50+ .add (Map .entry ("redstone_lamp" , "redstone_lamp" ))
51+ .add (Map .entry ("redstone_lamp_on" , "redstone_lamp_on" ))
52+ .add (Map .entry ("prismarine" , "prismarine" ))
53+ .add (Map .entry ("prismarine_bricks" , "prismarine_bricks" ))
54+ .add (Map .entry ("dark_prismarine" , "dark_prismarine" ))
55+ .add (Map .entry ("sea_lantern" , "sea_lantern" ))
56+ .build ()
57+ .flatMap (RGBBlocksPack ::makeIDs )
58+ .collect (ImmutableMap .toImmutableMap (Map .Entry ::getKey , Map .Entry ::getValue ));
59+
4360 private final PackMetadataSection packInfo ;
44- private Map <ResourceLocation , IoSupplier <InputStream >> resources = new HashMap <>();
45- private final Map <ResourceLocation , ResourceLocation > textures = new HashMap <>();
61+ private final HashMap <ResourceLocation , IoSupplier <InputStream >> resources = new HashMap <>();
4662
4763 public RGBBlocksPack () {
4864 super ("rgbblocks_virtual_pack" , true );
49- this .packInfo = new PackMetadataSection (Component .translatable ("rgbblocks.pack_description" ), 7 );
50- fillTexturesMap ();
51- }
52-
53- private void fillTexturesMap () {
54- Map <String , String > map = new HashMap <>();
55-
56- map .put ("concrete" , "white_concrete" );
57- map .put ("concrete_powder" , "white_concrete_powder" );
58- map .put ("wool" , "white_wool" );
59- map .put ("planks" , "birch_planks" );
60- map .put ("terracotta" , "white_terracotta" );
61- map .put ("glass" , "white_stained_glass" );
62- map .put ("glass_pane_top" , "white_stained_glass_pane_top" );
63- map .put ("glowstone" , "glowstone" );
64- map .put ("redstone_lamp" , "redstone_lamp" );
65- map .put ("redstone_lamp_on" , "redstone_lamp_on" );
66- map .put ("prismarine" , "prismarine" );
67- map .put ("prismarine_bricks" , "prismarine_bricks" );
68- map .put ("dark_prismarine" , "dark_prismarine" );
69- map .put ("sea_lantern" , "sea_lantern" );
70-
71- map .forEach (
72- (modName , vanillaName ) -> textures .put (
73- new ResourceLocation (RGBBlocks .MOD_ID , BLOCK_DIRECTORY + modName ),
74- new ResourceLocation (BLOCK_DIRECTORY + vanillaName )
75- )
65+ this .packInfo = new PackMetadataSection (
66+ Component .translatable ("rgbblocks.pack_description" ),
67+ SharedConstants .getCurrentVersion ().getPackVersion (PackType .CLIENT_RESOURCES )
7668 );
7769 }
7870
79- @ Override
80- public CompletableFuture <Void > reload (
81- PreparationBarrier stage ,
82- ResourceManager manager ,
83- ProfilerFiller workerProfiler ,
84- ProfilerFiller mainProfiler ,
85- Executor workerExecutor ,
86- Executor mainExecutor
87- ) {
88- this .gatherTextureData (manager , mainProfiler );
89- return CompletableFuture .supplyAsync (() -> null , workerExecutor )
90- .thenCompose (stage ::wait )
91- .thenAcceptAsync ((noResult ) -> {}, mainExecutor );
92- }
93-
94- protected void gatherTextureData (ResourceManager manager , ProfilerFiller profiler ) {
95- Map <ResourceLocation , IoSupplier <InputStream >> resourceStreams = new HashMap <>();
96-
97- textures .forEach (
98- (
99- modLocation ,
100- vanillaLocation
101- ) -> generateImage (modLocation , vanillaLocation , Minecraft .getInstance ().getResourceManager ())
102- .ifPresent (pair -> {
103- NativeImage image = pair .getFirst ();
104- ResourceLocation textureID = makeTextureID (modLocation );
105- resourceStreams .put (textureID , () -> new ByteArrayInputStream (image .asByteArray ()));
106- pair .getSecond ()
107- .ifPresent (
108- metadataGetter -> resourceStreams .put (getMetadataLocation (textureID ), metadataGetter )
109- );
110- })
71+ private static Stream <Map .Entry <ResourceLocation , ResourceLocation >> makeIDs (Map .Entry <String , String > entry ) {
72+ Map .Entry <ResourceLocation , ResourceLocation > paths = Map .entry (
73+ new ResourceLocation (RGBBlocks .MOD_ID , BLOCK_DIRECTORY + entry .getKey ()),
74+ new ResourceLocation (BLOCK_DIRECTORY + entry .getValue ())
11175 );
112-
113- this .resources = resourceStreams ;
76+ Map .Entry <ResourceLocation , ResourceLocation > texture =
77+ Map .entry (makeTextureID (paths .getKey ()), makeTextureID (paths .getValue ()));
78+ return Stream
79+ .of (texture , Map .entry (getMetadataLocation (texture .getKey ()), getMetadataLocation (texture .getValue ())));
11480 }
11581
116- public static ResourceLocation makeTextureID (ResourceLocation id ) {
117- return new ResourceLocation ( id .getNamespace (), TEXTURE_DIRECTORY + id . getPath () + ".png" );
82+ private static ResourceLocation makeTextureID (ResourceLocation id ) {
83+ return id .withPath ( path -> TEXTURE_DIRECTORY + path + ".png" );
11884 }
11985
120- public static ResourceLocation getMetadataLocation (ResourceLocation id ) {
121- return new ResourceLocation ( id .getNamespace (), id . getPath () + ".mcmeta" );
86+ private static ResourceLocation getMetadataLocation (ResourceLocation id ) {
87+ return id .withSuffix ( ".mcmeta" );
12288 }
12389
124- public Optional < Pair < NativeImage , Optional < IoSupplier <InputStream >>>> generateImage (
90+ private @ Nullable IoSupplier <InputStream > computeImage (
12591 ResourceLocation modLocation ,
12692 ResourceLocation vanillaLocation ,
12793 ResourceManager manager
12894 ) {
129- ResourceLocation parentFile = makeTextureID (vanillaLocation );
130- try (InputStream inputStream = manager .getResource (parentFile ).orElseThrow ().open ()) {
95+ try (InputStream inputStream = manager .getResourceOrThrow (vanillaLocation ).open ()) {
13196 NativeImage image = NativeImage .read (inputStream );
13297 NativeImage transformedImage = this .transformImage (image );
133- ResourceLocation metadata = getMetadataLocation (parentFile );
134- Optional <IoSupplier <InputStream >> metadataLookup = Optional .empty ();
135- BufferedReader bufferedReader = null ;
136- JsonObject metadataJson ;
137- if (manager .getResource (metadata ).isPresent ()) {
138- try (InputStream metadataStream = manager .getResource (metadata ).get ().open ()) {
139- bufferedReader = new BufferedReader (new InputStreamReader (metadataStream , StandardCharsets .UTF_8 ));
140- metadataJson = GsonHelper .parse (bufferedReader );
141- } catch (Exception e ) {
142- return Optional .empty ();
143- } finally {
144- IOUtils .closeQuietly (bufferedReader );
145- }
146- JsonObject metaDataJsonForLambda = metadataJson ;
147- metadataLookup =
148- Optional .of (() -> new ByteArrayInputStream (metaDataJsonForLambda .toString ().getBytes ()));
149- }
150- return Optional .of (Pair .of (transformedImage , metadataLookup ));
151- } catch (IOException | NoSuchElementException e ) {
152- return Optional .empty ();
98+ return () -> new ByteArrayInputStream (transformedImage .asByteArray ());
99+ } catch (IOException e ) {
100+ RGBBlocks .LOGGER .error ("Error while generating {}" , modLocation , e );
101+ return null ;
153102 }
154103 }
155104
156- public NativeImage transformImage (NativeImage image ) {
105+ private @ Nullable IoSupplier <InputStream > computeMetadata (
106+ ResourceLocation modLocation ,
107+ ResourceLocation vanillaLocation ,
108+ ResourceManager manager
109+ ) {
110+ return manager .getResource (vanillaLocation ).<IoSupplier <InputStream >>map (resource -> {
111+ try (
112+ BufferedReader bufferedReader =
113+ new BufferedReader (new InputStreamReader (resource .open (), StandardCharsets .UTF_8 ))
114+ ) {
115+ JsonObject metadataJson = GsonHelper .parse (bufferedReader );
116+ return () -> new ByteArrayInputStream (metadataJson .toString ().getBytes ());
117+ } catch (IOException e ) {
118+ RGBBlocks .LOGGER .error ("Error while generating {}" , modLocation , e );
119+ return null ;
120+ }
121+ }).orElse (() -> new ByteArrayInputStream ("{}" .getBytes ()));
122+ }
123+
124+ private NativeImage transformImage (NativeImage image ) {
157125 for (int x = 0 ; x < image .getWidth (); x ++) {
158126 for (int y = 0 ; y < image .getHeight (); y ++) {
159127 int oldColor = image .getPixelRGBA (x , y );
@@ -169,19 +137,20 @@ public NativeImage transformImage(NativeImage image) {
169137 return image ;
170138 }
171139
172- @ Override
173- public String getName () {
174- return Component .translatable ("rgbblocks.pack_title" ).getString ();
175- }
176-
177140 @ SuppressWarnings ("unchecked" )
178141 @ Override
179- public <T > T getMetadataSection (MetadataSectionSerializer <T > serializer ) {
142+ public <T > @ Nullable T getMetadataSection (MetadataSectionSerializer <T > serializer ) {
180143 return serializer instanceof PackMetadataSectionSerializer ? (T ) this .packInfo : null ;
181144 }
182145
183146 @ Override
184- public IoSupplier <InputStream > getRootResource (String ... fileName ) {
147+ public @ Nullable IoSupplier <InputStream > getRootResource (String ... elements ) {
148+ for (String name : elements ) {
149+ if (!name .equals ("pack.png" )) {
150+ continue ;
151+ }
152+ return IoSupplier .create (ModList .get ().getModFileById (RGBBlocks .MOD_ID ).getFile ().findResource ("logo.png" ));
153+ }
185154 return null ;
186155 }
187156
@@ -194,27 +163,32 @@ public Set<String> getNamespaces(PackType type) {
194163 }
195164
196165 @ Override
197- public IoSupplier <InputStream > getResource (PackType type , ResourceLocation id ) {
198- if (this .resources .containsKey (id )) {
199- IoSupplier <InputStream > streamGetter = this .resources .get (id );
200- if (streamGetter == null ) {
201- return null ;
166+ public @ Nullable IoSupplier <InputStream > getResource (PackType type , ResourceLocation id ) {
167+ if (RESOURCES .containsKey (id )) {
168+ ResourceManager manager = Minecraft .getInstance ().getResourceManager ();
169+ IoSupplier <InputStream > streamSupplier ;
170+ if (id .getPath ().endsWith (".mcmeta" )) {
171+ // noinspection DataFlowIssue
172+ streamSupplier = this .resources
173+ .computeIfAbsent (id , location -> computeMetadata (location , RESOURCES .get (location ), manager ));
174+ } else {
175+ // noinspection DataFlowIssue
176+ streamSupplier = this .resources
177+ .computeIfAbsent (id , location -> computeImage (location , RESOURCES .get (location ), manager ));
202178 }
203-
204179 try {
205- return streamGetter ;
180+ return streamSupplier ;
206181 } catch (Exception e ) {
207182 return null ;
208183 }
209- } else {
210- return null ;
211184 }
185+ return null ;
212186 }
213187
214188 @ Override
215189 public void listResources (PackType type , String namespace , String id , ResourceOutput output ) {
216190 if (namespace .equals (RGBBlocks .MOD_ID )) {
217- this . resources . forEach ((name , supplier ) -> {
191+ RESOURCES . forEach ((name , ignored ) -> {
218192 if (name .getPath ().startsWith (id )) {
219193 output .accept (name , getResource (type , name ));
220194 }
0 commit comments