66import java .util .concurrent .locks .StampedLock ;
77import java .util .function .Supplier ;
88
9- import org .apache .commons .lang3 .ArrayUtils ;
109import org .jetbrains .annotations .Unmodifiable ;
1110
11+ import it .unimi .dsi .fastutil .objects .ObjectArrayList ;
1212import it .unimi .dsi .fastutil .objects .Reference2ObjectOpenHashMap ;
13- import it .unimi .dsi .fastutil .objects .ReferenceArrayList ;
1413import net .fabricmc .fabric .api .client .rendering .v1 .InvalidateRenderStateCallback ;
14+ import net .fabricmc .fabric .api .renderer .v1 .Renderer ;
15+ import net .fabricmc .fabric .api .renderer .v1 .mesh .MutableMesh ;
16+ import net .fabricmc .fabric .api .renderer .v1 .mesh .MutableQuadView ;
17+ import net .fabricmc .fabric .api .renderer .v1 .mesh .QuadEmitter ;
18+ import net .fabricmc .fabric .api .renderer .v1 .mesh .QuadTransform ;
1519import net .minecraft .block .BlockState ;
1620import net .minecraft .client .MinecraftClient ;
1721import net .minecraft .client .render .block .BlockModels ;
1822import net .minecraft .client .render .model .BakedModel ;
19- import net .minecraft .client .render .model .BakedQuad ;
2023import net .minecraft .client .texture .Sprite ;
24+ import net .minecraft .util .math .BlockPos ;
2125import net .minecraft .util .math .Direction ;
2226import net .minecraft .util .math .random .Random ;
27+ import net .minecraft .world .EmptyBlockRenderView ;
2328
2429public final class SpriteCalculator {
2530 private static final BlockModels MODELS = MinecraftClient .getInstance ().getBakedModelManager ().getBlockModels ();
26- private static final Direction [] CULL_FACES = ArrayUtils .add (Direction .values (), null );
2731
2832 private static final EnumMap <Direction , SpriteCache > SPRITE_CACHES = new EnumMap <>(Direction .class );
2933
@@ -40,24 +44,6 @@ public static Set<Sprite> getSprites(BlockState state, Direction face) {
4044 return SPRITE_CACHES .get (face ).getSprites (state );
4145 }
4246
43- @ Unmodifiable
44- public static Set <Sprite > calculateSprites (BlockState state , Direction face , Supplier <Random > randomSupplier ) {
45- List <Sprite > sprites = new ReferenceArrayList <>();
46- BakedModel model = MODELS .getModel (state );
47- try {
48- for (Direction cullFace : CULL_FACES ) {
49- for (BakedQuad quad : model .getQuads (state , cullFace , randomSupplier .get ())) {
50- if (quad .getFace () == face ) {
51- sprites .add (quad .getSprite ());
52- }
53- }
54- }
55- } catch (Exception e ) {
56- //
57- }
58- return !sprites .isEmpty () ? Set .copyOf (sprites ) : Set .of (model .getParticleSprite ());
59- }
60-
6147 public static void clearCache () {
6248 for (SpriteCache cache : SPRITE_CACHES .values ()) {
6349 cache .clear ();
@@ -67,6 +53,8 @@ public static void clearCache() {
6753 private static class SpriteCache {
6854 private final Direction face ;
6955 private final Reference2ObjectOpenHashMap <BlockState , Set <Sprite >> spritesMap = new Reference2ObjectOpenHashMap <>();
56+ private final MutableMesh mutableMesh = Renderer .get ().mutableMesh ();
57+ private final CollectingQuadTransform quadTransform ;
7058 private final Supplier <Random > randomSupplier = new Supplier <>() {
7159 private final Random random = Random .create ();
7260
@@ -81,6 +69,7 @@ public Random get() {
8169
8270 public SpriteCache (Direction face ) {
8371 this .face = face ;
72+ quadTransform = new CollectingQuadTransform (face );
8473 }
8574
8675 @ Unmodifiable
@@ -114,7 +103,7 @@ public Set<Sprite> getSprites(BlockState state) {
114103 try {
115104 sprites = spritesMap .get (state );
116105 if (sprites == null ) {
117- sprites = calculateSprites (state , face , randomSupplier );
106+ sprites = calculateSprites (state );
118107 spritesMap .put (state , sprites );
119108 }
120109 } finally {
@@ -125,13 +114,56 @@ public Set<Sprite> getSprites(BlockState state) {
125114 return sprites ;
126115 }
127116
117+ @ Unmodifiable
118+ private Set <Sprite > calculateSprites (BlockState state ) {
119+ BakedModel model = MODELS .getModel (state );
120+ QuadEmitter emitter = mutableMesh .emitter ();
121+ quadTransform .clear ();
122+ emitter .pushTransform (quadTransform );
123+ try {
124+ model .emitBlockQuads (emitter , EmptyBlockRenderView .INSTANCE , state , BlockPos .ORIGIN , randomSupplier , cullFace -> false );
125+ } catch (Exception e ) {
126+ //
127+ }
128+ emitter .popTransform ();
129+ Set <Sprite > sprites = quadTransform .result ();
130+ return !sprites .isEmpty () ? sprites : Set .of (model .getParticleSprite ());
131+ }
132+
128133 public void clear () {
129134 long writeStamp = lock .writeLock ();
130135 try {
131136 spritesMap .clear ();
137+ quadTransform .clear ();
132138 } finally {
133139 lock .unlockWrite (writeStamp );
134140 }
135141 }
142+
143+ private static class CollectingQuadTransform implements QuadTransform {
144+ private final Direction face ;
145+ private final List <Sprite > sprites = new ObjectArrayList <>();
146+
147+ private CollectingQuadTransform (Direction face ) {
148+ this .face = face ;
149+ }
150+
151+ @ Override
152+ public boolean transform (MutableQuadView quad ) {
153+ if (quad .lightFace () == face ) {
154+ sprites .add (RenderUtil .getSpriteFinder ().find (quad ));
155+ }
156+ return false ;
157+ }
158+
159+ public void clear () {
160+ sprites .clear ();
161+ }
162+
163+ @ Unmodifiable
164+ public Set <Sprite > result () {
165+ return Set .copyOf (sprites );
166+ }
167+ }
136168 }
137169}
0 commit comments