Terraria v1.4.4.9
Terraria source code documentation
All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events Macros
LiquidRenderer.cs
Go to the documentation of this file.
1using System;
6using Terraria.ID;
8
10
11public class LiquidRenderer
12{
13 private struct LiquidCache
14 {
15 public float LiquidLevel;
16
17 public float VisibleLiquidLevel;
18
19 public float Opacity;
20
21 public bool IsSolid;
22
23 public bool IsHalfBrick;
24
25 public bool HasLiquid;
26
27 public bool HasVisibleLiquid;
28
29 public bool HasWall;
30
32
33 public bool HasLeftEdge;
34
35 public bool HasRightEdge;
36
37 public bool HasTopEdge;
38
39 public bool HasBottomEdge;
40
41 public float LeftWall;
42
43 public float RightWall;
44
45 public float BottomWall;
46
47 public float TopWall;
48
49 public float VisibleLeftWall;
50
51 public float VisibleRightWall;
52
53 public float VisibleBottomWall;
54
55 public float VisibleTopWall;
56
57 public byte Type;
58
59 public byte VisibleType;
60 }
61
62 private struct LiquidDrawCache
63 {
65
67
68 public bool IsVisible;
69
70 public float Opacity;
71
72 public byte Type;
73
74 public bool IsSurfaceLiquid;
75
76 public bool HasWall;
77 }
78
80 {
81 public int X;
82
83 public int Y;
84
86
88
89 public bool IsVisible;
90
91 public float Opacity;
92
93 public byte Type;
94
95 public bool IsSurfaceLiquid;
96
97 public bool HasWall;
98 }
99
100 private const int ANIMATION_FRAME_COUNT = 16;
101
102 private const int CACHE_PADDING = 2;
103
104 private const int CACHE_PADDING_2 = 4;
105
106 private static readonly int[] WATERFALL_LENGTH = new int[4] { 10, 3, 2, 10 };
107
108 private static readonly float[] DEFAULT_OPACITY = new float[4] { 0.6f, 0.95f, 0.95f, 0.75f };
109
110 private static readonly byte[] WAVE_MASK_STRENGTH = new byte[5];
111
112 private static readonly byte[] VISCOSITY_MASK = new byte[5] { 0, 200, 240, 0, 0 };
113
114 public const float MIN_LIQUID_SIZE = 0.25f;
115
117
119
120 private LiquidCache[] _cache = new LiquidCache[1];
121
123
125
126 private int _animationFrame;
127
128 private Rectangle _drawArea = new Rectangle(0, 0, 1, 1);
129
130 private readonly UnifiedRandom _random = new UnifiedRandom();
131
132 private Color[] _waveMask = new Color[1];
133
134 private float _frameState;
135
136 private static Tile[,] Tiles => Main.tile;
137
138 public event Action<Color[], Rectangle> WaveFilters;
139
140 public static void LoadContent()
141 {
142 Instance = new LiquidRenderer();
143 Instance.PrepareAssets();
144 }
145
146 private void PrepareAssets()
147 {
148 if (!Main.dedServ)
149 {
150 for (int i = 0; i < _liquidTextures.Length; i++)
151 {
152 _liquidTextures[i] = Main.Assets.Request<Texture2D>("Images/Misc/water_" + i, (AssetRequestMode)1);
153 }
154 }
155 }
156
157 private unsafe void InternalPrepareDraw(Rectangle drawArea)
158 {
159 Rectangle rectangle = new Rectangle(drawArea.X - 2, drawArea.Y - 2, drawArea.Width + 4, drawArea.Height + 4);
160 _drawArea = drawArea;
161 if (_cache.Length < rectangle.Width * rectangle.Height + 1)
162 {
163 _cache = new LiquidCache[rectangle.Width * rectangle.Height + 1];
164 }
165 if (_drawCache.Length < drawArea.Width * drawArea.Height + 1)
166 {
167 _drawCache = new LiquidDrawCache[drawArea.Width * drawArea.Height + 1];
168 }
169 if (_drawCacheForShimmer.Length < drawArea.Width * drawArea.Height + 1)
170 {
171 _drawCacheForShimmer = new SpecialLiquidDrawCache[drawArea.Width * drawArea.Height + 1];
172 }
173 if (_waveMask.Length < drawArea.Width * drawArea.Height)
174 {
175 _waveMask = new Color[drawArea.Width * drawArea.Height];
176 }
177 Tile tile = null;
178 fixed (LiquidCache* ptr = &_cache[1])
179 {
180 LiquidCache* ptr2 = ptr;
181 int num = rectangle.Height * 2 + 2;
182 ptr2 = ptr;
183 for (int i = rectangle.X; i < rectangle.X + rectangle.Width; i++)
184 {
185 for (int j = rectangle.Y; j < rectangle.Y + rectangle.Height; j++)
186 {
187 tile = Tiles[i, j];
188 if (tile == null)
189 {
190 tile = new Tile();
191 }
192 ptr2->LiquidLevel = (float)(int)tile.liquid / 255f;
193 ptr2->IsHalfBrick = tile.halfBrick() && ptr2[-1].HasLiquid && !TileID.Sets.Platforms[tile.type];
194 ptr2->IsSolid = WorldGen.SolidOrSlopedTile(tile);
195 ptr2->HasLiquid = tile.liquid != 0;
196 ptr2->VisibleLiquidLevel = 0f;
197 ptr2->HasWall = tile.wall != 0;
198 ptr2->Type = tile.liquidType();
199 if (ptr2->IsHalfBrick && !ptr2->HasLiquid)
200 {
201 ptr2->Type = ptr2[-1].Type;
202 }
203 ptr2++;
204 }
205 }
206 ptr2 = ptr;
207 float num2 = 0f;
208 ptr2 += num;
209 for (int k = 2; k < rectangle.Width - 2; k++)
210 {
211 for (int l = 2; l < rectangle.Height - 2; l++)
212 {
213 num2 = 0f;
214 if (ptr2->IsHalfBrick && ptr2[-1].HasLiquid)
215 {
216 num2 = 1f;
217 }
218 else if (!ptr2->HasLiquid)
219 {
220 LiquidCache liquidCache = ptr2[-1];
221 LiquidCache liquidCache2 = ptr2[1];
222 LiquidCache liquidCache3 = ptr2[-rectangle.Height];
223 LiquidCache liquidCache4 = ptr2[rectangle.Height];
224 if (liquidCache.HasLiquid && liquidCache2.HasLiquid && liquidCache.Type == liquidCache2.Type && !liquidCache.IsSolid && !liquidCache2.IsSolid)
225 {
226 num2 = liquidCache.LiquidLevel + liquidCache2.LiquidLevel;
227 ptr2->Type = liquidCache.Type;
228 }
229 if (liquidCache3.HasLiquid && liquidCache4.HasLiquid && liquidCache3.Type == liquidCache4.Type && !liquidCache3.IsSolid && !liquidCache4.IsSolid)
230 {
231 num2 = Math.Max(num2, liquidCache3.LiquidLevel + liquidCache4.LiquidLevel);
232 ptr2->Type = liquidCache3.Type;
233 }
234 num2 *= 0.5f;
235 }
236 else
237 {
238 num2 = ptr2->LiquidLevel;
239 }
240 ptr2->VisibleLiquidLevel = num2;
241 ptr2->HasVisibleLiquid = num2 != 0f;
242 ptr2++;
243 }
244 ptr2 += 4;
245 }
246 ptr2 = ptr;
247 for (int m = 0; m < rectangle.Width; m++)
248 {
249 for (int n = 0; n < rectangle.Height - 10; n++)
250 {
251 if (ptr2->HasVisibleLiquid && (!ptr2->IsSolid || ptr2->IsHalfBrick))
252 {
253 ptr2->Opacity = 1f;
254 ptr2->VisibleType = ptr2->Type;
255 float num3 = 1f / (float)(WATERFALL_LENGTH[ptr2->Type] + 1);
256 float num4 = 1f;
257 for (int num5 = 1; num5 <= WATERFALL_LENGTH[ptr2->Type]; num5++)
258 {
259 num4 -= num3;
260 if (ptr2[num5].IsSolid)
261 {
262 break;
263 }
264 ptr2[num5].VisibleLiquidLevel = Math.Max(ptr2[num5].VisibleLiquidLevel, ptr2->VisibleLiquidLevel * num4);
265 ptr2[num5].Opacity = num4;
266 ptr2[num5].VisibleType = ptr2->Type;
267 }
268 }
269 if (ptr2->IsSolid && !ptr2->IsHalfBrick)
270 {
271 ptr2->VisibleLiquidLevel = 1f;
272 ptr2->HasVisibleLiquid = false;
273 }
274 else
275 {
276 ptr2->HasVisibleLiquid = ptr2->VisibleLiquidLevel != 0f;
277 }
278 ptr2++;
279 }
280 ptr2 += 10;
281 }
282 ptr2 = ptr;
283 ptr2 += num;
284 for (int num6 = 2; num6 < rectangle.Width - 2; num6++)
285 {
286 for (int num7 = 2; num7 < rectangle.Height - 2; num7++)
287 {
288 if (!ptr2->HasVisibleLiquid)
289 {
290 ptr2->HasLeftEdge = false;
291 ptr2->HasTopEdge = false;
292 ptr2->HasRightEdge = false;
293 ptr2->HasBottomEdge = false;
294 }
295 else
296 {
297 LiquidCache liquidCache = ptr2[-1];
298 LiquidCache liquidCache2 = ptr2[1];
299 LiquidCache liquidCache3 = ptr2[-rectangle.Height];
300 LiquidCache liquidCache4 = ptr2[rectangle.Height];
301 float num8 = 0f;
302 float num9 = 1f;
303 float num10 = 0f;
304 float num11 = 1f;
305 float visibleLiquidLevel = ptr2->VisibleLiquidLevel;
306 if (!liquidCache.HasVisibleLiquid)
307 {
308 num10 += liquidCache2.VisibleLiquidLevel * (1f - visibleLiquidLevel);
309 }
310 if (!liquidCache2.HasVisibleLiquid && !liquidCache2.IsSolid && !liquidCache2.IsHalfBrick)
311 {
312 num11 -= liquidCache.VisibleLiquidLevel * (1f - visibleLiquidLevel);
313 }
314 if (!liquidCache3.HasVisibleLiquid && !liquidCache3.IsSolid && !liquidCache3.IsHalfBrick)
315 {
316 num8 += liquidCache4.VisibleLiquidLevel * (1f - visibleLiquidLevel);
317 }
318 if (!liquidCache4.HasVisibleLiquid && !liquidCache4.IsSolid && !liquidCache4.IsHalfBrick)
319 {
320 num9 -= liquidCache3.VisibleLiquidLevel * (1f - visibleLiquidLevel);
321 }
322 ptr2->LeftWall = num8;
323 ptr2->RightWall = num9;
324 ptr2->BottomWall = num11;
325 ptr2->TopWall = num10;
326 Point zero = Point.Zero;
327 ptr2->HasTopEdge = (!liquidCache.HasVisibleLiquid && !liquidCache.IsSolid) || num10 != 0f;
328 ptr2->HasBottomEdge = (!liquidCache2.HasVisibleLiquid && !liquidCache2.IsSolid) || num11 != 1f;
329 ptr2->HasLeftEdge = (!liquidCache3.HasVisibleLiquid && !liquidCache3.IsSolid) || num8 != 0f;
330 ptr2->HasRightEdge = (!liquidCache4.HasVisibleLiquid && !liquidCache4.IsSolid) || num9 != 1f;
331 if (!ptr2->HasLeftEdge)
332 {
333 if (ptr2->HasRightEdge)
334 {
335 zero.X += 32;
336 }
337 else
338 {
339 zero.X += 16;
340 }
341 }
342 if (ptr2->HasLeftEdge && ptr2->HasRightEdge)
343 {
344 zero.X = 16;
345 zero.Y += 32;
346 if (ptr2->HasTopEdge)
347 {
348 zero.Y = 16;
349 }
350 }
351 else if (!ptr2->HasTopEdge)
352 {
353 if (!ptr2->HasLeftEdge && !ptr2->HasRightEdge)
354 {
355 zero.Y += 48;
356 }
357 else
358 {
359 zero.Y += 16;
360 }
361 }
362 if (zero.Y == 16 && (ptr2->HasLeftEdge ^ ptr2->HasRightEdge) && (num7 + rectangle.Y) % 2 == 0)
363 {
364 zero.Y += 16;
365 }
366 ptr2->FrameOffset = zero;
367 }
368 ptr2++;
369 }
370 ptr2 += 4;
371 }
372 ptr2 = ptr;
373 ptr2 += num;
374 for (int num12 = 2; num12 < rectangle.Width - 2; num12++)
375 {
376 for (int num13 = 2; num13 < rectangle.Height - 2; num13++)
377 {
378 if (ptr2->HasVisibleLiquid)
379 {
380 LiquidCache liquidCache = ptr2[-1];
381 LiquidCache liquidCache2 = ptr2[1];
382 LiquidCache liquidCache3 = ptr2[-rectangle.Height];
383 LiquidCache liquidCache4 = ptr2[rectangle.Height];
384 ptr2->VisibleLeftWall = ptr2->LeftWall;
385 ptr2->VisibleRightWall = ptr2->RightWall;
386 ptr2->VisibleTopWall = ptr2->TopWall;
387 ptr2->VisibleBottomWall = ptr2->BottomWall;
388 if (liquidCache.HasVisibleLiquid && liquidCache2.HasVisibleLiquid)
389 {
390 if (ptr2->HasLeftEdge)
391 {
392 ptr2->VisibleLeftWall = (ptr2->LeftWall * 2f + liquidCache.LeftWall + liquidCache2.LeftWall) * 0.25f;
393 }
394 if (ptr2->HasRightEdge)
395 {
396 ptr2->VisibleRightWall = (ptr2->RightWall * 2f + liquidCache.RightWall + liquidCache2.RightWall) * 0.25f;
397 }
398 }
399 if (liquidCache3.HasVisibleLiquid && liquidCache4.HasVisibleLiquid)
400 {
401 if (ptr2->HasTopEdge)
402 {
403 ptr2->VisibleTopWall = (ptr2->TopWall * 2f + liquidCache3.TopWall + liquidCache4.TopWall) * 0.25f;
404 }
405 if (ptr2->HasBottomEdge)
406 {
407 ptr2->VisibleBottomWall = (ptr2->BottomWall * 2f + liquidCache3.BottomWall + liquidCache4.BottomWall) * 0.25f;
408 }
409 }
410 }
411 ptr2++;
412 }
413 ptr2 += 4;
414 }
415 ptr2 = ptr;
416 ptr2 += num;
417 for (int num14 = 2; num14 < rectangle.Width - 2; num14++)
418 {
419 for (int num15 = 2; num15 < rectangle.Height - 2; num15++)
420 {
421 if (ptr2->HasLiquid)
422 {
423 LiquidCache liquidCache = ptr2[-1];
424 LiquidCache liquidCache2 = ptr2[1];
425 LiquidCache liquidCache3 = ptr2[-rectangle.Height];
426 LiquidCache liquidCache4 = ptr2[rectangle.Height];
427 if (ptr2->HasTopEdge && !ptr2->HasBottomEdge && (ptr2->HasLeftEdge ^ ptr2->HasRightEdge))
428 {
429 if (ptr2->HasRightEdge)
430 {
431 ptr2->VisibleRightWall = liquidCache2.VisibleRightWall;
432 ptr2->VisibleTopWall = liquidCache3.VisibleTopWall;
433 }
434 else
435 {
436 ptr2->VisibleLeftWall = liquidCache2.VisibleLeftWall;
437 ptr2->VisibleTopWall = liquidCache4.VisibleTopWall;
438 }
439 }
440 else if (liquidCache2.FrameOffset.X == 16 && liquidCache2.FrameOffset.Y == 32)
441 {
442 if (ptr2->VisibleLeftWall > 0.5f)
443 {
444 ptr2->VisibleLeftWall = 0f;
445 ptr2->FrameOffset = new Point(0, 0);
446 }
447 else if (ptr2->VisibleRightWall < 0.5f)
448 {
449 ptr2->VisibleRightWall = 1f;
450 ptr2->FrameOffset = new Point(32, 0);
451 }
452 }
453 }
454 ptr2++;
455 }
456 ptr2 += 4;
457 }
458 ptr2 = ptr;
459 ptr2 += num;
460 for (int num16 = 2; num16 < rectangle.Width - 2; num16++)
461 {
462 for (int num17 = 2; num17 < rectangle.Height - 2; num17++)
463 {
464 if (ptr2->HasLiquid)
465 {
466 LiquidCache liquidCache = ptr2[-1];
467 LiquidCache liquidCache2 = ptr2[1];
468 LiquidCache liquidCache3 = ptr2[-rectangle.Height];
469 LiquidCache liquidCache4 = ptr2[rectangle.Height];
470 if (!ptr2->HasBottomEdge && !ptr2->HasLeftEdge && !ptr2->HasTopEdge && !ptr2->HasRightEdge)
471 {
472 if (liquidCache3.HasTopEdge && liquidCache.HasLeftEdge)
473 {
474 ptr2->FrameOffset.X = Math.Max(4, (int)(16f - liquidCache.VisibleLeftWall * 16f)) - 4;
475 ptr2->FrameOffset.Y = 48 + Math.Max(4, (int)(16f - liquidCache3.VisibleTopWall * 16f)) - 4;
476 ptr2->VisibleLeftWall = 0f;
477 ptr2->VisibleTopWall = 0f;
478 ptr2->VisibleRightWall = 1f;
479 ptr2->VisibleBottomWall = 1f;
480 }
481 else if (liquidCache4.HasTopEdge && liquidCache.HasRightEdge)
482 {
483 ptr2->FrameOffset.X = 32 - Math.Min(16, (int)(liquidCache.VisibleRightWall * 16f) - 4);
484 ptr2->FrameOffset.Y = 48 + Math.Max(4, (int)(16f - liquidCache4.VisibleTopWall * 16f)) - 4;
485 ptr2->VisibleLeftWall = 0f;
486 ptr2->VisibleTopWall = 0f;
487 ptr2->VisibleRightWall = 1f;
488 ptr2->VisibleBottomWall = 1f;
489 }
490 }
491 }
492 ptr2++;
493 }
494 ptr2 += 4;
495 }
496 ptr2 = ptr;
497 ptr2 += num;
498 fixed (LiquidDrawCache* ptr3 = &_drawCache[0])
499 {
500 fixed (Color* ptr5 = &_waveMask[0])
501 {
502 LiquidDrawCache* ptr4 = ptr3;
503 Color* ptr6 = ptr5;
504 for (int num18 = 2; num18 < rectangle.Width - 2; num18++)
505 {
506 for (int num19 = 2; num19 < rectangle.Height - 2; num19++)
507 {
508 if (ptr2->HasVisibleLiquid)
509 {
510 float num20 = Math.Min(0.75f, ptr2->VisibleLeftWall);
511 float num21 = Math.Max(0.25f, ptr2->VisibleRightWall);
512 float num22 = Math.Min(0.75f, ptr2->VisibleTopWall);
513 float num23 = Math.Max(0.25f, ptr2->VisibleBottomWall);
514 if (ptr2->IsHalfBrick && ptr2->IsSolid && num23 > 0.5f)
515 {
516 num23 = 0.5f;
517 }
518 ptr4->IsVisible = ptr2->HasWall || !ptr2->IsHalfBrick || !ptr2->HasLiquid || !(ptr2->LiquidLevel < 1f);
519 ptr4->SourceRectangle = new Rectangle((int)(16f - num21 * 16f) + ptr2->FrameOffset.X, (int)(16f - num23 * 16f) + ptr2->FrameOffset.Y, (int)Math.Ceiling((num21 - num20) * 16f), (int)Math.Ceiling((num23 - num22) * 16f));
520 ptr4->IsSurfaceLiquid = ptr2->FrameOffset.X == 16 && ptr2->FrameOffset.Y == 0 && (double)(num19 + rectangle.Y) > Main.worldSurface - 40.0;
521 ptr4->Opacity = ptr2->Opacity;
522 ptr4->LiquidOffset = new Vector2((float)Math.Floor(num20 * 16f), (float)Math.Floor(num22 * 16f));
523 ptr4->Type = ptr2->VisibleType;
524 ptr4->HasWall = ptr2->HasWall;
525 byte b = WAVE_MASK_STRENGTH[ptr2->VisibleType];
526 byte g = (ptr6->R = (byte)(b >> 1));
527 ptr6->G = g;
528 ptr6->B = VISCOSITY_MASK[ptr2->VisibleType];
529 ptr6->A = b;
530 LiquidCache* ptr7 = ptr2 - 1;
531 if (num19 != 2 && !ptr7->HasVisibleLiquid && !ptr7->IsSolid && !ptr7->IsHalfBrick)
532 {
533 *(ptr6 - 1) = *ptr6;
534 }
535 }
536 else
537 {
538 ptr4->IsVisible = false;
539 int num24 = ((!ptr2->IsSolid && !ptr2->IsHalfBrick) ? 4 : 3);
540 byte b3 = WAVE_MASK_STRENGTH[num24];
541 byte g2 = (ptr6->R = (byte)(b3 >> 1));
542 ptr6->G = g2;
543 ptr6->B = VISCOSITY_MASK[num24];
544 ptr6->A = b3;
545 }
546 ptr2++;
547 ptr4++;
548 ptr6++;
549 }
550 ptr2 += 4;
551 }
552 }
553 }
554 ptr2 = ptr;
555 for (int num25 = rectangle.X; num25 < rectangle.X + rectangle.Width; num25++)
556 {
557 for (int num26 = rectangle.Y; num26 < rectangle.Y + rectangle.Height; num26++)
558 {
559 if (ptr2->VisibleType == 1 && ptr2->HasVisibleLiquid && Dust.lavaBubbles < 200)
560 {
561 if (_random.Next(700) == 0)
562 {
563 Dust.NewDust(new Vector2(num25 * 16, num26 * 16), 16, 16, 35, 0f, 0f, 0, Color.White);
564 }
565 if (_random.Next(350) == 0)
566 {
567 int num27 = Dust.NewDust(new Vector2(num25 * 16, num26 * 16), 16, 8, 35, 0f, 0f, 50, Color.White, 1.5f);
568 Main.dust[num27].velocity *= 0.8f;
569 Main.dust[num27].velocity.X *= 2f;
570 Main.dust[num27].velocity.Y -= (float)_random.Next(1, 7) * 0.1f;
571 if (_random.Next(10) == 0)
572 {
573 Main.dust[num27].velocity.Y *= _random.Next(2, 5);
574 }
575 Main.dust[num27].noGravity = true;
576 }
577 }
578 ptr2++;
579 }
580 }
581 fixed (LiquidDrawCache* ptr8 = &_drawCache[0])
582 {
584 {
585 LiquidDrawCache* ptr9 = ptr8;
586 SpecialLiquidDrawCache* ptr11 = ptr10;
587 for (int num28 = 2; num28 < rectangle.Width - 2; num28++)
588 {
589 for (int num29 = 2; num29 < rectangle.Height - 2; num29++)
590 {
591 if (ptr9->IsVisible && ptr9->Type == 3)
592 {
593 ptr11->X = num28;
594 ptr11->Y = num29;
595 ptr11->IsVisible = ptr9->IsVisible;
596 ptr11->HasWall = ptr9->HasWall;
597 ptr11->IsSurfaceLiquid = ptr9->IsSurfaceLiquid;
598 ptr11->LiquidOffset = ptr9->LiquidOffset;
599 ptr11->Opacity = ptr9->Opacity;
600 ptr11->SourceRectangle = ptr9->SourceRectangle;
601 ptr11->Type = ptr9->Type;
602 ptr9->IsVisible = false;
603 ptr11++;
604 }
605 ptr9++;
606 }
607 }
608 ptr11->IsVisible = false;
609 }
610 }
611 }
612 if (this.WaveFilters != null)
613 {
614 this.WaveFilters(_waveMask, GetCachedDrawArea());
615 }
616 }
617
618 public unsafe void DrawNormalLiquids(SpriteBatch spriteBatch, Vector2 drawOffset, int waterStyle, float globalAlpha, bool isBackgroundDraw)
619 {
620 Rectangle drawArea = _drawArea;
621 Main.tileBatch.Begin();
622 fixed (LiquidDrawCache* ptr = &_drawCache[0])
623 {
624 LiquidDrawCache* ptr2 = ptr;
625 for (int i = drawArea.X; i < drawArea.X + drawArea.Width; i++)
626 {
627 for (int j = drawArea.Y; j < drawArea.Y + drawArea.Height; j++)
628 {
629 if (ptr2->IsVisible)
630 {
631 Rectangle sourceRectangle = ptr2->SourceRectangle;
632 if (ptr2->IsSurfaceLiquid)
633 {
634 sourceRectangle.Y = 1280;
635 }
636 else
637 {
638 sourceRectangle.Y += _animationFrame * 80;
639 }
640 Vector2 liquidOffset = ptr2->LiquidOffset;
641 float num = ptr2->Opacity * (isBackgroundDraw ? 1f : DEFAULT_OPACITY[ptr2->Type]);
642 int num2 = ptr2->Type;
643 switch (num2)
644 {
645 case 0:
646 num2 = waterStyle;
647 num *= globalAlpha;
648 break;
649 case 2:
650 num2 = 11;
651 break;
652 }
653 num = Math.Min(1f, num);
654 Lighting.GetCornerColors(i, j, out var vertices);
655 vertices.BottomLeftColor *= num;
656 vertices.BottomRightColor *= num;
657 vertices.TopLeftColor *= num;
658 vertices.TopRightColor *= num;
659 Main.DrawTileInWater(drawOffset, i, j);
660 Main.tileBatch.Draw(_liquidTextures[num2].Value, new Vector2(i << 4, j << 4) + drawOffset + liquidOffset, sourceRectangle, vertices, Vector2.Zero, 1f, SpriteEffects.None);
661 }
662 ptr2++;
663 }
664 }
665 }
666 Main.tileBatch.End();
667 }
668
669 public unsafe void DrawShimmer(SpriteBatch spriteBatch, Vector2 drawOffset, bool isBackgroundDraw)
670 {
671 Rectangle drawArea = _drawArea;
672 Main.tileBatch.Begin();
674 {
675 SpecialLiquidDrawCache* ptr2 = ptr;
676 int num = _drawCacheForShimmer.Length;
677 for (int i = 0; i < num; i++)
678 {
679 if (!ptr2->IsVisible)
680 {
681 break;
682 }
683 Rectangle sourceRectangle = ptr2->SourceRectangle;
684 if (ptr2->IsSurfaceLiquid)
685 {
686 sourceRectangle.Y = 1280;
687 }
688 else
689 {
690 sourceRectangle.Y += _animationFrame * 80;
691 }
692 Vector2 liquidOffset = ptr2->LiquidOffset;
693 float val = ptr2->Opacity * (isBackgroundDraw ? 1f : 0.75f);
694 int num2 = 14;
695 val = Math.Min(1f, val);
696 int num3 = ptr2->X + drawArea.X - 2;
697 int num4 = ptr2->Y + drawArea.Y - 2;
698 Lighting.GetCornerColors(num3, num4, out var vertices);
699 SetShimmerVertexColors(ref vertices, val, num3, num4);
700 Main.DrawTileInWater(drawOffset, num3, num4);
701 Main.tileBatch.Draw(_liquidTextures[num2].Value, new Vector2(num3 << 4, num4 << 4) + drawOffset + liquidOffset, sourceRectangle, vertices, Vector2.Zero, 1f, SpriteEffects.None);
702 sourceRectangle = ptr2->SourceRectangle;
703 bool flag = sourceRectangle.X != 16 || sourceRectangle.Y % 80 != 48;
704 if (flag || (num3 + num4) % 2 == 0)
705 {
706 sourceRectangle.X += 48;
707 sourceRectangle.Y += 80 * GetShimmerFrame(flag, num3, num4);
708 SetShimmerVertexColors_Sparkle(ref vertices, ptr2->Opacity, num3, num4, flag);
709 Main.tileBatch.Draw(_liquidTextures[num2].Value, new Vector2(num3 << 4, num4 << 4) + drawOffset + liquidOffset, sourceRectangle, vertices, Vector2.Zero, 1f, SpriteEffects.None);
710 }
711 ptr2++;
712 }
713 }
714 Main.tileBatch.End();
715 }
716
717 public static VertexColors SetShimmerVertexColors_Sparkle(ref VertexColors colors, float opacity, int x, int y, bool top)
718 {
719 colors.BottomLeftColor = GetShimmerGlitterColor(top, x, y + 1);
720 colors.BottomRightColor = GetShimmerGlitterColor(top, x + 1, y + 1);
721 colors.TopLeftColor = GetShimmerGlitterColor(top, x, y);
722 colors.TopRightColor = GetShimmerGlitterColor(top, x + 1, y);
723 colors.BottomLeftColor *= opacity;
724 colors.BottomRightColor *= opacity;
725 colors.TopLeftColor *= opacity;
726 colors.TopRightColor *= opacity;
727 return colors;
728 }
729
730 public static void SetShimmerVertexColors(ref VertexColors colors, float opacity, int x, int y)
731 {
732 colors.BottomLeftColor = Color.White;
733 colors.BottomRightColor = Color.White;
734 colors.TopLeftColor = Color.White;
735 colors.TopRightColor = Color.White;
736 colors.BottomLeftColor *= opacity;
737 colors.BottomRightColor *= opacity;
738 colors.TopLeftColor *= opacity;
739 colors.TopRightColor *= opacity;
740 colors.BottomLeftColor = new Color(colors.BottomLeftColor.ToVector4() * GetShimmerBaseColor(x, y + 1));
741 colors.BottomRightColor = new Color(colors.BottomRightColor.ToVector4() * GetShimmerBaseColor(x + 1, y + 1));
742 colors.TopLeftColor = new Color(colors.TopLeftColor.ToVector4() * GetShimmerBaseColor(x, y));
743 colors.TopRightColor = new Color(colors.TopRightColor.ToVector4() * GetShimmerBaseColor(x + 1, y));
744 }
745
746 public static float GetShimmerWave(ref float worldPositionX, ref float worldPositionY)
747 {
748 return (float)Math.Sin(((double)((worldPositionX + worldPositionY / 6f) / 10f) - Main.timeForVisualEffects / 360.0) * 6.2831854820251465);
749 }
750
751 public static Color GetShimmerGlitterColor(bool top, float worldPositionX, float worldPositionY)
752 {
753 Color color = Main.hslToRgb((float)(((double)(worldPositionX + worldPositionY / 6f) + Main.timeForVisualEffects / 30.0) / 6.0) % 1f, 1f, 0.5f);
754 color.A = 0;
755 return new Color(color.ToVector4() * GetShimmerGlitterOpacity(top, worldPositionX, worldPositionY));
756 }
757
758 public static float GetShimmerGlitterOpacity(bool top, float worldPositionX, float worldPositionY)
759 {
760 if (top)
761 {
762 return 0.5f;
763 }
764 float num = Utils.Remap((float)Math.Sin(((double)((worldPositionX + worldPositionY / 6f) / 10f) - Main.timeForVisualEffects / 360.0) * 6.2831854820251465), -0.5f, 1f, 0f, 0.35f);
765 float num2 = (float)Math.Sin((double)((float)SimpleWhiteNoise((uint)worldPositionX, (uint)worldPositionY) / 10f) + Main.timeForVisualEffects / 180.0);
766 return Utils.Remap(num * num2, 0f, 0.5f, 0f, 1f);
767 }
768
769 private static uint SimpleWhiteNoise(uint x, uint y)
770 {
771 x = 36469 * (x & 0xFFFF) + (x >> 16);
772 y = 18012 * (y & 0xFFFF) + (y >> 16);
773 return (x << 16) + y;
774 }
775
776 public int GetShimmerFrame(bool top, float worldPositionX, float worldPositionY)
777 {
778 worldPositionX += 0.5f;
779 worldPositionY += 0.5f;
780 double num = (double)((worldPositionX + worldPositionY / 6f) / 10f) - Main.timeForVisualEffects / 360.0;
781 if (!top)
782 {
783 num += (double)(worldPositionX + worldPositionY);
784 }
785 return ((int)num % 16 + 16) % 16;
786 }
787
788 public static Vector4 GetShimmerBaseColor(float worldPositionX, float worldPositionY)
789 {
790 float shimmerWave = GetShimmerWave(ref worldPositionX, ref worldPositionY);
791 return Vector4.Lerp(new Vector4(0.64705884f, 26f / 51f, 14f / 15f, 1f), new Vector4(41f / 51f, 41f / 51f, 1f, 1f), 0.1f + shimmerWave * 0.4f);
792 }
793
794 public bool HasFullWater(int x, int y)
795 {
796 x -= _drawArea.X;
797 y -= _drawArea.Y;
798 int num = x * _drawArea.Height + y;
799 if (num >= 0 && num < _drawCache.Length)
800 {
801 if (_drawCache[num].IsVisible)
802 {
803 return !_drawCache[num].IsSurfaceLiquid;
804 }
805 return false;
806 }
807 return true;
808 }
809
810 public float GetVisibleLiquid(int x, int y)
811 {
812 x -= _drawArea.X;
813 y -= _drawArea.Y;
814 if (x < 0 || x >= _drawArea.Width || y < 0 || y >= _drawArea.Height)
815 {
816 return 0f;
817 }
818 int num = (x + 2) * (_drawArea.Height + 4) + y + 2;
819 if (!_cache[num].HasVisibleLiquid)
820 {
821 return 0f;
822 }
823 return _cache[num].VisibleLiquidLevel;
824 }
825
826 public void Update(GameTime gameTime)
827 {
829 {
830 float num = Main.windSpeedCurrent * 25f;
831 num = ((!(num < 0f)) ? (num + 6f) : (num - 6f));
832 _frameState += num * (float)gameTime.ElapsedGameTime.TotalSeconds;
833 if (_frameState < 0f)
834 {
835 _frameState += 16f;
836 }
837 _frameState %= 16f;
839 }
840 }
841
842 public void PrepareDraw(Rectangle drawArea)
843 {
844 InternalPrepareDraw(drawArea);
845 }
846
847 public void SetWaveMaskData(ref Texture2D texture)
848 {
849 try
850 {
851 if (texture == null || texture.Width < _drawArea.Height || texture.Height < _drawArea.Width)
852 {
853 Console.WriteLine("WaveMaskData texture recreated. {0}x{1}", _drawArea.Height, _drawArea.Width);
854 if (texture != null)
855 {
856 try
857 {
858 texture.Dispose();
859 }
860 catch
861 {
862 }
863 }
864 texture = new Texture2D(Main.instance.GraphicsDevice, _drawArea.Height, _drawArea.Width, mipMap: false, SurfaceFormat.Color);
865 }
866 texture.SetData(0, new Rectangle(0, 0, _drawArea.Height, _drawArea.Width), _waveMask, 0, _drawArea.Width * _drawArea.Height);
867 }
868 catch
869 {
870 texture = new Texture2D(Main.instance.GraphicsDevice, _drawArea.Height, _drawArea.Width, mipMap: false, SurfaceFormat.Color);
871 texture.SetData(0, new Rectangle(0, 0, _drawArea.Height, _drawArea.Width), _waveMask, 0, _drawArea.Width * _drawArea.Height);
872 }
873 }
874
876 {
877 return _drawArea;
878 }
879}
static void WriteLine()
Definition Console.cs:733
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static double Ceiling(double a)
static double Sin(double a)
static double Floor(double d)
static byte Max(byte val1, byte val2)
Definition Math.cs:738
static int NewDust(Vector2 Position, int Width, int Height, int Type, float SpeedX=0f, float SpeedY=0f, int Alpha=0, Color newColor=default(Color), float Scale=1f)
Definition Dust.cs:73
static int lavaBubbles
Definition Dust.cs:14
int GetShimmerFrame(bool top, float worldPositionX, float worldPositionY)
SpecialLiquidDrawCache[] _drawCacheForShimmer
static float GetShimmerGlitterOpacity(bool top, float worldPositionX, float worldPositionY)
Action< Color[], Rectangle > WaveFilters
static Vector4 GetShimmerBaseColor(float worldPositionX, float worldPositionY)
void SetWaveMaskData(ref Texture2D texture)
static float GetShimmerWave(ref float worldPositionX, ref float worldPositionY)
unsafe void InternalPrepareDraw(Rectangle drawArea)
static Color GetShimmerGlitterColor(bool top, float worldPositionX, float worldPositionY)
unsafe void DrawNormalLiquids(SpriteBatch spriteBatch, Vector2 drawOffset, int waterStyle, float globalAlpha, bool isBackgroundDraw)
static void SetShimmerVertexColors(ref VertexColors colors, float opacity, int x, int y)
readonly Asset< Texture2D >[] _liquidTextures
static VertexColors SetShimmerVertexColors_Sparkle(ref VertexColors colors, float opacity, int x, int y, bool top)
unsafe void DrawShimmer(SpriteBatch spriteBatch, Vector2 drawOffset, bool isBackgroundDraw)
static uint SimpleWhiteNoise(uint x, uint y)
static bool[] Platforms
Definition TileID.cs:163
static void GetCornerColors(int centerX, int centerY, out VertexColors vertices, float scale=1f)
Definition Lighting.cs:295
static bool hasFocus
Definition Main.cs:1781
static bool dedServ
Definition Main.cs:1226
static double timeForVisualEffects
Definition Main.cs:1286
static Main instance
Definition Main.cs:283
static Tile[,] tile
Definition Main.cs:1675
static TileBatch tileBatch
Definition Main.cs:976
static void DrawTileInWater(Vector2 drawOffset, int x, int y)
Definition Main.cs:54316
static Microsoft.Xna.Framework.Color hslToRgb(Vector3 hslVector)
Definition Main.cs:44913
static IAssetRepository Assets
Definition Main.cs:209
static bool gamePaused
Definition Main.cs:1072
static Dust[] dust
Definition Main.cs:1677
void liquidType(int liquidType)
Definition Tile.cs:233
ushort type
Definition Tile.cs:8
bool halfBrick()
Definition Tile.cs:650
static float Remap(float fromValue, float fromMin, float fromMax, float toMin, float toMax, bool clamped=true)
Definition Utils.cs:233
static bool SolidOrSlopedTile(Tile tile)
static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount)
Definition Vector4.cs:277