Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemSignBlockBehavior.cs
浏览该文件的文档.
1using System.Globalization;
2using Engine;
4using Engine.Media;
6
7namespace Game {
9 public class TextData {
10 public Point3 Point;
11
13
14 public string[] Lines = [string.Empty, string.Empty, string.Empty, string.Empty];
15
17
18 public string Url = string.Empty;
19
20 public int? TextureLocation;
21
22 public float UsedTextureWidth;
23
24 public float UsedTextureHeight;
25
26 public float Distance;
27
29
30 public int Light;
31 }
32
33 public const float m_maxVisibilityDistanceSqr = 400f;
34
35 public const float m_minUpdateDistance = 2f;
36
37 public const int m_textWidth = 128;
38
39 public const int m_textHeight = 32;
40
41 public static int m_maxTexts = 32;
42
43 public float m_fontScale = 1f;
44
46
48
50
51 public Dictionary<Point3, TextData> m_textsByPoint = [];
52
53 public Dictionary<MovingBlock, TextData> m_textsByMovingBlock = new();
54
55 public List<RenderTarget2D> m_texturesByPoint = [];
56
58
59 public List<TextData> m_nearTexts = [];
60
62
64
65 public List<Vector3> m_lastUpdatePositions = [];
66
68
70
71 public bool ShowSignsTexture;
72
73 public bool CopySignsText;
74
75 public static int[] m_drawOrders = [50];
76
77 public override int[] HandledBlocks => [23, 97, 98, 210, 211];
78
80
81 public int[] DrawOrders => m_drawOrders;
82
83 public SignData GetSignData(Point3 point) {
84 if (m_textsByPoint.TryGetValue(point, out TextData value)) {
85 return new SignData { Lines = value.Lines.ToArray(), Colors = value.Colors.ToArray(), Url = value.Url };
86 }
87 return null;
88 }
89
90 public void SetSignData(Point3 point, string[] lines, Color[] colors, string url, MovingBlock movingBlock = null) {
91 TextData textData = new() { Point = point };
92 for (int i = 0; i < 4; i++) {
93 textData.Lines[i] = lines[i];
94 textData.Colors[i] = colors[i];
95 }
96 textData.Url = url;
97 textData.MovingBlock = movingBlock;
98 if (!MovingBlock.IsNullOrStopped(movingBlock)) {
99 m_textsByMovingBlock[movingBlock] = textData;
100 }
101 else {
102 m_textsByPoint[point] = textData;
103 }
104 m_lastUpdatePositions.Clear();
105 }
106
107 public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) {
108 int cellValueFast = SubsystemTerrain.Terrain.GetCellValueFast(x, y, z);
109 int num = Terrain.ExtractContents(cellValueFast);
110 int data = Terrain.ExtractData(cellValueFast);
111 Block block = BlocksManager.Blocks[num];
112 if (block is AttachedSignBlock) {
114 int x2 = x - point.X;
115 int y2 = y - point.Y;
116 int z2 = z - point.Z;
117 int cellValue = SubsystemTerrain.Terrain.GetCellValue(x2, y2, z2);
118 int cellContents = Terrain.ExtractContents(cellValue);
119 if (!BlocksManager.Blocks[cellContents].IsCollidable_(cellValue)) {
120 SubsystemTerrain.DestroyCell(
121 0,
122 x,
123 y,
124 z,
125 0,
126 false,
127 false
128 );
129 }
130 }
131 else if (block is PostedSignBlock) {
132 int num2 = PostedSignBlock.GetHanging(data)
133 ? SubsystemTerrain.Terrain.GetCellValue(x, y + 1, z)
134 : SubsystemTerrain.Terrain.GetCellValue(x, y - 1, z);
136 SubsystemTerrain.DestroyCell(
137 0,
138 x,
139 y,
140 z,
141 0,
142 false,
143 false
144 );
145 }
146 }
147 }
148
149 public override bool OnInteract(TerrainRaycastResult raycastResult, ComponentMiner componentMiner) {
150 AudioManager.PlaySound("Audio/UI/ButtonClick", 1f, 0f, 0f);
151 Point3 point = new(raycastResult.CellFace.X, raycastResult.CellFace.Y, raycastResult.CellFace.Z);
152 if (m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Adventure) {
153 SignData signData = GetSignData(point);
154 if (signData != null
155 && !string.IsNullOrEmpty(signData.Url)) {
157 }
158 }
159 else if (componentMiner.ComponentPlayer != null) {
160 DialogsManager.ShowDialog(componentMiner.ComponentPlayer.GuiWidget, new EditSignDialog(this, point));
161 }
162 return true;
163 }
164
165 public override void OnBlockStartMoving(int value, int newValue, int x, int y, int z, MovingBlock movingBlock) {
166 Point3 key = new(x, y, z);
167 bool valueGotten = m_textsByPoint.TryGetValue(key, out TextData textData);
168 m_textsByPoint.Remove(key);
169 if (valueGotten) {
170 m_textsByMovingBlock.Add(movingBlock, textData);
171 textData.MovingBlock = movingBlock;
172 }
173 m_lastUpdatePositions.Clear();
174 }
175
176 public override void OnBlockStopMoving(int value, int oldValue, int x, int y, int z, MovingBlock movingBlock) {
177 bool valueGotten = m_textsByMovingBlock.TryGetValue(movingBlock, out TextData textData);
178 m_textsByMovingBlock.Remove(movingBlock);
179 if (valueGotten) {
180 m_textsByPoint[new Point3(x, y, z)] = textData;
181 textData.Point = new Point3(x, y, z);
182 textData.MovingBlock = null;
183 }
184 m_lastUpdatePositions.Clear();
185 }
186
187 public override void OnBlockRemoved(int value, int newValue, int x, int y, int z) {
188 Point3 key = new(x, y, z);
189 m_textsByPoint.Remove(key);
190 m_lastUpdatePositions.Clear();
191 }
192
193 public virtual void Update(float dt) {
195 }
196
197 public virtual void Draw(Camera camera, int drawOrder) {
198 DrawSigns(camera);
199 }
200
201 public override void Load(ValuesDictionary valuesDictionary) {
202 base.Load(valuesDictionary);
203 m_subsystemViews = Project.FindSubsystem<SubsystemGameWidgets>(true);
204 m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
205 m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(true);
207 foreach (ValuesDictionary value11 in valuesDictionary.GetValue<ValuesDictionary>("Texts").Values) {
208 Point3 value = value11.GetValue<Point3>("Point");
210 string value2 = value11.GetValue("Line1", string.Empty);
211 string value3 = value11.GetValue("Line2", string.Empty);
212 string value4 = value11.GetValue("Line3", string.Empty);
213 string value5 = value11.GetValue("Line4", string.Empty);
214 Color value6 = value11.GetValue("Color1", Color.Black);
215 Color value7 = value11.GetValue("Color2", Color.Black);
216 Color value8 = value11.GetValue("Color3", Color.Black);
217 Color value9 = value11.GetValue("Color4", Color.Black);
218 string value10 = value11.GetValue("Url", string.Empty);
219 SetSignData(value, [value2, value3, value4, value5], [value6, value7, value8, value9], value10, movingBlock);
220 }
221 Display.DeviceReset += Display_DeviceReset;
222 }
223
224 public virtual void SaveTextData(TextData textData, ValuesDictionary valuesDictionary) {
225 valuesDictionary.SetValue("Point", textData.Point);
226 textData.MovingBlock?.SetValuesDicionary(valuesDictionary);
227 if (!string.IsNullOrEmpty(textData.Lines[0])) {
228 valuesDictionary.SetValue("Line1", textData.Lines[0]);
229 }
230 if (!string.IsNullOrEmpty(textData.Lines[1])) {
231 valuesDictionary.SetValue("Line2", textData.Lines[1]);
232 }
233 if (!string.IsNullOrEmpty(textData.Lines[2])) {
234 valuesDictionary.SetValue("Line3", textData.Lines[2]);
235 }
236 if (!string.IsNullOrEmpty(textData.Lines[3])) {
237 valuesDictionary.SetValue("Line4", textData.Lines[3]);
238 }
239 if (textData.Colors[0] != Color.Black) {
240 valuesDictionary.SetValue("Color1", textData.Colors[0]);
241 }
242 if (textData.Colors[1] != Color.Black) {
243 valuesDictionary.SetValue("Color2", textData.Colors[1]);
244 }
245 if (textData.Colors[2] != Color.Black) {
246 valuesDictionary.SetValue("Color3", textData.Colors[2]);
247 }
248 if (textData.Colors[3] != Color.Black) {
249 valuesDictionary.SetValue("Color4", textData.Colors[3]);
250 }
251 if (!string.IsNullOrEmpty(textData.Url)) {
252 valuesDictionary.SetValue("Url", textData.Url);
253 }
254 }
255
256 public override void Save(ValuesDictionary valuesDictionary) {
257 int num = 0;
258 ValuesDictionary valuesDictionary2 = new();
259 valuesDictionary.SetValue("Texts", valuesDictionary2);
260 foreach (TextData value in m_textsByPoint.Values) {
262 continue;
263 }
264 ValuesDictionary valuesDictionary3 = new();
265 SaveTextData(value, valuesDictionary3);
266 valuesDictionary2.SetValue(num++.ToString(CultureInfo.InvariantCulture), valuesDictionary3);
267 }
268 foreach (TextData textData in m_textsByMovingBlock.Values) {
269 ValuesDictionary valuesDictionary3 = new();
270 SaveTextData(textData, valuesDictionary3);
271 valuesDictionary2.SetValue(num++.ToString(CultureInfo.InvariantCulture), valuesDictionary3);
272 }
273 }
274
275 public override void Dispose() {
276 Utilities.Dispose(ref m_renderTarget);
277 Display.DeviceReset -= Display_DeviceReset;
278 }
279
280 public void Display_DeviceReset() {
282 }
283
284 public void CreateRenderTarget() {
285 int eachSignHeight = (int)(m_font.GlyphHeight * m_fontScale * 4);
286 if (Display.MaxTextureSize < eachSignHeight * 32) {
287 m_maxTexts = Display.MaxTextureSize / eachSignHeight;
288 }
290 (int)(m_font.GlyphHeight * 16 * m_fontScale),
291 eachSignHeight * m_maxTexts,
292 1,
293 ColorFormat.Rgba8888,
294 DepthFormat.None
295 );
296 }
297
299 m_lastUpdatePositions.Clear();
300 for (int i = 0; i < m_textureLocations.Length; i++) {
301 m_textureLocations[i] = null;
302 }
303 foreach (TextData value in m_textsByPoint.Values) {
304 value.TextureLocation = null;
305 }
306 }
307
308 public void RenderText(FontBatch2D fontBatch, FlatBatch2D flatBatch, TextData textData) {
309 if (!textData.TextureLocation.HasValue) {
310 return;
311 }
312 List<string> list = [];
313 List<Color> list2 = [];
314 for (int i = 0; i < textData.Lines.Length; i++) {
315 if (!string.IsNullOrEmpty(textData.Lines[i])) {
316 list.Add(textData.Lines[i].Replace("\\", "").ToUpper());
317 list2.Add(textData.Colors[i]);
318 }
319 }
320 if (list.Count > 0) {
321 float num = list.Max(l => l.Length) * m_font.GlyphHeight * m_fontScale;
322 float num2 = list.Count * m_font.GlyphHeight * m_fontScale;
323 float num3 = 4f;
324 float num4;
325 float num5;
326 if (num / num2 < num3) {
327 num4 = num2 * num3;
328 num5 = num2;
329 }
330 else {
331 num4 = num;
332 num5 = num / num3;
333 }
334 bool flag = !string.IsNullOrEmpty(textData.Url);
335 for (int j = 0; j < list.Count; j++) {
336 fontBatch.QueueText(
337 position: new Vector2(
338 num4 / 2f,
339 j * m_font.GlyphHeight * m_fontScale
340 + textData.TextureLocation.Value * (4f * m_font.GlyphHeight * m_fontScale)
341 + (num5 - num2) / 2f
342 ),
343 text: list[j],
344 depth: 0f,
345 color: flag ? new Color(0, 0, 64) : list2[j],
346 anchor: TextAnchor.HorizontalCenter,
347 scale: new Vector2(1f / m_font.Scale * m_fontScale),
348 spacing: Vector2.Zero
349 );
350 }
351 textData.UsedTextureWidth = num4;
352 textData.UsedTextureHeight = num5;
353 }
354 }
355
356 public virtual void UpdateRenderTarget() {
357 bool flag = false;
358 foreach (GameWidget gameWidget in m_subsystemViews.GameWidgets) {
359 bool flag2 = false;
360 foreach (Vector3 lastUpdatePosition in m_lastUpdatePositions) {
361 if (Vector3.DistanceSquared(gameWidget.ActiveCamera.ViewPosition, lastUpdatePosition) < 4f) {
362 flag2 = true;
363 break;
364 }
365 }
366 if (!flag2) {
367 flag = true;
368 break;
369 }
370 }
371 if (!flag) {
372 return;
373 }
374 m_lastUpdatePositions.Clear();
375 m_lastUpdatePositions.AddRange(m_subsystemViews.GameWidgets.Select(v => v.ActiveCamera.ViewPosition));
376 m_nearTexts.Clear();
377 foreach (TextData value in m_textsByPoint.Values) {
378 Point3 point = value.Point;
379 float num = m_subsystemViews.CalculateSquaredDistanceFromNearestView(new Vector3(point));
380 if (num <= m_maxVisibilityDistanceSqr) {
381 value.Distance = num;
382 m_nearTexts.Add(value);
383 }
384 }
385 foreach (MovingBlock movingBlock in m_textsByMovingBlock.Keys) {
386 Vector3 position = movingBlock.Position;
387 TextData value = m_textsByMovingBlock[movingBlock];
388 float num = m_subsystemViews.CalculateSquaredDistanceFromNearestView(position);
389 if (num <= m_maxVisibilityDistanceSqr) {
390 value.Distance = num;
391 m_nearTexts.Add(value);
392 }
393 }
394 m_nearTexts.Sort((d1, d2) => Comparer<float>.Default.Compare(d1.Distance, d2.Distance));
395 if (m_nearTexts.Count > m_maxTexts) {
396 m_nearTexts.RemoveRange(m_maxTexts, m_nearTexts.Count - m_maxTexts);
397 }
398 foreach (TextData nearText in m_nearTexts) {
399 nearText.ToBeRenderedFrame = Time.FrameIndex;
400 }
401 bool flag3 = false;
402 for (int i = 0; i < MathUtils.Min(m_nearTexts.Count, m_maxTexts); i++) {
403 TextData textData = m_nearTexts[i];
404 if (textData.TextureLocation.HasValue) {
405 continue;
406 }
407 int num2 = m_textureLocations.FirstIndex(d => d == null);
408 if (num2 < 0
409 || num2 >= m_maxTexts) {
410 num2 = m_textureLocations.FirstIndex(d => d.ToBeRenderedFrame != Time.FrameIndex);
411 }
412 if (num2 >= 0) {
413 TextData textData2 = m_textureLocations[num2];
414 if (textData2 != null) {
415 textData2.TextureLocation = null;
416 m_textureLocations[num2] = null;
417 }
418 m_textureLocations[num2] = textData;
419 textData.TextureLocation = num2;
420 flag3 = true;
421 }
422 }
423 if (!flag3) {
424 return;
425 }
426 RenderTarget2D renderTarget = Display.RenderTarget;
427 Display.RenderTarget = m_renderTarget;
428 try {
431 FontBatch2D fontBatch = m_primitivesRenderer2D.FontBatch(
432 m_font,
433 1,
435 null,
438 );
439 for (int j = 0; j < m_maxTexts; j++) {
440 TextData textData3 = m_textureLocations[j];
441 if (textData3 != null) {
442 RenderText(fontBatch, flatBatch, textData3);
443 }
444 }
446 }
447 finally {
448 Display.RenderTarget = renderTarget;
449 }
450 }
451
452 public virtual void DrawSigns(Camera camera) {
453 if (m_nearTexts.Count <= 0) {
454 return;
455 }
456 TexturedBatch3D texturedBatch3D = m_primitivesRenderer3D.TexturedBatch(
458 false,
459 0,
462 null,
464 );
465 foreach (TextData nearText in m_nearTexts) {
466 if (!nearText.TextureLocation.HasValue) {
467 continue;
468 }
469 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(nearText.Point.X, nearText.Point.Y, nearText.Point.Z);
470 if (!MovingBlock.IsNullOrStopped(nearText.MovingBlock)) {
471 cellValue = nearText.MovingBlock.Value;
472 }
473 int num = Terrain.ExtractContents(cellValue);
474 if (!(BlocksManager.Blocks[num] is SignBlock signBlock)) {
475 continue;
476 }
477 int data = Terrain.ExtractData(cellValue);
478 BlockMesh signSurfaceBlockMesh = signBlock.GetSignSurfaceBlockMesh(data);
479 if (signSurfaceBlockMesh != null) {
480 TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(nearText.Point.X, nearText.Point.Z);
481 if (chunkAtCell != null
482 && chunkAtCell.State >= TerrainChunkState.InvalidVertices1) {
483 nearText.Light = Terrain.ExtractLight(cellValue);
484 }
485 float num2 = LightingManager.LightIntensityByLightValue[nearText.Light];
486 Color color = new(num2, num2, num2);
487 float x = 0f;
488 float x2 = nearText.UsedTextureWidth / (m_font.GlyphHeight * 16f * m_fontScale);
489 float x3 = (float)nearText.TextureLocation.Value / m_maxTexts;
490 float x4 = (nearText.TextureLocation.Value + nearText.UsedTextureHeight / (m_font.GlyphHeight * 4f * m_fontScale)) / m_maxTexts;
491 Vector3 signSurfaceNormal = signBlock.GetSignSurfaceNormal(data);
492 Vector3 vector = new(nearText.Point.X, nearText.Point.Y, nearText.Point.Z);
493 if (!MovingBlock.IsNullOrStopped(nearText.MovingBlock)) {
494 vector = nearText.MovingBlock.Position;
495 }
496 float num3 = Vector3.Dot(camera.ViewPosition - (vector + new Vector3(0.5f)), signSurfaceNormal);
497 Vector3 vector2 = MathUtils.Max(0.01f * num3, 0.005f) * signSurfaceNormal;
498 for (int i = 0; i < signSurfaceBlockMesh.Indices.Count / 3; i++) {
499 BlockMeshVertex blockMeshVertex = signSurfaceBlockMesh.Vertices.Array[signSurfaceBlockMesh.Indices.Array[i * 3]];
500 BlockMeshVertex blockMeshVertex2 = signSurfaceBlockMesh.Vertices.Array[signSurfaceBlockMesh.Indices.Array[i * 3 + 1]];
501 BlockMeshVertex blockMeshVertex3 = signSurfaceBlockMesh.Vertices.Array[signSurfaceBlockMesh.Indices.Array[i * 3 + 2]];
502 Vector3 p = blockMeshVertex.Position + vector + vector2;
503 Vector3 p2 = blockMeshVertex2.Position + vector + vector2;
504 Vector3 p3 = blockMeshVertex3.Position + vector + vector2;
505 Vector2 textureCoordinates = blockMeshVertex.TextureCoordinates;
506 Vector2 textureCoordinates2 = blockMeshVertex2.TextureCoordinates;
507 Vector2 textureCoordinates3 = blockMeshVertex3.TextureCoordinates;
508 textureCoordinates.X = MathUtils.Lerp(x, x2, textureCoordinates.X);
509 textureCoordinates2.X = MathUtils.Lerp(x, x2, textureCoordinates2.X);
510 textureCoordinates3.X = MathUtils.Lerp(x, x2, textureCoordinates3.X);
511 textureCoordinates.Y = MathUtils.Lerp(x3, x4, textureCoordinates.Y);
512 textureCoordinates2.Y = MathUtils.Lerp(x3, x4, textureCoordinates2.Y);
513 textureCoordinates3.Y = MathUtils.Lerp(x3, x4, textureCoordinates3.Y);
514 texturedBatch3D.QueueTriangle(
515 p,
516 p2,
517 p3,
518 textureCoordinates,
519 textureCoordinates2,
520 textureCoordinates3,
521 color
522 );
523 }
524 }
525 }
526 m_primitivesRenderer3D.Flush(camera.ViewProjectionMatrix);
527 }
528 }
529}
Engine.Vector3 Vector3
static readonly BlendState Opaque
static readonly DepthStencilState None
static readonly DepthStencilState DepthRead
static void Clear(Vector4? color, float? depth=null, int? stencil=null)
static RenderTarget2D RenderTarget
void QueueText(string text, Vector2 position, float depth, Color color, TextAnchor anchor=TextAnchor.Default)
static readonly RasterizerState CullCounterClockwiseScissor
static int Min(int x1, int x2)
static int Max(int x1, int x2)
static float Lerp(float x1, float x2, float f)
static int FrameIndex
定义 Time.cs:26
static void PlaySound(string name, float volume, float pitch, float pan)
virtual bool IsCollidable_(int value)
DynamicArray< BlockMeshVertex > Vertices
DynamicArray< int > Indices
Vector3 ViewPosition
ComponentPlayer ComponentPlayer
static void ShowDialog(ContainerWidget parentWidget, Dialog dialog)
static BitmapFont BitmapFont
static readonly float[] LightIntensityByLightValue
static bool IsNullOrStopped(MovingBlock movingBlock)
void SetValuesDicionary(ValuesDictionary valuesDictionary, bool saveWhenStopped=false)
static MovingBlock LoadFromValuesDictionary(Project project, ValuesDictionary valuesDictionary, bool throwOnError=true, bool throwIfNotFound=false)
static bool GetHanging(int data)
override void OnBlockStopMoving(int value, int oldValue, int x, int y, int z, MovingBlock movingBlock)
void SetSignData(Point3 point, string[] lines, Color[] colors, string url, MovingBlock movingBlock=null)
override void Load(ValuesDictionary valuesDictionary)
virtual void Draw(Camera camera, int drawOrder)
virtual void SaveTextData(TextData textData, ValuesDictionary valuesDictionary)
void RenderText(FontBatch2D fontBatch, FlatBatch2D flatBatch, TextData textData)
Dictionary< MovingBlock, TextData > m_textsByMovingBlock
override void OnBlockRemoved(int value, int newValue, int x, int y, int z)
override void OnBlockStartMoving(int value, int newValue, int x, int y, int z, MovingBlock movingBlock)
override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ)
override bool OnInteract(TerrainRaycastResult raycastResult, ComponentMiner componentMiner)
override void Save(ValuesDictionary valuesDictionary)
Dictionary< Point3, TextData > m_textsByPoint
TerrainChunkState State
static int ExtractContents(int value)
static int ExtractLight(int value)
static int ExtractData(int value)
static void LaunchBrowser(string url)
ValuesDictionary ValuesDictionary
Camera ActiveCamera
static Color Transparent
定义 Color.cs:5
static Color Black
定义 Color.cs:7
static readonly Vector2 Zero
static float DistanceSquared(Vector3 v1, Vector3 v2)
static float Dot(Vector3 v1, Vector3 v2)
static Point3 FaceToPoint3(int face)