12
12
import dev .lambdaurora .lambdynlights .accessor .WorldRendererAccessor ;
13
13
import dev .lambdaurora .lambdynlights .api .DynamicLightHandlers ;
14
14
import dev .lambdaurora .lambdynlights .api .DynamicLightsInitializer ;
15
+ import dev .lambdaurora .lambdynlights .engine .DynamicLightingEngine ;
15
16
import dev .lambdaurora .lambdynlights .resource .item .ItemLightSources ;
16
17
import dev .yumi .commons .event .EventManager ;
17
18
import it .unimi .dsi .fastutil .longs .LongOpenHashSet ;
18
19
import net .fabricmc .api .ClientModInitializer ;
20
+ import net .fabricmc .fabric .api .client .event .lifecycle .v1 .ClientTickEvents ;
19
21
import net .fabricmc .fabric .api .client .rendering .v1 .WorldRenderEvents ;
22
+ import net .fabricmc .fabric .api .event .lifecycle .v1 .CommonLifecycleEvents ;
20
23
import net .fabricmc .fabric .api .resource .ResourceManagerHelper ;
21
24
import net .fabricmc .fabric .api .resource .SimpleSynchronousResourceReloadListener ;
22
25
import net .fabricmc .loader .api .FabricLoader ;
28
31
import net .minecraft .resources .Identifier ;
29
32
import net .minecraft .resources .io .ResourceManager ;
30
33
import net .minecraft .resources .io .ResourceType ;
31
- import net .minecraft .util .math .MathHelper ;
32
34
import net .minecraft .world .entity .Entity ;
33
35
import net .minecraft .world .entity .LivingEntity ;
34
36
import net .minecraft .world .entity .item .PrimedTnt ;
35
37
import net .minecraft .world .entity .monster .Creeper ;
36
38
import net .minecraft .world .entity .player .Player ;
37
39
import net .minecraft .world .item .ItemStack ;
40
+ import net .minecraft .world .level .BlockAndTintGetter ;
38
41
import org .jetbrains .annotations .NotNull ;
39
42
import org .jetbrains .annotations .Nullable ;
40
43
import org .slf4j .Logger ;
41
44
import org .slf4j .LoggerFactory ;
42
45
46
+ import java .util .ArrayList ;
43
47
import java .util .HashSet ;
48
+ import java .util .List ;
44
49
import java .util .Set ;
45
50
import java .util .concurrent .locks .ReentrantReadWriteLock ;
46
51
import java .util .function .Predicate ;
49
54
* Represents the LambDynamicLights mod.
50
55
*
51
56
* @author LambdAurora
52
- * @version 3.0.1
57
+ * @version 3.1.0
53
58
* @since 1.0.0
54
59
*/
55
60
public class LambDynLights implements ClientModInitializer {
56
61
private static final Logger LOGGER = LoggerFactory .getLogger ("LambDynamicLights" );
57
- private static final double MAX_RADIUS = 7.75 ;
58
- private static final double MAX_RADIUS_SQUARED = MAX_RADIUS * MAX_RADIUS ;
59
62
public static final EventManager <Identifier > EVENT_MANAGER = new EventManager <>(Identifier .of (LambDynLightsConstants .NAMESPACE , "default" ), Identifier ::parse );
60
63
private static LambDynLights INSTANCE ;
61
64
public final DynamicLightsConfig config = new DynamicLightsConfig (this );
62
65
public final ItemLightSources itemLightSources = new ItemLightSources ();
66
+ private final DynamicLightingEngine engine = new DynamicLightingEngine ();
63
67
private final Set <DynamicLightSource > dynamicLightSources = new HashSet <>();
68
+ private final List <DynamicLightSource > toClear = new ArrayList <>();
64
69
private final ReentrantReadWriteLock lightSourcesLock = new ReentrantReadWriteLock ();
65
70
private long lastUpdate = System .currentTimeMillis ();
66
71
private int lastUpdateCount = 0 ;
@@ -89,6 +94,18 @@ public void reload(ResourceManager manager) {
89
94
}
90
95
});
91
96
97
+ CommonLifecycleEvents .TAGS_LOADED .register ((registries , client ) -> {
98
+ this .itemLightSources .apply (registries );
99
+ });
100
+
101
+ ClientTickEvents .END_WORLD_TICK .register (level -> {
102
+ this .lightSourcesLock .writeLock ().lock ();
103
+ this .engine .computeSpatialLookup (this .dynamicLightSources );
104
+ this .toClear .forEach (source -> source .lambdynlights$scheduleTrackedChunksRebuild (Minecraft .getInstance ().levelRenderer ));
105
+ this .toClear .clear ();
106
+ this .lightSourcesLock .writeLock ().unlock ();
107
+ });
108
+
92
109
WorldRenderEvents .START .register (context -> {
93
110
Minecraft .getInstance ().getProfiler ().swap ("dynamic_lighting" );
94
111
this .updateAll (context .worldRenderer ());
@@ -111,11 +128,9 @@ public void updateAll(@NotNull LevelRenderer renderer) {
111
128
this .lastUpdate = now ;
112
129
this .lastUpdateCount = 0 ;
113
130
114
- this .lightSourcesLock .readLock ().lock ();
115
131
for (var lightSource : this .dynamicLightSources ) {
116
132
if (lightSource .lambdynlights$updateDynamicLight (renderer )) this .lastUpdateCount ++;
117
133
}
118
- this .lightSourcesLock .readLock ().unlock ();
119
134
}
120
135
}
121
136
@@ -131,11 +146,12 @@ public int getLastUpdateCount() {
131
146
/**
132
147
* Returns the lightmap with combined light levels.
133
148
*
149
+ * @param level the level in which the light is computed
134
150
* @param pos the position
135
151
* @param lightmap the vanilla lightmap coordinates
136
152
* @return the modified lightmap coordinates
137
153
*/
138
- public int getLightmapWithDynamicLight (@ NotNull BlockPos pos , int lightmap ) {
154
+ public int getLightmapWithDynamicLight (@ NotNull BlockAndTintGetter level , @ NotNull BlockPos pos , int lightmap ) {
139
155
return this .getLightmapWithDynamicLight (this .getDynamicLightLevel (pos ), lightmap );
140
156
}
141
157
@@ -184,44 +200,10 @@ public int getLightmapWithDynamicLight(double dynamicLightLevel, int lightmap) {
184
200
* @return the dynamic light level at the specified position
185
201
*/
186
202
public double getDynamicLightLevel (@ NotNull BlockPos pos ) {
187
- double result = 0 ;
188
203
this .lightSourcesLock .readLock ().lock ();
189
- for (var lightSource : this .dynamicLightSources ) {
190
- result = maxDynamicLightLevel (pos , lightSource , result );
191
- }
204
+ double light = this .engine .getDynamicLightLevel (pos );
192
205
this .lightSourcesLock .readLock ().unlock ();
193
-
194
- return MathHelper .clamp (result , 0 , 15 );
195
- }
196
-
197
- /**
198
- * Returns the dynamic light level generated by the light source at the specified position.
199
- *
200
- * @param pos the position
201
- * @param lightSource the light source
202
- * @param currentLightLevel the current surrounding dynamic light level
203
- * @return the dynamic light level at the specified position
204
- */
205
- public static double maxDynamicLightLevel (@ NotNull BlockPos pos , @ NotNull DynamicLightSource lightSource , double currentLightLevel ) {
206
- int luminance = lightSource .getLuminance ();
207
- if (luminance > 0 ) {
208
- // Can't use Entity#squaredDistanceTo because of eye Y coordinate.
209
- double dx = pos .getX () - lightSource .getDynamicLightX () + 0.5 ;
210
- double dy = pos .getY () - lightSource .getDynamicLightY () + 0.5 ;
211
- double dz = pos .getZ () - lightSource .getDynamicLightZ () + 0.5 ;
212
-
213
- double distanceSquared = dx * dx + dy * dy + dz * dz ;
214
- // 7.75 because else we would have to update more chunks and that's not a good idea.
215
- // 15 (max range for blocks) would be too much and a bit cheaty.
216
- if (distanceSquared <= MAX_RADIUS_SQUARED ) {
217
- double multiplier = 1.0 - Math .sqrt (distanceSquared ) / MAX_RADIUS ;
218
- double lightLevel = multiplier * (double ) luminance ;
219
- if (lightLevel > currentLightLevel ) {
220
- return lightLevel ;
221
- }
222
- }
223
- }
224
- return currentLightLevel ;
206
+ return light ;
225
207
}
226
208
227
209
/**
@@ -236,9 +218,7 @@ public void addLightSource(@NotNull DynamicLightSource lightSource) {
236
218
return ;
237
219
if (this .containsLightSource (lightSource ))
238
220
return ;
239
- this .lightSourcesLock .writeLock ().lock ();
240
221
this .dynamicLightSources .add (lightSource );
241
- this .lightSourcesLock .writeLock ().unlock ();
242
222
}
243
223
244
224
/**
@@ -251,11 +231,7 @@ public boolean containsLightSource(@NotNull DynamicLightSource lightSource) {
251
231
if (!lightSource .getDynamicLightLevel ().isClientSide ())
252
232
return false ;
253
233
254
- boolean result ;
255
- this .lightSourcesLock .readLock ().lock ();
256
- result = this .dynamicLightSources .contains (lightSource );
257
- this .lightSourcesLock .readLock ().unlock ();
258
- return result ;
234
+ return this .dynamicLightSources .contains (lightSource );
259
235
}
260
236
261
237
/**
@@ -264,13 +240,7 @@ public boolean containsLightSource(@NotNull DynamicLightSource lightSource) {
264
240
* @return the number of dynamic light sources emitting light
265
241
*/
266
242
public int getLightSourcesCount () {
267
- int result ;
268
-
269
- this .lightSourcesLock .readLock ().lock ();
270
- result = this .dynamicLightSources .size ();
271
- this .lightSourcesLock .readLock ().unlock ();
272
-
273
- return result ;
243
+ return this .dynamicLightSources .size ();
274
244
}
275
245
276
246
/**
@@ -279,39 +249,31 @@ public int getLightSourcesCount() {
279
249
* @param lightSource the light source to remove
280
250
*/
281
251
public void removeLightSource (@ NotNull DynamicLightSource lightSource ) {
282
- this .lightSourcesLock .writeLock ().lock ();
283
-
284
252
var dynamicLightSources = this .dynamicLightSources .iterator ();
285
253
DynamicLightSource it ;
286
254
while (dynamicLightSources .hasNext ()) {
287
255
it = dynamicLightSources .next ();
288
256
if (it .equals (lightSource )) {
289
257
dynamicLightSources .remove ();
290
- lightSource . lambdynlights$scheduleTrackedChunksRebuild ( Minecraft . getInstance (). levelRenderer );
258
+ this . toClear . add ( lightSource );
291
259
break ;
292
260
}
293
261
}
294
-
295
- this .lightSourcesLock .writeLock ().unlock ();
296
262
}
297
263
298
264
/**
299
265
* Clears light sources.
300
266
*/
301
267
public void clearLightSources () {
302
- this .lightSourcesLock .writeLock ().lock ();
303
-
304
268
var dynamicLightSources = this .dynamicLightSources .iterator ();
305
269
DynamicLightSource it ;
306
270
while (dynamicLightSources .hasNext ()) {
307
271
it = dynamicLightSources .next ();
308
272
dynamicLightSources .remove ();
309
273
if (it .getLuminance () > 0 )
310
274
it .resetDynamicLight ();
311
- it . lambdynlights$scheduleTrackedChunksRebuild ( Minecraft . getInstance (). levelRenderer );
275
+ this . toClear . add ( it );
312
276
}
313
-
314
- this .lightSourcesLock .writeLock ().unlock ();
315
277
}
316
278
317
279
/**
@@ -320,8 +282,6 @@ public void clearLightSources() {
320
282
* @param filter the removal filter
321
283
*/
322
284
public void removeLightSources (@ NotNull Predicate <DynamicLightSource > filter ) {
323
- this .lightSourcesLock .writeLock ().lock ();
324
-
325
285
var dynamicLightSources = this .dynamicLightSources .iterator ();
326
286
DynamicLightSource it ;
327
287
while (dynamicLightSources .hasNext ()) {
@@ -330,12 +290,10 @@ public void removeLightSources(@NotNull Predicate<DynamicLightSource> filter) {
330
290
dynamicLightSources .remove ();
331
291
if (it .getLuminance () > 0 )
332
292
it .resetDynamicLight ();
333
- it . lambdynlights$scheduleTrackedChunksRebuild ( Minecraft . getInstance (). levelRenderer );
293
+ this . toClear . add ( it );
334
294
break ;
335
295
}
336
296
}
337
-
338
- this .lightSourcesLock .writeLock ().unlock ();
339
297
}
340
298
341
299
/**
0 commit comments