Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
PlantsManager.cs
浏览该文件的文档.
1using Engine;
2
3namespace Game {
4 public static class PlantsManager {
5 public static List<TerrainBrush>[] m_treeBrushesByType;
6
7 public static int[] m_treeTrunksByType;
8
9 public static int[] m_treeLeavesByType;
10
11 static PlantsManager() {
12 m_treeBrushesByType = new List<TerrainBrush>[EnumUtils.GetEnumValues<TreeType>().Max() + 1];
13 m_treeTrunksByType = [9, 10, 11, 11, 255, 262];
17 14,
18 225,
21 ];
22 Random random = new(33);
23 m_treeBrushesByType[0] = [];
24 for (int i = 0; i < 16; i++) {
25 int[] array = [
26 5,
27 6,
28 7,
29 8,
30 9,
31 10,
32 11,
33 11,
34 12,
35 12,
36 13,
37 13,
38 14,
39 15,
40 16,
41 18
42 ];
43 int height4 = array[i];
44 int branchesCount = (int)MathUtils.Lerp(10f, 22f, i / 16f);
46 random,
49 height4,
50 branchesCount,
51 3,
52 delegate(int y, int _) {
53 float num7 = 0.4f;
54 if (y < 0.2f * height4) {
55 num7 = 0f;
56 }
57 else if (y >= 0.2f * height4
58 && y <= height4) {
59 num7 *= 1.5f;
60 }
61 return num7;
62 },
63 delegate(int y) {
64 if (y < height4 * 0.3f
65 || y > height4 * 0.9f) {
66 return 0f;
67 }
68 float num6 = y < height4 * 0.7f ? 0.5f * height4 : 0.35f * height4;
69 return random.Float(0.33f, 1f) * num6;
70 }
71 );
72 m_treeBrushesByType[0].Add(item);
73 }
74 m_treeBrushesByType[1] = [];
75 for (int j = 0; j < 16; j++) {
76 int[] array2 = [
77 4,
78 5,
79 6,
80 7,
81 7,
82 8,
83 8,
84 9,
85 9,
86 9,
87 10,
88 10,
89 10,
90 11,
91 11,
92 12
93 ];
94 int height3 = array2[j];
95 int branchesCount2 = (int)MathUtils.Lerp(0f, 20f, j / 16f);
97 random,
100 height3,
101 branchesCount2,
102 3,
103 delegate(int y, int _) {
104 float num5 = 0.66f;
105 if (y < height3 / 2 - 1) {
106 num5 = 0f;
107 }
108 else if (y > height3 / 2
109 && y <= height3) {
110 num5 *= 1.5f;
111 }
112 return num5;
113 },
114 y => y < height3 * 0.35f || y > height3 * 0.75f ? 0f : random.Float(0f, 0.33f * height3)
115 );
116 m_treeBrushesByType[1].Add(item2);
117 }
118 m_treeBrushesByType[2] = [];
119 for (int k = 0; k < 16; k++) {
120 int[] array3 = [
121 7,
122 8,
123 9,
124 10,
125 10,
126 11,
127 11,
128 12,
129 12,
130 13,
131 13,
132 14,
133 14,
134 15,
135 16,
136 17
137 ];
138 int height2 = array3[k];
139 int branchesCount3 = height2 * 3;
141 random,
144 height2,
145 branchesCount3,
146 3,
147 delegate(int y, int _) {
148 float num4 = MathUtils.Lerp(1.4f, 0.3f, y / (float)height2);
149 if (y < 3) {
150 num4 = 0f;
151 }
152 if (y % 2 == 0) {
153 num4 *= 0.3f;
154 }
155 return num4;
156 },
157 delegate(int y) {
158 if (y < 3
159 || y > height2 * 0.8f) {
160 return 0f;
161 }
162 return y % 2 == 0 ? 0f : MathUtils.Lerp(0.3f * height2, 0f, MathUtils.Saturate(y / (float)height2));
163 }
164 );
165 m_treeBrushesByType[2].Add(item3);
166 }
167 m_treeBrushesByType[3] = [];
168 for (int l = 0; l < 16; l++) {
169 int[] array4 = [
170 20,
171 21,
172 22,
173 23,
174 24,
175 24,
176 25,
177 25,
178 26,
179 26,
180 27,
181 27,
182 28,
183 28,
184 29,
185 30,
186 31,
187 32
188 ];
189 int height = array4[l];
190 int branchesCount4 = height * 3;
191 float startHeight = (0.3f + l % 4 * 0.05f) * height;
193 random,
194 GetTreeTrunkValue(TreeType.TallSpruce),
195 GetTreeLeavesValue(TreeType.TallSpruce),
196 height,
197 branchesCount4,
198 3,
199 delegate(int y, int _) {
200 float num2 = MathUtils.Saturate(y / (float)height);
201 float num3 = MathUtils.Lerp(1.5f, 0f, MathUtils.Saturate((num2 - 0.6f) / 0.4f));
202 if (y < startHeight) {
203 num3 = 0f;
204 }
205 if (y % 3 != 0
206 && y < height - 4) {
207 num3 *= 0.2f;
208 }
209 return num3;
210 },
211 delegate(int y) {
212 float num = MathUtils.Saturate(y / (float)height);
213 if (y % 3 != 0) {
214 return 0f;
215 }
216 return y < startHeight
217 ? !(y < startHeight - 4f) ? 0.1f * height : 0f
218 : MathUtils.Lerp(0.18f * height, 0f, MathUtils.Saturate((num - 0.6f) / 0.4f));
219 }
220 );
221 m_treeBrushesByType[3].Add(item4);
222 }
223 m_treeBrushesByType[4] = [];
224 for (int m = 0; m < 16; m++) {
225 m_treeBrushesByType[4].Add(CreateMimosaBrush(random, MathUtils.Lerp(6f, 9f, m / 15f)));
226 }
227 m_treeBrushesByType[5] = [];
228 for (int n = 0; n < 16; n++) {
229 int[] array5 = [
230 10,
231 11,
232 11,
233 12,
234 12,
235 13,
236 13,
237 13,
238 14,
239 14,
240 14,
241 15,
242 15,
243 16,
244 16,
245 17,
246 17
247 ];
248 int height5 = array5[n];
249 int branchesCount5 = height5 * 3;
251 random,
254 height5,
255 branchesCount5,
256 2,
257 delegate(int y, int round) {
258 int num8 = height5 < 14 ? 1 : 2;
259 if (y < num8) {
260 return 0f;
261 }
262 if (round == 0) {
263 return 1f;
264 }
265 if (y == num8) {
266 return 0f;
267 }
268 return y == num8 + 1 ? 0.5f : MathUtils.LinearStep(height5 - 1, num8 + 2, y);
269 },
270 _ => 0f
271 );
272 m_treeBrushesByType[5].Add(item5);
273 }
274 }
275
276 public static int GetTreeTrunkValue(TreeType treeType) => m_treeTrunksByType[(int)treeType];
277
278 public static int GetTreeLeavesValue(TreeType treeType) => m_treeLeavesByType[(int)treeType];
279
280 public static ReadOnlyList<TerrainBrush> GetTreeBrushes(TreeType treeType) => new(m_treeBrushesByType[(int)treeType]);
281
282 public static int GenerateRandomPlantValue(Random random, int groundValue, int temperature, int humidity, int y) {
283 switch (Terrain.ExtractContents(groundValue)) {
284 case 2:
285 case 8:
286 if (humidity >= 6) {
287 if (!(random.Float(0f, 1f) < humidity / 60f)) {
288 break;
289 }
290 int result = Terrain.MakeBlockValue(19, 0, TallGrassBlock.SetIsSmall(0, false));
291 if (!SubsystemWeather.IsPlaceFrozen(temperature, y)) {
292 float num = random.Float(0f, 1f);
293 if (num < 0.04f) {
294 result = Terrain.MakeBlockValue(20);
295 }
296 else if (num < 0.07f) {
297 result = Terrain.MakeBlockValue(24);
298 }
299 else if (num < 0.09f) {
300 result = Terrain.MakeBlockValue(25);
301 }
302 else if (num < 0.17f) {
303 result = Terrain.MakeBlockValue(174, 0, RyeBlock.SetIsWild(RyeBlock.SetSize(0, 7), true));
304 }
305 else if (num < 0.19f) {
306 result = Terrain.MakeBlockValue(204, 0, CottonBlock.SetIsWild(CottonBlock.SetSize(0, 2), true));
307 }
308 }
309 return result;
310 }
311 if (random.Float(0f, 1f) < 0.025f) {
312 if (random.Float(0f, 1f) < 0.2f) {
313 return Terrain.MakeBlockValue(99, 0, 0);
314 }
315 return Terrain.MakeBlockValue(28, 0, 0);
316 }
317 break;
318 case 7:
319 if (humidity < 8
320 && random.Float(0f, 1f) < 0.01f) {
321 if (random.Float(0f, 1f) < 0.05f) {
322 return Terrain.MakeBlockValue(99, 0, 0);
323 }
324 return Terrain.MakeBlockValue(28, 0, 0);
325 }
326 break;
327 }
328 return 0;
329 }
330
331 public static TreeType? GenerateRandomTreeType(Random random, int temperature, int humidity, int y, float densityMultiplier = 1f) {
332 TreeType? result = null;
333 float num = random.Float() * CalculateTreeProbability(TreeType.Oak, temperature, humidity, y);
334 float num2 = random.Float() * CalculateTreeProbability(TreeType.Birch, temperature, humidity, y);
335 float num3 = random.Float() * CalculateTreeProbability(TreeType.Spruce, temperature, humidity, y);
336 float num4 = random.Float() * CalculateTreeProbability(TreeType.TallSpruce, temperature, humidity, y);
337 float num5 = random.Float() * CalculateTreeProbability(TreeType.Mimosa, temperature, humidity, y);
338 float num7 = random.Float() * CalculateTreeProbability(TreeType.Poplar, temperature, humidity, y);
339 float num6 = MathUtils.Max(MathUtils.Max(num, num2, num3, num4), num5, num7);
340 if (num6 > 0f) {
341 if (num6 == num) {
342 result = TreeType.Oak;
343 }
344 if (num6 == num2) {
345 result = TreeType.Birch;
346 }
347 if (num6 == num3) {
348 result = TreeType.Spruce;
349 }
350 if (num6 == num4) {
351 result = TreeType.TallSpruce;
352 }
353 if (num6 == num5) {
354 result = TreeType.Mimosa;
355 }
356 if (num6 == num7) {
357 result = TreeType.Poplar;
358 }
359 }
360 if (result.HasValue
361 && random.Bool(densityMultiplier * CalculateTreeDensity(result.Value, temperature, humidity, y))) {
362 return result;
363 }
364 return null;
365 }
366
367 public static float CalculateTreeDensity(TreeType treeType, int temperature, int humidity, int y) {
368 switch (treeType) {
369 case TreeType.Oak: return RangeProbability(humidity, 4f, 15f, 15f, 15f);
370 case TreeType.Birch: return RangeProbability(humidity, 4f, 15f, 15f, 15f);
371 case TreeType.Spruce: return RangeProbability(humidity, 4f, 15f, 15f, 15f);
372 case TreeType.TallSpruce: return RangeProbability(humidity, 4f, 15f, 15f, 15f);
373 case TreeType.Mimosa: return 0.04f;
374 case TreeType.Poplar:
375 return RangeProbability(temperature, 4f, 8f, 10f, 15f)
376 * RangeProbability(humidity, 3f, 15f, 15f, 15f)
377 * RangeProbability(y, 0f, 0f, 85f, 92f);
378 default: return 0f;
379 }
380 }
381
382 public static float CalculateTreeProbability(TreeType treeType, int temperature, int humidity, int y) {
383 switch (treeType) {
384 case TreeType.Oak:
385 return RangeProbability(temperature, 4f, 10f, 15f, 15f)
386 * RangeProbability(humidity, 6f, 8f, 15f, 15f)
387 * RangeProbability(y, 0f, 0f, 82f, 87f);
388 case TreeType.Birch:
389 return RangeProbability(temperature, 5f, 9f, 11f, 15f)
390 * RangeProbability(humidity, 3f, 15f, 15f, 15f)
391 * RangeProbability(y, 0f, 0f, 82f, 87f);
392 case TreeType.Spruce: return RangeProbability(temperature, 0f, 0f, 6f, 10f) * RangeProbability(humidity, 3f, 10f, 11f, 12f);
393 case TreeType.TallSpruce:
394 return 0.25f
395 * RangeProbability(temperature, 0f, 0f, 6f, 10f)
396 * RangeProbability(humidity, 9f, 11f, 15f, 15f)
397 * RangeProbability(y, 0f, 0f, 95f, 100f);
398 case TreeType.Mimosa: return RangeProbability(temperature, 2f, 4f, 12f, 14f) * RangeProbability(humidity, 0f, 0f, 4f, 6f);
399 case TreeType.Poplar:
400 return RangeProbability(temperature, 4f, 8f, 12f, 15f)
401 * RangeProbability(humidity, 3f, 15f, 15f, 15f)
402 * RangeProbability(y, 0f, 0f, 85f, 92f);
403 default: return 0f;
404 }
405 }
406
407 public static float RangeProbability(float v, float a, float b, float c, float d) {
408 if (v < a) {
409 return 0f;
410 }
411 if (v < b) {
412 return (v - a) / (b - a);
413 }
414 if (v <= c) {
415 return 1f;
416 }
417 if (v <= d) {
418 return 1f - (v - c) / (d - c);
419 }
420 return 0f;
421 }
422
423 public static TerrainBrush CreateTreeBrush(Random random,
424 int woodIndex,
425 int leavesIndex,
426 int height,
427 int branchesCount,
428 int leavesRounds,
429 Func<int, int, float> leavesProbability,
430 Func<int, float> branchesLength) {
431 TerrainBrush terrainBrush = new();
432 terrainBrush.AddRay(
433 0,
434 -1,
435 0,
436 0,
437 height,
438 0,
439 1,
440 1,
441 1,
442 woodIndex
443 );
444 for (int i = 0; i < branchesCount; i++) {
445 int x = 0;
446 int num = random.Int(0, height);
447 int z = 0;
448 float s = branchesLength(num);
449 Vector3 vector = Vector3.Normalize(new Vector3(random.Float(-1f, 1f), random.Float(0f, 0.33f), random.Float(-1f, 1f))) * s;
450 int x2 = (int)MathF.Round(vector.X);
451 int y = num + (int)MathF.Round(vector.Y);
452 int z2 = (int)MathF.Round(vector.Z);
453 int cutFace = 0;
454 if (MathF.Abs(vector.X) == MathUtils.Max(MathF.Abs(vector.X), MathF.Abs(vector.Y), MathF.Abs(vector.Z))) {
455 cutFace = 1;
456 }
457 else if (MathF.Abs(vector.Y) == MathUtils.Max(MathF.Abs(vector.X), MathF.Abs(vector.Y), MathF.Abs(vector.Z))) {
458 cutFace = 4;
459 }
460 terrainBrush.AddRay(
461 x,
462 num,
463 z,
464 x2,
465 y,
466 z2,
467 1,
468 1,
469 1,
470 (Func<int?, int?>)(v => v.HasValue ? null : new int?(Terrain.MakeBlockValue(woodIndex, 0, WoodBlock.SetCutFace(0, cutFace))))
471 );
472 }
473 for (int j = 0; j < leavesRounds; j++) {
474 terrainBrush.CalculateBounds(out Point3 min, out Point3 max);
475 for (int k = min.X - 1; k <= max.X + 1; k++) {
476 for (int l = min.Z - 1; l <= max.Z + 1; l++) {
477 for (int m = 1; m <= max.Y + 1; m++) {
478 float num2 = leavesProbability(m, j);
479 if (random.Float(0f, 1f) < num2
480 && !terrainBrush.GetValue(k, m, l).HasValue
481 && (terrainBrush.CountNonDiagonalNeighbors(k, m, l, leavesIndex) != 0
482 || terrainBrush.CountNonDiagonalNeighbors(
483 k,
484 m,
485 l,
486 (Func<int?, int>)(v => v.HasValue && Terrain.ExtractContents(v.Value) == woodIndex ? 1 : 0)
487 )
488 != 0)) {
489 terrainBrush.AddCell(k, m, l, 0);
490 }
491 }
492 }
493 }
494 terrainBrush.Replace(0, leavesIndex);
495 }
496 terrainBrush.AddCell(0, height, 0, leavesIndex);
497 terrainBrush.Compile();
498 return terrainBrush;
499 }
500
501 public static TerrainBrush CreateMimosaBrush(Random random, float size) {
502 TerrainBrush terrainBrush = new();
503 int value = m_treeTrunksByType[4];
504 int value2 = m_treeLeavesByType[4];
505 terrainBrush.AddRay(
506 0,
507 -1,
508 0,
509 0,
510 0,
511 0,
512 1,
513 1,
514 1,
515 value
516 );
517 List<Point3> list = new();
518 float num = random.Float(0f, (float)Math.PI * 2f);
519 for (int i = 0; i < 3; i++) {
520 float radians = num + i * MathUtils.DegToRad(120f);
521 Vector3 v = Vector3.Transform(Vector3.Normalize(new Vector3(1f, random.Float(1f, 1.5f), 0f)), Matrix.CreateRotationY(radians));
522 int num2 = random.Int((int)(0.7f * size), (int)size);
523 Point3 p = new(0, 0, 0);
524 Point3 item = new(Vector3.Round(new Vector3(p) + v * num2));
525 terrainBrush.AddRay(
526 p.X,
527 p.Y,
528 p.Z,
529 item.X,
530 item.Y,
531 item.Z,
532 1,
533 1,
534 1,
535 value
536 );
537 list.Add(item);
538 }
539 foreach (Point3 item2 in list) {
540 float num3 = random.Float(0.3f * size, 0.45f * size);
541 int num4 = (int)MathF.Ceiling(num3);
542 for (int j = item2.X - num4; j <= item2.X + num4; j++) {
543 for (int k = item2.Y - num4; k <= item2.Y + num4; k++) {
544 for (int l = item2.Z - num4; l <= item2.Z + num4; l++) {
545 int num5 = Math.Abs(j - item2.X) + Math.Abs(k - item2.Y) + Math.Abs(l - item2.Z);
546 float num6 = ((new Vector3(j, k, l) - new Vector3(item2)) * new Vector3(1f, 1.7f, 1f)).Length();
547 if (num6 <= num3
548 && (num3 - num6 > 1f || num5 <= 2 || random.Bool(0.7f))
549 && !terrainBrush.GetValue(j, k, l).HasValue) {
550 terrainBrush.AddCell(j, k, l, value2);
551 }
552 }
553 }
554 }
555 }
556 terrainBrush.Compile();
557 return terrainBrush;
558 }
559 }
560}
Engine.Vector3 Vector3
static float Saturate(float x)
static int Max(int x1, int x2)
static float DegToRad(float degrees)
static float Lerp(float x1, float x2, float f)
static float LinearStep(float zero, float one, float f)
static int SetSize(int data, int size)
static int SetIsWild(int data, bool isWild)
static int SetSeason(int data, Season season)
static IList< int > GetEnumValues(Type type)
static int GenerateRandomPlantValue(Random random, int groundValue, int temperature, int humidity, int y)
static List< TerrainBrush >[] m_treeBrushesByType
static float RangeProbability(float v, float a, float b, float c, float d)
static int[] m_treeLeavesByType
static ReadOnlyList< TerrainBrush > GetTreeBrushes(TreeType treeType)
static float CalculateTreeDensity(TreeType treeType, int temperature, int humidity, int y)
static TerrainBrush CreateTreeBrush(Random random, int woodIndex, int leavesIndex, int height, int branchesCount, int leavesRounds, Func< int, int, float > leavesProbability, Func< int, float > branchesLength)
static int[] m_treeTrunksByType
static ? TreeType GenerateRandomTreeType(Random random, int temperature, int humidity, int y, float densityMultiplier=1f)
static float CalculateTreeProbability(TreeType treeType, int temperature, int humidity, int y)
static TerrainBrush CreateMimosaBrush(Random random, float size)
static int GetTreeTrunkValue(TreeType treeType)
static int GetTreeLeavesValue(TreeType treeType)
float Float()
static int SetIsWild(int data, bool isWild)
static int SetSize(int data, int size)
static Func< int, int, bool > IsPlaceFrozen
static int SetIsSmall(int data, bool isSmall)
void CalculateBounds(out Point3 min, out Point3 max)
void Replace(int oldValue, int newValue)
int CountNonDiagonalNeighbors(int x, int y, int z, Counter counter)
void AddCell(int x, int y, int z, Brush brush)
void AddRay(int x1, int y1, int z1, int x2, int y2, int z2, int sizeX, int sizeY, int sizeZ, Brush brush)
int? GetValue(Point3 p)
static int ExtractContents(int value)
static int MakeBlockValue(int contents)
static int SetCutFace(int data, int cutFace)
static Matrix CreateRotationY(float radians)
static Vector3 Round(Vector3 v)
static Vector3 Transform(Vector3 v, Matrix m)
static Vector3 Normalize(Vector3 v)