Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
FurnitureDesign.cs
浏览该文件的文档.
1using System.Globalization;
2using System.Text;
3using Engine;
5
6namespace Game {
7 public class FurnitureDesign {
8 public struct Cell {
9 public int Value;
10 }
11
12 public static string fName = "FurnitureDesign";
13
14 public struct Subdivision {
15 public int TotalVolume;
16
17 public int MinVolume;
18
19 public List<Box> Boxes;
20 }
21
22 public const int MinResolution = 2;
23
24 public const int maxDesign = 8192; //家具上限数量
25
26 public const int MaxResolution = 256; //家具格分辨率
27
28 public const int MaxTriangles = 65535; //家具复杂度
29
30 public const int MaxNameLength = 100;
31
32 public int m_index = -1;
33
34 public string m_name = string.Empty;
35
37
39
40 public bool m_gcUsed;
41
43
45
46 public int m_resolution;
47
48 public int[] m_values;
49
50 public int? m_hash;
51
53
54 public Box? m_box;
55
57
59
61
63
64 public int m_mainValue;
65
66 public int m_mountingFacesMask = -1;
67
68 public int m_transparentFacesMask = -1;
69
71
73
74 public int Resolution => m_resolution;
75
76 public int Hash {
77 get {
78 if (!m_hash.HasValue) {
80 for (int i = 0; i < m_values.Length; i++) {
81 m_hash += m_values[i] * (1 + 113 * i);
82 }
83 }
84 return m_hash.Value;
85 }
86 }
87
88 public Box Box {
89 get {
90 if (!m_box.HasValue) {
92 }
93 return m_box.Value;
94 }
95 }
96
98 get {
99 if (!m_shadowStrengthFactor.HasValue) {
101 }
102 return m_shadowStrengthFactor.Value;
103 }
104 }
105
106 public bool IsLightEmitter => GetTorchPoints(0).Length != 0;
107
108 public int MainValue {
109 get {
110 if (m_mainValue == 0) {
112 }
113 return m_mainValue;
114 }
115 }
116
117 public int MountingFacesMask {
118 get {
119 if (m_mountingFacesMask < 0) {
121 }
122 return m_mountingFacesMask;
123 }
124 }
125
127 get {
128 if (m_transparentFacesMask < 0) {
130 }
132 }
133 }
134
135 public int Index {
136 get => m_index;
137 set => m_index = value;
138 }
139
140 public string Name {
141 get => m_name;
142 set {
143 if (value.Length > 0) {
144 if (value[0] == ' '
145 || value[^1] == ' ') {
146 throw new InvalidOperationException(LanguageControl.Get(fName, 1));
147 }
148 /*string text = value;
149 foreach (char c in text)
150 {
151 if (c > '\u007f' || (!char.IsLetterOrDigit(c) && c != ' '))
152 {
153 throw new InvalidOperationException(LanguageControl.Get(fName, 1));
154 }
155 }*/
156 if (value.Length > 20) {
157 value = value.Substring(0, 20);
158 }
159 }
160 m_name = value;
161 }
162 }
163
165 get => m_furnitureSet;
166 set => m_furnitureSet = value;
167 }
168
170 get => m_linkedDesign;
171 set {
172 if (value != m_linkedDesign) {
173 m_linkedDesign = value;
174 m_hash = null;
175 }
176 }
177 }
178
180 get => m_interactionMode;
181 set {
182 if (value != m_interactionMode) {
183 m_interactionMode = value;
184 m_hash = null;
185 }
186 }
187 }
188
190 get {
191 if (m_geometry == null) {
193 }
194 return m_geometry;
195 }
196 }
197
198 public FurnitureDesign(SubsystemTerrain subsystemTerrain) => m_subsystemTerrain = subsystemTerrain;
199
200 public FurnitureDesign(int index, SubsystemTerrain subsystemTerrain, ValuesDictionary valuesDictionary) {
201 m_subsystemTerrain = subsystemTerrain;
202 m_index = index;
203 Name = valuesDictionary.GetValue("Name", string.Empty);
204 m_terrainUseCount = valuesDictionary.GetValue<int>("TerrainUseCount");
205 int value = valuesDictionary.GetValue<int>("Resolution");
206 InteractionMode = valuesDictionary.GetValue<FurnitureInteractionMode>("InteractionMode");
207 m_loadTimeLinkedDesignIndex = valuesDictionary.GetValue("LinkedDesign", -1);
208 string value2 = valuesDictionary.GetValue<string>("Values");
209 int num = 0;
210 int[] array = new int[value * value * value];
211 string[] array2 = value2.Split([','], StringSplitOptions.RemoveEmptyEntries);
212 for (int i = 0; i < array2.Length; i++) {
213 string[] array3 = array2[i].Split(['*'], StringSplitOptions.None);
214 if (array3.Length != 2) {
215 throw new InvalidOperationException(LanguageControl.Get(fName, 2));
216 }
217 int num2 = int.Parse(array3[0], CultureInfo.InvariantCulture);
218 int num3 = int.Parse(array3[1], CultureInfo.InvariantCulture);
219 int num4 = 0;
220 while (num4 < num2) {
221 array[num] = num3;
222 num4++;
223 num++;
224 }
225 }
226 SetValues(value, array);
227 }
228
229 public int GetValue(int index) => m_values[index];
230
231 public void SetValues(int resolution, int[] values) {
232 if (resolution < MinResolution
233 || resolution > MaxResolution) {
234 throw new ArgumentException(LanguageControl.Get(fName, 3));
235 }
236 if (values.Length != resolution * resolution * resolution) {
237 throw new ArgumentException(LanguageControl.Get(fName, 4));
238 }
239 m_resolution = resolution;
240 if (m_values == null
241 || m_values.Length != resolution * resolution * resolution) {
242 m_values = new int[resolution * resolution * resolution];
243 }
244 values.CopyTo(m_values, 0);
245 m_hash = null;
246 m_geometry = null;
247 m_box = null;
251 m_mainValue = 0;
254 }
255
256 public string GetDefaultName() {
257 if (InteractionMode == FurnitureInteractionMode.Multistate) {
258 int count = ListChain().Count;
259 if (count > 1) {
260 return string.Format(LanguageControl.Get(fName, 5), count);
261 }
262 }
263 else {
264 if (InteractionMode == FurnitureInteractionMode.ElectricButton) {
265 return LanguageControl.Get(fName, 6);
266 }
267 if (InteractionMode == FurnitureInteractionMode.ElectricSwitch) {
268 return LanguageControl.Get(fName, 7);
269 }
270 if (InteractionMode == FurnitureInteractionMode.ConnectedMultistate) {
271 int count2 = ListChain().Count;
272 if (count2 > 1) {
273 return string.Format(LanguageControl.Get(fName, 8), count2);
274 }
275 }
276 }
277 return LanguageControl.Get(fName, 9);
278 }
279
280 public BoundingBox[] GetCollisionBoxes(int rotation) {
281 if (m_collisionBoxesByRotation == null) {
283 }
284 return m_collisionBoxesByRotation[rotation];
285 }
286
287 public BoundingBox[] GetInteractionBoxes(int rotation) {
288 if (m_interactionBoxesByRotation == null) {
290 }
291 return m_interactionBoxesByRotation[rotation];
292 }
293
294 public BoundingBox[] GetTorchPoints(int rotation) {
295 if (m_torchPointsByRotation == null) {
297 }
298 return m_torchPointsByRotation[rotation];
299 }
300
301 public void Paint(int? color) {
302 int[] array = new int[m_values.Length];
303 for (int i = 0; i < m_values.Length; i++) {
304 int num = m_values[i];
305 int num2 = Terrain.ExtractContents(num);
306 IPaintableBlock paintableBlock = BlocksManager.Blocks[num2] as IPaintableBlock;
307 array[i] = paintableBlock?.Paint(null, num, color) ?? num;
308 }
309 SetValues(Resolution, array);
310 }
311
312 public void Resize(int resolution) {
313 if (resolution < MinResolution
314 || resolution > MaxResolution) {
315 throw new ArgumentException(LanguageControl.Get(fName, 3));
316 }
317 if (resolution == m_resolution) {
318 return;
319 }
320 int[] array = new int[resolution * resolution * resolution];
321 for (int i = 0; i < resolution; i++) {
322 for (int j = 0; j < resolution; j++) {
323 for (int k = 0; k < resolution; k++) {
324 if (k >= 0
325 && k < m_resolution
326 && j >= 0
327 && j < m_resolution
328 && i >= 0
329 && i < m_resolution) {
330 array[k + j * resolution + i * resolution * resolution] =
332 }
333 }
334 }
335 }
336 SetValues(resolution, array);
337 }
338
339 public void Shift(Point3 delta) {
340 if (!(delta != Point3.Zero)) {
341 return;
342 }
343 int[] array = new int[m_resolution * m_resolution * m_resolution];
344 for (int i = 0; i < m_resolution; i++) {
345 for (int j = 0; j < m_resolution; j++) {
346 for (int k = 0; k < m_resolution; k++) {
347 int num = k + delta.X;
348 int num2 = j + delta.Y;
349 int num3 = i + delta.Z;
350 if (num >= 0
351 && num < m_resolution
352 && num2 >= 0
353 && num2 < m_resolution
354 && num3 >= 0
355 && num3 < m_resolution) {
356 array[num + num2 * m_resolution + num3 * m_resolution * m_resolution] =
358 }
359 }
360 }
361 }
362 SetValues(m_resolution, array);
363 }
364
365 public void Rotate(int axis, int steps) {
366 steps %= 4;
367 if (steps < 0) {
368 steps += 4;
369 }
370 if (steps <= 0) {
371 return;
372 }
373 int[] array = new int[m_resolution * m_resolution * m_resolution];
374 for (int i = 0; i < m_resolution; i++) {
375 for (int j = 0; j < m_resolution; j++) {
376 for (int k = 0; k < m_resolution; k++) {
377 Vector3 vector = RotatePoint(new Vector3(k, j, i) - new Vector3(m_resolution / 2f - 0.5f), axis, steps)
378 + new Vector3(m_resolution / 2f - 0.5f);
379 Point3 point = new((int)MathF.Round(vector.X), (int)MathF.Round(vector.Y), (int)MathF.Round(vector.Z));
380 if (point.X >= 0
381 && point.X < m_resolution
382 && point.Y >= 0
383 && point.Y < m_resolution
384 && point.Z >= 0
385 && point.Z < m_resolution) {
386 array[point.X + point.Y * m_resolution + point.Z * m_resolution * m_resolution] =
388 }
389 }
390 }
391 }
392 SetValues(m_resolution, array);
393 }
394
395 public void Mirror(int axis) {
396 int[] array = new int[m_resolution * m_resolution * m_resolution];
397 for (int i = 0; i < m_resolution; i++) {
398 for (int j = 0; j < m_resolution; j++) {
399 for (int k = 0; k < m_resolution; k++) {
400 Vector3 vector = MirrorPoint(new Vector3(k, j, i) - new Vector3(m_resolution / 2f - 0.5f), axis)
401 + new Vector3(m_resolution / 2f - 0.5f);
402 Point3 point = new((int)MathF.Round(vector.X), (int)MathF.Round(vector.Y), (int)MathF.Round(vector.Z));
403 if (point.X >= 0
404 && point.X < m_resolution
405 && point.Y >= 0
406 && point.Y < m_resolution
407 && point.Z >= 0
408 && point.Z < m_resolution) {
409 array[point.X + point.Y * m_resolution + point.Z * m_resolution * m_resolution] =
411 }
412 }
413 }
414 }
415 SetValues(m_resolution, array);
416 }
417
419 StringBuilder stringBuilder = new();
420 int num = m_values[0];
421 int num2 = 1;
422 for (int i = 1; i < m_values.Length; i++) {
423 if (m_values[i] != num) {
424 stringBuilder.Append(num2.ToString(CultureInfo.InvariantCulture));
425 stringBuilder.Append('*');
426 stringBuilder.Append(num.ToString(CultureInfo.InvariantCulture));
427 stringBuilder.Append(',');
428 num = m_values[i];
429 num2 = 1;
430 }
431 else {
432 num2++;
433 }
434 }
435 stringBuilder.Append(num2.ToString(CultureInfo.InvariantCulture));
436 stringBuilder.Append('*');
437 stringBuilder.Append(num.ToString(CultureInfo.InvariantCulture));
438 stringBuilder.Append(',');
439 ValuesDictionary valuesDictionary = new();
440 if (!string.IsNullOrEmpty(Name)) {
441 valuesDictionary.SetValue("Name", Name);
442 }
443 valuesDictionary.SetValue("TerrainUseCount", m_terrainUseCount);
444 valuesDictionary.SetValue("Resolution", m_resolution);
445 valuesDictionary.SetValue("InteractionMode", m_interactionMode);
446 if (LinkedDesign != null) {
447 valuesDictionary.SetValue("LinkedDesign", LinkedDesign.Index);
448 }
449 valuesDictionary.SetValue("Values", stringBuilder.ToString());
450 return valuesDictionary;
451 }
452
453 public bool Compare(FurnitureDesign other) {
454 if (this == other) {
455 return true;
456 }
457 if (Resolution == other.Resolution
459 && Hash == other.Hash
460 && Name == other.Name) {
461 for (int i = 0; i < m_values.Length; i++) {
462 if (m_values[i] != other.m_values[i]) {
463 return false;
464 }
465 }
466 return true;
467 }
468 return false;
469 }
470
471 public bool CompareChain(FurnitureDesign other) {
472 if (this == other) {
473 return true;
474 }
475 List<FurnitureDesign> list = ListChain();
476 List<FurnitureDesign> list2 = other.ListChain();
477 if (list.Count != list2.Count) {
478 return false;
479 }
480 for (int i = 0; i < list.Count; i++) {
481 if (!list[i].Compare(list2[i])) {
482 return false;
483 }
484 }
485 return true;
486 }
487
489 FurnitureDesign furnitureDesign = new(m_subsystemTerrain);
490 furnitureDesign.SetValues(Resolution, m_values);
491 furnitureDesign.Name = Name;
492 furnitureDesign.LinkedDesign = LinkedDesign;
493 furnitureDesign.InteractionMode = InteractionMode;
494 return furnitureDesign;
495 }
496
497 public List<FurnitureDesign> CloneChain() {
498 List<FurnitureDesign> list = ListChain();
499 List<FurnitureDesign> list2 = new(list.Count);
500 for (int i = 0; i < list.Count; i++) {
501 list2.Add(list[i].Clone());
502 }
503 for (int j = 0; j < list2.Count - 1; j++) {
504 list2[j].LinkedDesign = list2[j + 1];
505 }
506 int num = list.IndexOf(list[^1].LinkedDesign);
507 if (num >= 0) {
508 list2[^1].LinkedDesign = list2[num];
509 }
510 return list2;
511 }
512
513 public List<FurnitureDesign> ListChain() {
514 FurnitureDesign furnitureDesign = this;
515 HashSet<FurnitureDesign> hashSet = new();
516 List<FurnitureDesign> list = new();
517 do {
518 hashSet.Add(furnitureDesign);
519 list.Add(furnitureDesign);
520 furnitureDesign = furnitureDesign.LinkedDesign;
521 }
522 while (furnitureDesign != null
523 && !hashSet.Contains(furnitureDesign));
524 return list;
525 }
526
527 public static List<List<FurnitureDesign>> ListChains(IEnumerable<FurnitureDesign> designs) {
528 List<List<FurnitureDesign>> list = new();
529 List<FurnitureDesign> list2 = new(designs);
530 while (list2.Count > 0) {
531 List<FurnitureDesign> list3 = list2[0].ListChain();
532 list.Add(list3);
533 foreach (FurnitureDesign item in list3) {
534 list2.Remove(item);
535 }
536 }
537 return list;
538 }
539
541 byte[] array = new byte[m_values.Length];
542 int num = 0;
543 for (int i = 0; i < Resolution; i++) {
544 for (int j = 0; j < Resolution; j++) {
545 int num2 = 0;
546 int num3 = 0;
547 while (num3 < Resolution) {
548 num2 = m_values[num] == 0 ? num2 + 1 : 0;
549 array[num] = (byte)num2;
550 num3++;
551 num++;
552 }
553 }
554 }
555 return array;
556 }
557
558 public Box CalculateBox(Box box, byte[] precedingEmptySpaces) {
559 int num = int.MaxValue;
560 int num2 = int.MaxValue;
561 int num3 = int.MaxValue;
562 int num4 = int.MinValue;
563 int num5 = int.MinValue;
564 int num6 = int.MinValue;
565 for (int i = box.Near; i < box.Far; i++) {
566 int num7 = Math.Min(num3, i);
567 int num8 = Math.Max(num6, i);
568 int num9 = box.Top;
569 int num10 = (num9 + i * Resolution) * Resolution;
570 while (num9 < box.Bottom) {
571 int num11 = box.Right - 1 - precedingEmptySpaces[num10 + box.Right - 1];
572 if (num11 >= box.Left) {
573 num4 = Math.Max(num4, num11);
574 num2 = Math.Min(num2, num9);
575 num5 = Math.Max(num5, num9);
576 num3 = num7;
577 num6 = num8;
578 int num12 = num - 1;
579 for (int j = box.Left; j <= num12; j++) {
580 if (m_values[num10 + j] != 0) {
581 num = Math.Min(num, j);
582 break;
583 }
584 }
585 }
586 num9++;
587 num10 += Resolution;
588 }
589 }
590 return new Box(num, num2, num3, num4 - num + 1, num5 - num2 + 1, num6 - num3 + 1);
591 }
592
594 float[] array = new float[Resolution * Resolution];
595 int num = 0;
596 for (int i = 0; i < Resolution; i++) {
597 for (int j = 0; j < Resolution; j++) {
598 float x = (j + 1) / (float)Resolution;
599 for (int k = 0; k < Resolution; k++) {
600 if (!IsValueTransparent(m_values[num++])) {
601 array[k + i * Resolution] = MathUtils.Max(array[k + i * Resolution], x);
602 }
603 }
604 }
605 }
606 float num2 = 0f;
607 for (int l = 0; l < Resolution * Resolution; l++) {
608 num2 += array[l];
609 }
610 num2 /= Resolution * Resolution;
611 float num3 = 1.5f;
612 m_shadowStrengthFactor = (int)Math.Clamp(MathF.Round(num2 * 3f * num3), 0f, 3f);
613 }
614
615 public void CreateGeometry() {
617 for (int i = 0; i < 6; i++) {
618 int num = CellFace.OppositeFace(i);
619 Point3 point;
620 Point3 point2;
621 Point3 point3;
622 Point3 point4;
623 Point3 point5;
624 switch (i) {
625 case 0:
626 point = new Point3(0, 0, 1);
627 point2 = new Point3(-1, 0, 0);
628 point3 = new Point3(0, -1, 0);
629 point4 = new Point3(m_resolution, m_resolution, 0);
630 point5 = new Point3(m_resolution - 1, m_resolution - 1, 0);
631 break;
632 case 1:
633 point = new Point3(1, 0, 0);
634 point2 = new Point3(0, 0, 1);
635 point3 = new Point3(0, -1, 0);
636 point4 = new Point3(0, m_resolution, 0);
637 point5 = new Point3(0, m_resolution - 1, 0);
638 break;
639 case 2:
640 point = new Point3(0, 0, -1);
641 point2 = new Point3(1, 0, 0);
642 point3 = new Point3(0, -1, 0);
643 point4 = new Point3(0, m_resolution, m_resolution);
644 point5 = new Point3(0, m_resolution - 1, m_resolution - 1);
645 break;
646 case 3:
647 point = new Point3(-1, 0, 0);
648 point2 = new Point3(0, 0, -1);
649 point3 = new Point3(0, -1, 0);
651 point5 = new Point3(m_resolution - 1, m_resolution - 1, m_resolution - 1);
652 break;
653 case 4:
654 point = new Point3(0, 1, 0);
655 point2 = new Point3(-1, 0, 0);
656 point3 = new Point3(0, 0, 1);
657 point4 = new Point3(m_resolution, 0, 0);
658 point5 = new Point3(m_resolution - 1, 0, 0);
659 break;
660 default:
661 point = new Point3(0, -1, 0);
662 point2 = new Point3(-1, 0, 0);
663 point3 = new Point3(0, 0, -1);
665 point5 = new Point3(m_resolution - 1, m_resolution - 1, m_resolution - 1);
666 break;
667 }
668 BlockMesh blockMesh = new();
669 BlockMesh blockMesh2 = new();
670 for (int j = 0; j < m_resolution; j++) {
671 Cell[] array = new Cell[m_resolution * m_resolution];
672 for (int k = 0; k < m_resolution; k++) {
673 for (int l = 0; l < m_resolution; l++) {
674 int num2 = j * point.X + k * point3.X + l * point2.X + point5.X;
675 int num3 = j * point.Y + k * point3.Y + l * point2.Y + point5.Y;
676 int num4 = j * point.Z + k * point3.Z + l * point2.Z + point5.Z;
677 int num5 = num2 + num3 * m_resolution + num4 * m_resolution * m_resolution;
678 int num6 = m_values[num5];
679 Cell cell = default;
680 cell.Value = num6;
681 Cell cell2 = cell;
682 if (j > 0
683 && num6 != 0) {
684 int num7 = num2 - point.X + (num3 - point.Y) * m_resolution + (num4 - point.Z) * m_resolution * m_resolution;
685 int value = m_values[num7];
686 if (!IsValueTransparent(value)
687 || Terrain.ExtractContents(num6) == Terrain.ExtractContents(value)) {
688 cell2.Value = 0;
689 }
690 }
691 array[l + k * m_resolution] = cell2;
692 }
693 }
694 for (int m = 0; m < m_resolution; m++) {
695 for (int n = 0; n < m_resolution; n++) {
696 int value2 = array[n + m * m_resolution].Value;
697 if (value2 == 0) {
698 continue;
699 }
700 Point2 point6 = FindLargestSize(array, new Point2(n, m), value2);
701 if (!(point6 == Point2.Zero)) {
702 MarkUsed(array, new Point2(n, m), point6);
703 float num8 = 0.0005f * m_resolution;
704 float num9 = n - num8;
705 float num10 = n + point6.X + num8;
706 float num11 = m - num8;
707 float num12 = m + point6.Y + num8;
708 float x = j * point.X + num11 * point3.X + num9 * point2.X + point4.X;
709 float y = j * point.Y + num11 * point3.Y + num9 * point2.Y + point4.Y;
710 float z = j * point.Z + num11 * point3.Z + num9 * point2.Z + point4.Z;
711 float x2 = j * point.X + num11 * point3.X + num10 * point2.X + point4.X;
712 float y2 = j * point.Y + num11 * point3.Y + num10 * point2.Y + point4.Y;
713 float z2 = j * point.Z + num11 * point3.Z + num10 * point2.Z + point4.Z;
714 float x3 = j * point.X + num12 * point3.X + num10 * point2.X + point4.X;
715 float y3 = j * point.Y + num12 * point3.Y + num10 * point2.Y + point4.Y;
716 float z3 = j * point.Z + num12 * point3.Z + num10 * point2.Z + point4.Z;
717 float x4 = j * point.X + num12 * point3.X + num9 * point2.X + point4.X;
718 float y4 = j * point.Y + num12 * point3.Y + num9 * point2.Y + point4.Y;
719 float z4 = j * point.Z + num12 * point3.Z + num9 * point2.Z + point4.Z;
720 BlockMesh blockMesh3 = blockMesh;
721 int num13 = Terrain.ExtractContents(value2);
722 Block block = BlocksManager.Blocks[num13];
723 int num14 = block.GetFaceTextureSlot(i, value2);
724 bool isEmissive = false;
725 Color color = Color.White;
726 if (block is IPaintableBlock paintableBlock) {
727 int? paintColor = paintableBlock.GetPaintColor(value2);
728 color = SubsystemPalette.GetColor(m_subsystemTerrain, paintColor);
729 }
730 else if (block is WaterBlock) {
731 color = BlockColorsMap.Water.Lookup(12, 12);
732 num14 = 189;
733 }
734 else if (block is CarpetBlock) {
735 int color2 = CarpetBlock.GetColor(Terrain.ExtractData(value2));
737 }
738 else if (block is TorchBlock
739 || block is WickerLampBlock) {
740 isEmissive = true;
741 num14 = 31;
742 }
743 else if (block is GlassBlock) {
744 blockMesh3 = blockMesh2;
745 }
747 "SetFurnitureDesignColor",
748 loader => {
749 loader.SetFurnitureDesignColor(this, block, value2, ref num14, ref color);
750 return false;
751 }
752 );
753 int num15 = num14 % 16;
754 int num16 = num14 / 16;
755 int count = blockMesh3.Vertices.Count;
756 blockMesh3.Vertices.Count += 4;
757 BlockMeshVertex[] array2 = blockMesh3.Vertices.Array;
758 float x5 = ((n + 0.01f) / m_resolution + num15) / 16f;
759 float x6 = ((n + point6.X - 0.01f) / m_resolution + num15) / 16f;
760 float y5 = ((m + 0.01f) / m_resolution + num16) / 16f;
761 float y6 = ((m + point6.Y - 0.01f) / m_resolution + num16) / 16f;
762 array2[count] = new BlockMeshVertex {
763 Position = new Vector3(x, y, z) / m_resolution,
764 Color = color,
765 Face = (byte)num,
766 TextureCoordinates = new Vector2(x5, y5),
767 IsEmissive = isEmissive
768 };
769 array2[count + 1] = new BlockMeshVertex {
770 Position = new Vector3(x2, y2, z2) / m_resolution,
771 Color = color,
772 Face = (byte)num,
773 TextureCoordinates = new Vector2(x6, y5),
774 IsEmissive = isEmissive
775 };
776 array2[count + 2] = new BlockMeshVertex {
777 Position = new Vector3(x3, y3, z3) / m_resolution,
778 Color = color,
779 Face = (byte)num,
780 TextureCoordinates = new Vector2(x6, y6),
781 IsEmissive = isEmissive
782 };
783 array2[count + 3] = new BlockMeshVertex {
784 Position = new Vector3(x4, y4, z4) / m_resolution,
785 Color = color,
786 Face = (byte)num,
787 TextureCoordinates = new Vector2(x5, y6),
788 IsEmissive = isEmissive
789 };
790 int count2 = blockMesh3.Indices.Count;
791 blockMesh3.Indices.Count += 6;
792 int[] array3 = blockMesh3.Indices.Array;
793 array3[count2] = count;
794 array3[count2 + 1] = count + 1;
795 array3[count2 + 2] = count + 2;
796 array3[count2 + 3] = count + 2;
797 array3[count2 + 4] = count + 3;
798 array3[count2 + 5] = count;
799 }
800 }
801 }
802 }
803 if (blockMesh.Indices.Count > 0) {
804 blockMesh.Trim();
805 blockMesh.GenerateSidesData();
806 m_geometry.SubsetOpaqueByFace[i] = blockMesh;
807 }
808 if (blockMesh2.Indices.Count > 0) {
809 blockMesh2.Trim();
810 blockMesh2.GenerateSidesData();
811 m_geometry.SubsetAlphaTestByFace[i] = blockMesh2;
812 }
813 }
814 }
815
818 List<BoundingBox> list = new(subdivision.Boxes.Count);
819 for (int i = 0; i < subdivision.Boxes.Count; i++) {
820 Box box = subdivision.Boxes[i];
821 Vector3 min = new Vector3(box.Left, box.Top, box.Near) / Resolution;
822 Vector3 max = new Vector3(box.Right, box.Bottom, box.Far) / Resolution;
823 list.Add(new BoundingBox(min, max));
824 }
826 for (int j = 0; j < 4; j++) {
827 Matrix m = Matrix.CreateTranslation(-0.5f, 0f, -0.5f)
828 * Matrix.CreateRotationY(j * (float)Math.PI / 2f)
829 * Matrix.CreateTranslation(0.5f, 0f, 0.5f);
830 m_collisionBoxesByRotation[j] = new BoundingBox[list.Count];
831 for (int k = 0; k < list.Count; k++) {
832 Vector3 v = Vector3.Transform(list[k].Min, m);
833 Vector3 v2 = Vector3.Transform(list[k].Max, m);
834 BoundingBox boundingBox = new(Vector3.Min(v, v2), Vector3.Max(v, v2));
835 m_collisionBoxesByRotation[j][k] = boundingBox;
836 }
837 }
838 List<BoundingBox> list2 = new(list);
839 while (true) {
840 int num = 0;
841 int l;
842 BoundingBox item;
843 while (true) {
844 if (num < list2.Count) {
845 for (l = 0; l < list2.Count; l++) {
846 if (num != l) {
847 BoundingBox b = list2[num];
848 BoundingBox b2 = list2[l];
849 item = BoundingBox.Union(b, b2);
850 Vector3 vector = item.Size();
851 if ((item.Volume() - b.Volume() - b2.Volume()) / MathUtils.Min(vector.X, vector.Y, vector.Z) < 0.4f) {
852 goto end_IL_0263;
853 }
854 }
855 }
856 num++;
857 continue;
858 }
859 bool flag = false;
860 for (int n = 0; n < list2.Count; n++) {
861 Vector3 vector2 = list2[n].Size();
862 flag |= vector2.X >= 0.6f && vector2.Y >= 0.6f;
863 flag |= vector2.X >= 0.6f && vector2.Z >= 0.6f;
864 flag |= vector2.Y >= 0.6f && vector2.Z >= 0.6f;
865 }
866 float minSize = flag ? 0.0625f : 0.6f;
867 for (int num2 = 0; num2 < list2.Count; num2++) {
868 BoundingBox value = list2[num2];
869 EnsureMinSize(ref value.Min.X, ref value.Max.X, minSize);
870 EnsureMinSize(ref value.Min.Y, ref value.Max.Y, minSize);
871 EnsureMinSize(ref value.Min.Z, ref value.Max.Z, minSize);
872 list2[num2] = value;
873 }
875 for (int num3 = 0; num3 < 4; num3++) {
876 Matrix m2 = Matrix.CreateTranslation(-0.5f, 0f, -0.5f)
877 * Matrix.CreateRotationY(num3 * (float)Math.PI / 2f)
878 * Matrix.CreateTranslation(0.5f, 0f, 0.5f);
879 m_interactionBoxesByRotation[num3] = new BoundingBox[list2.Count];
880 for (int num4 = 0; num4 < list2.Count; num4++) {
881 Vector3 v3 = Vector3.Transform(list2[num4].Min, m2);
882 Vector3 v4 = Vector3.Transform(list2[num4].Max, m2);
883 BoundingBox boundingBox2 = new(Vector3.Min(v3, v4), Vector3.Max(v3, v4));
884 m_interactionBoxesByRotation[num3][num4] = boundingBox2;
885 }
886 }
887 return;
888 end_IL_0263:
889 break;
890 }
891 list2.RemoveAt(num);
892 list2.RemoveAt(num < l ? l - 1 : l);
893 list2.Add(item);
894 }
895 }
896
897 public void CreateTorchPoints() {
898 List<BoundingBox> list = new();
899 for (int i = 0; i < Resolution; i++) {
900 for (int j = 0; j < Resolution; j++) {
901 for (int k = 0; k < Resolution; k++) {
903 if (num != 31
904 && num != 17) {
905 continue;
906 }
907 BoundingBox boundingBox = new(new Vector3(k, j, i) / Resolution, new Vector3(k + 1, j + 1, i + 1) / Resolution);
908 int num2 = -1;
909 for (int l = 0; l < list.Count; l++) {
910 BoundingBox boundingBox2 = list[l];
911 Vector3 vector = boundingBox2.Size();
912 Vector3 vector2 = boundingBox2.Center() - boundingBox.Center();
913 vector2.X = MathUtils.Max(MathF.Abs(vector2.X) - vector.X / 2f, 0f);
914 vector2.Y = MathUtils.Max(MathF.Abs(vector2.Y) - vector.Y / 2f, 0f);
915 vector2.Z = MathUtils.Max(MathF.Abs(vector2.Z) - vector.Z / 2f, 0f);
916 if (vector2.Length() < 0.15f) {
917 num2 = l;
918 break;
919 }
920 }
921 if (num2 >= 0) {
922 list[num2] = BoundingBox.Union(list[num2], boundingBox);
923 }
924 else if (list.Count < 4) {
925 list.Add(boundingBox);
926 }
927 }
928 }
929 }
931 for (int m = 0; m < 4; m++) {
932 Matrix m2 = Matrix.CreateTranslation(-0.5f, 0f, -0.5f)
933 * Matrix.CreateRotationY(m * (float)Math.PI / 2f)
934 * Matrix.CreateTranslation(0.5f, 0f, 0.5f);
935 m_torchPointsByRotation[m] = new BoundingBox[list.Count];
936 for (int n = 0; n < list.Count; n++) {
937 Vector3 v = Vector3.Transform(list[n].Min, m2);
938 Vector3 v2 = Vector3.Transform(list[n].Max, m2);
939 m_torchPointsByRotation[m][n] = new BoundingBox(Vector3.Min(v, v2), Vector3.Max(v, v2));
940 }
941 }
942 }
943
944 public void CalculateMainValue() {
945 Dictionary<int, int> dictionary = new();
946 for (int i = 0; i < Resolution; i++) {
947 for (int j = 0; j < Resolution; j++) {
948 for (int num = Resolution - 1; num >= 0; num--) {
949 int num2 = m_values[j + num * Resolution + i * Resolution * Resolution];
950 if (num2 != 0) {
951 dictionary.TryGetValue(num2, out int value);
952 dictionary[num2] = value + 1;
953 break;
954 }
955 }
956 }
957 }
958 int num3 = 0;
959 foreach (KeyValuePair<int, int> item in dictionary) {
960 if (item.Value > num3) {
961 m_mainValue = item.Key;
962 num3 = item.Value;
963 }
964 }
965 }
966
967 public void CalculateFacesMasks() {
970 for (int i = 0; i < Resolution; i++) {
971 for (int j = 0; j < Resolution; j++) {
972 int[] values = m_values;
973 int num = i + j * Resolution;
974 _ = Resolution;
975 int value = values[num + 0 * Resolution];
976 int value2 = m_values[i + j * Resolution + (Resolution - 1) * Resolution * Resolution];
977 if (IsValueTransparent(value)) {
979 }
980 else {
982 }
983 if (IsValueTransparent(value2)) {
985 }
986 else {
988 }
989 }
990 }
991 for (int k = 0; k < Resolution; k++) {
992 for (int l = 0; l < Resolution; l++) {
993 int value3 = m_values[k * Resolution + l * Resolution * Resolution];
994 int value4 = m_values[Resolution - 1 + k * Resolution + l * Resolution * Resolution];
995 if (IsValueTransparent(value3)) {
997 }
998 else {
1000 }
1001 if (IsValueTransparent(value4)) {
1003 }
1004 else {
1006 }
1007 }
1008 }
1009 for (int m = 0; m < Resolution; m++) {
1010 for (int n = 0; n < Resolution; n++) {
1011 int[] values2 = m_values;
1012 int num2 = m;
1013 _ = Resolution;
1014 int value5 = values2[num2 + 0 + n * Resolution * Resolution];
1015 int value6 = m_values[m + (Resolution - 1) * Resolution + n * Resolution * Resolution];
1016 if (IsValueTransparent(value5)) {
1018 }
1019 else {
1020 m_mountingFacesMask |= 32;
1021 }
1022 if (IsValueTransparent(value6)) {
1024 }
1025 else {
1026 m_mountingFacesMask |= 16;
1027 }
1028 }
1029 }
1030 }
1031
1032 public Subdivision CreateBoundingBoxesHelper(Box box, int depth, byte[] precedingEmptySpaces) {
1033 int num = 0;
1034 Subdivision result = default;
1035 result.TotalVolume = box.Width * box.Height * box.Depth;
1036 result.MinVolume = result.TotalVolume;
1037 result.Boxes = [box];
1038 if (depth < 2) {
1039 for (int num2 = box.Bottom - 1; num2 >= box.Top + 1; num2--) {
1040 Box box2 = CalculateBox(new Box(box.Left, box.Top, box.Near, box.Width, num2 - box.Top, box.Depth), precedingEmptySpaces);
1041 Box box3 = CalculateBox(new Box(box.Left, num2, box.Near, box.Width, box.Bottom - num2, box.Depth), precedingEmptySpaces);
1042 Subdivision subdivision = CreateBoundingBoxesHelper(box2, depth + 1, precedingEmptySpaces);
1043 Subdivision subdivision2 = CreateBoundingBoxesHelper(box3, depth + 1, precedingEmptySpaces);
1044 int num3 = subdivision.Boxes.Count + subdivision2.Boxes.Count;
1045 int num4 = subdivision.TotalVolume + subdivision2.TotalVolume;
1046 int num5 = MathUtils.Min(subdivision.MinVolume, subdivision2.MinVolume);
1047 int num6 = num3 > result.Boxes.Count ? num4 + num : num4;
1048 if (num6 < result.TotalVolume
1049 || (num6 == result.TotalVolume && num5 > result.MinVolume)) {
1050 result.TotalVolume = num4;
1051 result.MinVolume = num5;
1052 result.Boxes = subdivision.Boxes;
1053 result.Boxes.AddRange(subdivision2.Boxes);
1054 }
1055 }
1056 for (int i = box.Near + 1; i < box.Far; i++) {
1057 Box box4 = CalculateBox(new Box(box.Left, box.Top, box.Near, box.Width, box.Height, i - box.Near), precedingEmptySpaces);
1058 Box box5 = CalculateBox(new Box(box.Left, box.Top, i, box.Width, box.Height, box.Far - i), precedingEmptySpaces);
1059 Subdivision subdivision3 = CreateBoundingBoxesHelper(box4, depth + 1, precedingEmptySpaces);
1060 Subdivision subdivision4 = CreateBoundingBoxesHelper(box5, depth + 1, precedingEmptySpaces);
1061 int num7 = subdivision3.Boxes.Count + subdivision4.Boxes.Count;
1062 int num8 = subdivision3.TotalVolume + subdivision4.TotalVolume;
1063 int num9 = MathUtils.Min(subdivision3.MinVolume, subdivision4.MinVolume);
1064 int num10 = num7 > result.Boxes.Count ? num8 + num : num8;
1065 if (num10 < result.TotalVolume
1066 || (num10 == result.TotalVolume && num9 > result.MinVolume)) {
1067 result.TotalVolume = num8;
1068 result.MinVolume = num9;
1069 result.Boxes = subdivision3.Boxes;
1070 result.Boxes.AddRange(subdivision4.Boxes);
1071 }
1072 }
1073 for (int j = box.Left + 1; j < box.Right; j++) {
1074 Box box6 = CalculateBox(new Box(box.Left, box.Top, box.Near, j - box.Left, box.Height, box.Depth), precedingEmptySpaces);
1075 Box box7 = CalculateBox(new Box(j, box.Top, box.Near, box.Right - j, box.Height, box.Depth), precedingEmptySpaces);
1076 Subdivision subdivision5 = CreateBoundingBoxesHelper(box6, depth + 1, precedingEmptySpaces);
1077 Subdivision subdivision6 = CreateBoundingBoxesHelper(box7, depth + 1, precedingEmptySpaces);
1078 int num11 = subdivision5.Boxes.Count + subdivision6.Boxes.Count;
1079 int num12 = subdivision5.TotalVolume + subdivision6.TotalVolume;
1080 int num13 = MathUtils.Min(subdivision5.MinVolume, subdivision6.MinVolume);
1081 int num14 = num11 > result.Boxes.Count ? num12 + num : num12;
1082 if (num14 < result.TotalVolume
1083 || (num14 == result.TotalVolume && num13 > result.MinVolume)) {
1084 result.TotalVolume = num12;
1085 result.MinVolume = num13;
1086 result.Boxes = subdivision5.Boxes;
1087 result.Boxes.AddRange(subdivision6.Boxes);
1088 }
1089 }
1090 }
1091 return result;
1092 }
1093
1094 public Point2 FindLargestSize(Cell[] surface, Point2 start, int value) {
1095 Point2 result = Point2.Zero;
1096 int num = m_resolution;
1097 for (int i = start.Y; i < m_resolution; i++) {
1098 for (int j = start.X; j <= num; j++) {
1099 if (j == num
1100 || surface[j + i * m_resolution].Value != value) {
1101 num = j;
1102 Point2 point = new(num - start.X, i - start.Y + 1);
1103 if (point.X * point.Y > result.X * result.Y) {
1104 result = point;
1105 }
1106 }
1107 }
1108 }
1109 return result;
1110 }
1111
1112 public void MarkUsed(Cell[] surface, Point2 start, Point2 size) {
1113 for (int i = start.Y; i < start.Y + size.Y; i++) {
1114 for (int j = start.X; j < start.X + size.X; j++) {
1115 surface[j + i * m_resolution].Value = 0;
1116 }
1117 }
1118 }
1119
1120 public static Vector3 RotatePoint(Vector3 p, int axis, int steps) {
1121 for (int i = 0; i < steps; i++) {
1122 switch (axis) {
1123 case 0: p = new Vector3(p.X, p.Z, 0f - p.Y); break;
1124 case 1: p = new Vector3(0f - p.Z, p.Y, p.X); break;
1125 default: p = new Vector3(0f - p.Y, p.X, p.Z); break;
1126 }
1127 }
1128 return p;
1129 }
1130
1131 public static Vector3 MirrorPoint(Vector3 p, int axis) {
1132 switch (axis) {
1133 case 0: p = new Vector3(p.X, p.Y, 0f - p.Z); break;
1134 case 1: p = new Vector3(0f - p.X, p.Y, p.Z); break;
1135 default: p = new Vector3(0f - p.X, p.Y, p.Z); break;
1136 }
1137 return p;
1138 }
1139
1140 public static void EnsureMinSize(ref float min, ref float max, float minSize) {
1141 float num = max - min;
1142 if (num < minSize) {
1143 float num2 = minSize - num;
1144 min -= num2 / 2f;
1145 max += num2 / 2f;
1146 if (min < 0f) {
1147 max -= min;
1148 min = 0f;
1149 }
1150 else if (max > 1f) {
1151 min -= max - 1f;
1152 max = 1f;
1153 }
1154 }
1155 }
1156
1157 public static bool IsValueTransparent(int value) {
1158 if (value != 0) {
1159 return Terrain.ExtractContents(value) == 15;
1160 }
1161 return true;
1162 }
1163 }
1164}
Engine.Vector3 Vector3
static int Min(int x1, int x2)
static int Max(int x1, int x2)
Color Lookup(int temperature, int humidity)
static BlockColorsMap Water
virtual int GetFaceTextureSlot(int face, int value)
virtual void Trim()
virtual void GenerateSidesData()
DynamicArray< BlockMeshVertex > Vertices
DynamicArray< int > Indices
static int GetColor(int data)
FurnitureDesign(int index, SubsystemTerrain subsystemTerrain, ValuesDictionary valuesDictionary)
FurnitureInteractionMode m_interactionMode
void MarkUsed(Cell[] surface, Point2 start, Point2 size)
static Vector3 RotatePoint(Vector3 p, int axis, int steps)
FurnitureInteractionMode InteractionMode
BoundingBox[][] m_interactionBoxesByRotation
BoundingBox[][] m_collisionBoxesByRotation
List< FurnitureDesign > ListChain()
void Resize(int resolution)
BoundingBox[][] m_torchPointsByRotation
SubsystemTerrain m_subsystemTerrain
bool CompareChain(FurnitureDesign other)
BoundingBox[] GetTorchPoints(int rotation)
static Vector3 MirrorPoint(Vector3 p, int axis)
FurnitureGeometry m_geometry
Subdivision CreateBoundingBoxesHelper(Box box, int depth, byte[] precedingEmptySpaces)
FurnitureDesign(SubsystemTerrain subsystemTerrain)
bool Compare(FurnitureDesign other)
Point2 FindLargestSize(Cell[] surface, Point2 start, int value)
static List< List< FurnitureDesign > > ListChains(IEnumerable< FurnitureDesign > designs)
static bool IsValueTransparent(int value)
BoundingBox[] GetCollisionBoxes(int rotation)
static void EnsureMinSize(ref float min, ref float max, float minSize)
Box CalculateBox(Box box, byte[] precedingEmptySpaces)
void SetValues(int resolution, int[] values)
List< FurnitureDesign > CloneChain()
BoundingBox[] GetInteractionBoxes(int rotation)
void Rotate(int axis, int steps)
static string Get(string className, int key)
获取在当前语言类名键对应的字符串
static int ExtractContents(int value)
static int ExtractData(int value)
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
int Paint(SubsystemTerrain subsystemTerrain, int value, int? color)
static BoundingBox Union(BoundingBox b1, BoundingBox b2)
int Width
定义 Box.cs:9
static Color White
static Matrix CreateTranslation(float x, float y, float z)
static Matrix CreateRotationY(float radians)
static readonly Point2 Zero
static readonly Point3 Zero
static Vector3 Transform(Vector3 v, Matrix m)
static Vector3 Max(Vector3 v, float f)
static Vector3 Min(Vector3 v, float f)
static int OppositeFace(int face)