@@ -103,22 +103,21 @@ protected static double maxDistance(int i, int a) {
103103
104104 @ Shadow @ Final private DensityFunction depthDensityFunction ;
105105
106+ @ Shadow protected abstract AquiferSampler .FluidLevel getWaterLevel (int i );
107+
106108 @ Unique
107- private int c2me$dist1 ;
108- @ Unique
109- private int c2me$dist2 ;
110- @ Unique
111- private int c2me$dist3 ;
112- @ Unique
113- private long c2me$pos1 ;
109+ private int c2me$packed1 ;
114110 @ Unique
115- private long c2me$pos2 ;
111+ private int c2me$packed2 ;
116112 @ Unique
117- private long c2me$pos3 ;
113+ private int c2me$packed3 ;
118114
119115 @ Unique
120116 private double c2me$mutableDoubleThingy ;
121117
118+ @ Unique
119+ private short [] c2me$packedBlockPositions ;
120+
122121 @ Inject (method = "<init>" , at = @ At ("RETURN" ))
123122 private void onInit (CallbackInfo info ) {
124123 // preload position cache
@@ -128,6 +127,8 @@ private void onInit(CallbackInfo info) {
128127
129128 int sizeY = this .blockPositions .length / (this .sizeX * this .sizeZ );
130129
130+ this .c2me$packedBlockPositions = new short [this .blockPositions .length ];
131+
131132 final Random random = RandomUtils .getRandom (this .randomDeriver );
132133 // index: y, z, x
133134 for (int y = 0 ; y < sizeY ; y ++) {
@@ -137,11 +138,15 @@ private void onInit(CallbackInfo info) {
137138 final int y1 = y + this .startY ;
138139 final int z1 = z + this .startZ ;
139140 RandomUtils .derive (this .randomDeriver , random , x1 , y1 , z1 );
140- int x2 = x1 * 16 + random .nextInt (10 );
141- int y2 = y1 * 12 + random .nextInt (9 );
142- int z2 = z1 * 16 + random .nextInt (10 );
141+ int r0 = random .nextInt (10 );
142+ int r1 = random .nextInt (9 );
143+ int r2 = random .nextInt (10 );
144+ int x2 = x1 * 16 + r0 ;
145+ int y2 = y1 * 12 + r1 ;
146+ int z2 = z1 * 16 + r2 ;
143147 int index = this .index (x1 , y1 , z1 );
144148 this .blockPositions [index ] = BlockPos .asLong (x2 , y2 , z2 );
149+ this .c2me$packedBlockPositions [index ] = (short ) ((r0 << 8 ) | (r1 << 4 ) | r2 );
145150 }
146151 }
147152 }
@@ -152,6 +157,30 @@ private void onInit(CallbackInfo info) {
152157 }
153158 }
154159
160+ @ Unique
161+ private static int c2me$unpackPackedX (int packed ) {
162+ return packed >> 8 ;
163+ }
164+
165+ @ Unique
166+ private static int c2me$unpackPackedY (int packed ) {
167+ return (packed >> 4 ) & 0b1111;
168+ }
169+
170+ @ Unique
171+ private static int c2me$unpackPackedZ (int packed ) {
172+ return packed & 0b1111;
173+ }
174+
175+ @ Unique
176+ private static int c2me$unpackPackedDist (int packed ) {
177+ return packed >> 20 ;
178+ }
179+
180+ private static int c2me$unpackPackedPosIdx (int packed ) {
181+ return packed & 0xffff ;
182+ }
183+
155184 /**
156185 * @author ishland
157186 * @reason make C2 happier by splitting method into many
@@ -178,8 +207,8 @@ public BlockState apply(DensityFunction.NoisePos pos, double density) {
178207
179208 @ Unique
180209 private @ Nullable BlockState aquiferExtracted$applyPost (DensityFunction .NoisePos pos , double density , int j , int i , int k ) {
181- AquiferSampler .FluidLevel fluidLevel2 = this .getWaterLevel ( this .c2me$pos1 );
182- double d = maxDistance (this .c2me$dist1 , this .c2me$dist2 );
210+ AquiferSampler .FluidLevel fluidLevel2 = this .c2me$getWaterLevelIndexed ( c2me$unpackPackedPosIdx ( this .c2me$packed1 ) );
211+ double d = maxDistance (c2me$unpackPackedDist ( this .c2me$packed1 ), c2me$unpackPackedDist ( this .c2me$packed2 ) );
183212 BlockState blockState = fluidLevel2 .getBlockState (j );
184213 if (d <= 0.0 ) {
185214 this .needsFluidTick = d >= NEEDS_FLUID_TICK_DISTANCE_THRESHOLD ;
@@ -190,7 +219,7 @@ public BlockState apply(DensityFunction.NoisePos pos, double density) {
190219 } else {
191220// MutableDouble mutableDouble = new MutableDouble(Double.NaN); // 234MB/s alloc rate at 480 cps
192221 this .c2me$mutableDoubleThingy = Double .NaN ;
193- AquiferSampler .FluidLevel fluidLevel3 = this .getWaterLevel ( this .c2me$pos2 );
222+ AquiferSampler .FluidLevel fluidLevel3 = this .c2me$getWaterLevelIndexed ( c2me$unpackPackedPosIdx ( this .c2me$packed2 ) );
194223 double e = d * this .c2me$calculateDensityModified (pos , fluidLevel2 , fluidLevel3 );
195224 if (density + e > 0.0 ) {
196225 this .needsFluidTick = false ;
@@ -203,11 +232,12 @@ public BlockState apply(DensityFunction.NoisePos pos, double density) {
203232
204233 @ Unique
205234 private BlockState aquiferExtracted$getFinalBlockState (DensityFunction .NoisePos pos , double density , double d , AquiferSampler .FluidLevel fluidLevel2 , AquiferSampler .FluidLevel fluidLevel3 , BlockState blockState ) {
206- AquiferSampler .FluidLevel fluidLevel4 = this .getWaterLevel (this .c2me$pos3 );
207- double f = maxDistance (this .c2me$dist1 , this .c2me$dist3 );
235+ AquiferSampler .FluidLevel fluidLevel4 = this .c2me$getWaterLevelIndexed (c2me$unpackPackedPosIdx (this .c2me$packed3 ));
236+ int dist3 = c2me$unpackPackedDist (this .c2me$packed3 );
237+ double f = maxDistance (c2me$unpackPackedDist (this .c2me$packed1 ), dist3 );
208238 if (aquiferExtracted$extractedCheckFG (pos , density , d , fluidLevel2 , f , fluidLevel4 )) return null ;
209239
210- double g = maxDistance (this . c2me$dist2 , this .c2me$dist3 );
240+ double g = maxDistance (c2me$unpackPackedDist ( this .c2me$packed2 ), dist3 );
211241 if (aquiferExtracted$extractedCheckFG (pos , density , d , fluidLevel3 , g , fluidLevel4 )) return null ;
212242
213243 this .needsFluidTick = true ;
@@ -227,82 +257,79 @@ public BlockState apply(DensityFunction.NoisePos pos, double density) {
227257 }
228258
229259 @ Unique
230- @ NotNull
231260 private void aquiferExtracted$refreshDistPosIdx (int x , int y , int z ) {
232261 int gx = (x - 5 ) >> 4 ;
233262 int gy = Math .floorDiv (y + 1 , 12 );
234263 int gz = (z - 5 ) >> 4 ;
235- int dist1 = Integer .MAX_VALUE ;
236- int dist2 = Integer .MAX_VALUE ;
237- int dist3 = Integer .MAX_VALUE ;
238- long pos1 = 0 ;
239- long pos2 = 0 ;
240- long pos3 = 0 ;
264+ int A = Integer .MAX_VALUE ;
265+ int B = Integer .MAX_VALUE ;
266+ int C = Integer .MAX_VALUE ;
241267
268+ int index = 12 ; // 12 max
242269 for (int offY = -1 ; offY <= 1 ; ++offY ) {
270+ int gymul = (gy + offY ) * 12 ;
243271 for (int offZ = 0 ; offZ <= 1 ; ++offZ ) {
244- for ( int offX = 0 ; offX <= 1 ; ++ offX ) {
245- int posIdx = this . index ( gx + offX , gy + offY , gz + offZ );
246-
247- long position = this . blockPositions [ posIdx ] ;
248-
249- int dx = BlockPos . unpackLongX ( position ) - x ;
250- int dy = BlockPos . unpackLongY ( position ) - y ;
251- int dz = BlockPos . unpackLongZ ( position ) - z ;
252- int dist = dx * dx + dy * dy + dz * dz ;
253-
254- // unexplainable branch prediction magic
255- if ( dist3 >= dist ) {
256- pos3 = position ;
257- dist3 = dist ;
258- }
259- if ( dist2 >= dist ) {
260- pos3 = pos2 ;
261- dist3 = dist2 ;
262- pos2 = position ;
263- dist2 = dist ;
264- }
265- if ( dist1 >= dist ) {
266- pos2 = pos1 ;
267- dist2 = dist1 ;
268- pos1 = position ;
269- dist1 = dist ;
270- }
272+ int gzmul = ( gz + offZ ) << 4 ;
273+
274+ int index0 = index - 1 ;
275+ int posIdx0 = this . index ( gx , gy + offY , gz + offZ ) ;
276+ int position0 = this . c2me$packedBlockPositions [ posIdx0 ];
277+ int dx0 = ( gx << 4 ) + c2me$unpackPackedX ( position0 ) - x ;
278+ int dy0 = gymul + c2me$unpackPackedY ( position0 ) - y ;
279+ int dz0 = gzmul + c2me$unpackPackedZ ( position0 ) - z ;
280+ int dist_0 = dx0 * dx0 + dy0 * dy0 + dz0 * dz0 ;
281+
282+ int index1 = index - 2 ;
283+ int posIdx1 = posIdx0 + 1 ;
284+ int position1 = this . c2me$packedBlockPositions [ posIdx1 ] ;
285+ int dx1 = (( gx + 1 ) << 4 ) + c2me$unpackPackedX ( position1 ) - x ;
286+ int dy1 = gymul + c2me$unpackPackedY ( position1 ) - y ;
287+ int dz1 = gzmul + c2me$unpackPackedZ ( position1 ) - z ;
288+ int dist_1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1 ;
289+
290+ int p0 = ( dist_0 << 20 ) | ( index0 << 16 ) | posIdx0 ;
291+ if ( p0 <= C ) {
292+ int n01 = Math . max ( A , p0 );
293+ A = Math . min ( A , p0 );
294+
295+ int n02 = Math . max ( B , n01 ) ;
296+ B = Math . min ( B , n01 ) ;
297+
298+ C = Math . min ( C , n02 );
271299 }
300+
301+ int p1 = (dist_1 << 20 ) | (index1 << 16 ) | posIdx1 ;
302+ if (p1 <= C ) {
303+ int n11 = Math .max (A , p1 );
304+ A = Math .min (A , p1 );
305+
306+ int n12 = Math .max (B , n11 );
307+ B = Math .min (B , n11 );
308+
309+ C = Math .min (C , n12 );
310+ }
311+
312+ index -= 2 ;
272313 }
273314 }
274315
275- this .c2me$dist1 = dist1 ;
276- this .c2me$dist2 = dist2 ;
277- this .c2me$dist3 = dist3 ;
278- this .c2me$pos1 = pos1 ;
279- this .c2me$pos2 = pos2 ;
280- this .c2me$pos3 = pos3 ;
316+ // this.c2me$dist1 = A >> 20;
317+ // this.c2me$dist2 = B >> 20;
318+ // this.c2me$dist3 = C >> 20;
319+ // this.c2me$pos1 = this.blockPositions[A & 0xffff];
320+ // this.c2me$pos2 = this.blockPositions[B & 0xffff];
321+ // this.c2me$pos3 = this.blockPositions[C & 0xffff];
322+ this .c2me$packed1 = A ;
323+ this .c2me$packed2 = B ;
324+ this .c2me$packed3 = C ;
281325 }
282326
283- /**
284- * @author ishland
285- * @reason optimize
286- */
287- @ Overwrite
288- private AquiferSampler .FluidLevel getWaterLevel (long pos ) {
289- int i = BlockPos .unpackLongX (pos );
290- int j = BlockPos .unpackLongY (pos );
291- int k = BlockPos .unpackLongZ (pos );
292- int l = i >> 4 ; // C2ME - inline: floorDiv(i, 16)
293- int m = Math .floorDiv (j , 12 ); // C2ME - inline
294- int n = k >> 4 ; // C2ME - inline: floorDiv(k, 16)
295- int o = this .index (l , m , n );
296- AquiferSampler .FluidLevel fluidLevel = this .waterLevels [o ];
297- if (fluidLevel != null ) {
298- return fluidLevel ;
299- } else {
300- AquiferSampler .FluidLevel fluidLevel2 = this .getFluidLevel (i , j , k );
301- this .waterLevels [o ] = fluidLevel2 ;
302- return fluidLevel2 ;
303- }
327+ @ Unique
328+ private AquiferSampler .FluidLevel c2me$getWaterLevelIndexed (int index ) {
329+ return this .getWaterLevel (index );
304330 }
305331
332+
306333 /**
307334 * @author ishland
308335 * @reason optimize
0 commit comments