Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Pickable.cs
浏览该文件的文档.
1using Engine;
5
6namespace Game {
7 public class Pickable : WorldItem {
8 public int Count;
9
11
13
14 public bool SplashGenerated = true;
15
16 protected double m_timeWaitToAutoPick = 0.5;
17
18 protected float m_distanceToPick = 1f;
19
20 protected float m_distanceToFlyToTarget = 1.75f;
21
23 public virtual double TimeWaitToAutoPick => m_timeWaitToAutoPick;
24 public virtual float DistanceToPick => m_distanceToPick;
26
27 public bool IsExplosionProof = false;
28
29 #region 必选参数
30
31 public Func<Terrain> CurrnetTerrain;
32
33 public Func<float> CalcVisibilityRange;
34
35 public Func<DrawBlockEnvironmentData> DrawBlockEnvironmentData;
36
38
39 public Func<PrimitivesRenderer3D> PrimitivesRenderer;
40
41 #endregion
42
43 #region 可选
44
46
48
50
52
54 get {
55 if (m_subsystemPickables == null
56 && Project != null) {
58 }
60 }
61 }
62
64
66 get {
67 if (m_subsystemTerrain == null
68 && Project != null) {
70 }
71 return m_subsystemTerrain;
72 }
73 }
74
76
78 get {
79 if (m_subsystemExplosions == null
80 && Project != null) {
82 }
84 }
85 }
86
88
90 get {
91 if (m_subsystemMovingBlocks == null
92 && Project != null) {
94 }
96 }
97 }
98
99 #endregion
100
101 public override void Load(ValuesDictionary valuesDictionary) {
102 Value = valuesDictionary.GetValue<int>("Value");
103 Count = valuesDictionary.GetValue<int>("Count");
104 Position = valuesDictionary.GetValue<Vector3>("Position");
105 Velocity = valuesDictionary.GetValue<Vector3>("Velocity");
106 CreationTime = valuesDictionary.GetValue("CreationTime", 0.0);
107 if (valuesDictionary.ContainsKey("StuckMatrix")) {
108 StuckMatrix = valuesDictionary.GetValue<Matrix>("StuckMatrix");
109 }
110 int ownerEntityID = valuesDictionary.GetValue("OwnerID", 0);
111 if (ownerEntityID != 0
112 && Project != null) {
113 OwnerEntity = Project.FindEntity(ownerEntityID);
114 }
115 }
116
117 public virtual void InitializeData(Func<Terrain> terrain,
118 Func<DrawBlockEnvironmentData> drawBlockEnvironmentData,
119 Func<float> calcVisibilityRange,
120 Func<SubsystemSky.CalculateFogDelegate> calculateFog,
121 Func<PrimitivesRenderer3D> primitivesRenderer) {
122 CurrnetTerrain = terrain;
123 DrawBlockEnvironmentData = drawBlockEnvironmentData;
124 CalculateFog = calculateFog;
125 CalcVisibilityRange = calcVisibilityRange;
126 PrimitivesRenderer = primitivesRenderer;
127 }
128
129 public virtual void Initialize(int value, int count, Vector3 position, Vector3? velocity, Matrix? stuckMatrix, Entity owner) {
130 Value = value;
131 Count = count;
132 Position = position;
133 StuckMatrix = stuckMatrix;
134 OwnerEntity = owner;
135 if (velocity.HasValue) {
136 Velocity = velocity.Value;
137 }
138 else if (Terrain.ExtractContents(value) == 248) {
139 Vector2 vector = m_random.Vector2(1.5f, 2f);
140 Velocity = new Vector3(vector.X, 3f, vector.Y);
141 }
142 else {
143 Velocity = new Vector3(m_random.Float(-0.5f, 0.5f), m_random.Float(1f, 1.2f), m_random.Float(-0.5f, 0.5f));
144 }
145 }
146
147 protected TerrainRaycastResult?
148 WrappedRaycast(Vector3 start, Vector3 end, bool useInteractionBoxes, bool skipAirBlocks, Func<int, float, bool> action) =>
149 m_subsystemTerrain == null
150 ? SubsystemTerrain.Raycast(CurrnetTerrain(), start, end, useInteractionBoxes, skipAirBlocks, action)
151 : m_subsystemTerrain.Raycast(start, end, useInteractionBoxes, skipAirBlocks, action);
152
153 public virtual void Update(float dt) {
154 bool toRemove = UpdateTimeToRemove();
155 if (toRemove) {
156 ToRemove = true;
157 }
158 else {
159 TerrainChunk chunkAtCell = CurrnetTerrain().GetChunkAtCell(Terrain.ToCell(Position.X), Terrain.ToCell(Position.Z));
160 if (chunkAtCell != null
161 && chunkAtCell.State > TerrainChunkState.InvalidContents4) {
162 Vector3 positionAtdt = Position + Velocity * dt;
163 if (FlyToPosition.HasValue) {
165 }
166 else {
167 UpdateMovement(dt, ref positionAtdt);
168 }
169 Position = positionAtdt;
170 }
171 }
172 }
173
174 public virtual bool UpdateTimeToRemove() //更新移除逻辑
175 {
176 if (SubsystemPickables == null) {
177 return false;
178 }
179 float maxTimeExist;
180 if (MaxTimeExist.HasValue) {
181 maxTimeExist = MaxTimeExist.Value;
182 }
183 else {
185 string category = block.GetCategory(Value);
186 int remainPickables = SubsystemPickables.m_pickables.Count - SubsystemPickables.m_pickablesToRemove.Count;
187 maxTimeExist = category == "Terrain" ? remainPickables > 80 ? 60 : 120 :
188 category == "Plants" && block.GetNutritionalValue(Value) == 0f ? remainPickables > 80 ? 60 : 120 :
189 !(block is EggBlock) ? remainPickables > 80 ? 120 : 480 : 240f;
190 }
191 double timeExisted = SubsystemPickables.m_subsystemGameInfo.TotalElapsedGameTime - CreationTime;
192 if (timeExisted > maxTimeExist) {
193 return true;
194 }
195 return false;
196 }
197
198 public virtual void UpdateMovement(float dt, ref Vector3 positionAtdt) {
199 FluidBlock surfaceBlock = null;
200 float? surfaceHeight = null;
202 Vector2? vector2 = SubsystemPickables?.m_subsystemFluidBlockBehavior.CalculateFlowSpeed(
204 Terrain.ToCell(Position.Y + 0.1f),
206 out surfaceBlock,
207 out surfaceHeight
208 );
209 if (!StuckMatrix.HasValue) {
210 TerrainRaycastResult? terrainRaycastResult = WrappedRaycast(
211 Position,
212 positionAtdt,
213 false,
214 true,
215 (value, _) => BlocksManager.Blocks[Terrain.ExtractContents(value)].IsCollidable_(value)
216 );
217 MovingBlocksRaycastResult? movingBlocksRaycastResult = SubsystemMovingBlocks?.Raycast(
218 Position + new Vector3(0f, 0.25f, 0f),
219 positionAtdt + new Vector3(0f, 0.25f, 0f),
220 true,
221 (value, _) => BlocksManager.Blocks[Terrain.ExtractContents(value)].IsCollidable_(value)
222 );
223 bool isMovingRaycastDominant = false;
224 int cellValue = 0;
225 if (movingBlocksRaycastResult.HasValue
226 && movingBlocksRaycastResult.Value.MovingBlock != null
227 && (!terrainRaycastResult.HasValue || terrainRaycastResult.Value.Distance >= movingBlocksRaycastResult.Value.Distance)) {
228 isMovingRaycastDominant = true;
229 cellValue = movingBlocksRaycastResult.Value.MovingBlock.Value;
230 }
231 else if (terrainRaycastResult.HasValue
232 && (!movingBlocksRaycastResult.HasValue || terrainRaycastResult.Value.Distance < movingBlocksRaycastResult.Value.Distance)) {
233 //isMovingRaycastDominant = false;
234 cellValue = CurrnetTerrain()
235 .GetCellValue(
236 terrainRaycastResult.Value.CellFace.X,
237 terrainRaycastResult.Value.CellFace.Y,
238 terrainRaycastResult.Value.CellFace.Z
239 );
240 }
241 if (SubsystemPickables != null) {
242 SubsystemBlockBehavior[] blockBehaviors =
243 SubsystemPickables.m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(cellValue));
244 for (int i = 0; i < blockBehaviors.Length; i++) {
245 if (isMovingRaycastDominant) {
246 blockBehaviors[i].OnHitByProjectile(movingBlocksRaycastResult.Value.MovingBlock, this);
247 }
248 else if (terrainRaycastResult.HasValue) {
249 blockBehaviors[i].OnHitByProjectile(terrainRaycastResult.Value.CellFace, this);
250 }
251 }
252 }
253 if (terrainRaycastResult.HasValue) {
254 if (WrappedRaycast(
255 Position,
256 Position,
257 false,
258 true,
259 (value2, _) => BlocksManager.Blocks[Terrain.ExtractContents(value2)].IsCollidable_(value2)
260 )
261 .HasValue) {
262 int num8 = Terrain.ToCell(Position.X);
263 int num9 = Terrain.ToCell(Position.Y);
264 int num10 = Terrain.ToCell(Position.Z);
265 int num11 = 0;
266 int num12 = 0;
267 int num13 = 0;
268 int? num14 = null;
269 for (int j = -3; j <= 3; j++) {
270 for (int k = -3; k <= 3; k++) {
271 for (int l = -3; l <= 3; l++) {
272 int value = CurrnetTerrain().GetCellContents(j + num8, k + num9, l + num10);
274 int num15 = j * j + k * k + l * l;
275 if (!num14.HasValue
276 || num15 < num14.Value) {
277 num11 = j + num8;
278 num12 = k + num9;
279 num13 = l + num10;
280 num14 = num15;
281 }
282 }
283 }
284 }
285 }
286 if (num14.HasValue) {
287 FlyToPosition = new Vector3(num11, num12, num13) + new Vector3(0.5f);
288 }
289 else {
290 ToRemove = true;
291 }
292 }
293 else {
294 Plane plane = terrainRaycastResult.Value.CellFace.CalculatePlane();
295 bool flag2 = vector2.HasValue && vector2.Value != Vector2.Zero;
296 if (plane.Normal.X != 0f) {
297 float num16 = flag2 || MathF.Sqrt(MathUtils.Sqr(Velocity.Y) + MathUtils.Sqr(Velocity.Z)) > 10f ? 0.95f : 0.25f;
298 Velocity *= new Vector3(0f - num16, num16, num16);
299 }
300 if (plane.Normal.Y != 0f) {
301 float num17 = flag2 || MathF.Sqrt(MathUtils.Sqr(Velocity.X) + MathUtils.Sqr(Velocity.Z)) > 10f ? 0.95f : 0.25f;
302 Velocity *= new Vector3(num17, 0f - num17, num17);
303 if (flag2) {
304 Velocity.Y += 0.1f * plane.Normal.Y;
305 }
306 }
307 if (plane.Normal.Z != 0f) {
308 float num18 = flag2 || MathF.Sqrt(MathUtils.Sqr(Velocity.X) + MathUtils.Sqr(Velocity.Y)) > 10f ? 0.95f : 0.25f;
309 Velocity *= new Vector3(num18, num18, 0f - num18);
310 }
311 positionAtdt = Position;
312 }
313 }
314 }
315 else {
316 Vector3 vector3 = StuckMatrix.Value.Translation + StuckMatrix.Value.Up * block.ProjectileTipOffset;
317 if (!WrappedRaycast(
318 vector3,
319 vector3,
320 false,
321 true,
322 (value, _) => BlocksManager.Blocks[Terrain.ExtractContents(value)].IsCollidable_(value)
323 )
324 .HasValue) {
325 Position = StuckMatrix.Value.Translation;
327 StuckMatrix = null;
328 }
329 }
330 if (surfaceBlock != null
332 && SubsystemPickables != null) {
333 if (surfaceBlock is MagmaBlock) {
334 SubsystemPickables.m_subsystemParticles.AddParticleSystem(new MagmaSplashParticleSystem(SubsystemTerrain, Position, false));
335 SubsystemPickables.m_subsystemAudio.PlayRandomSound(
336 "Audio/Sizzles",
337 1f,
338 SubsystemPickables.m_random.Float(-0.2f, 0.2f),
339 Position,
340 3f,
341 true
342 );
343 if (!IsFireProof) {
344 ToRemove = true;
345 SubsystemPickables.m_subsystemExplosions.TryExplodeBlock(
349 Value
350 );
351 }
352 }
353 else {
354 SubsystemPickables.m_subsystemParticles.AddParticleSystem(new WaterSplashParticleSystem(SubsystemTerrain, Position, false));
355 SubsystemPickables.m_subsystemAudio.PlayRandomSound(
356 "Audio/Splashes",
357 1f,
358 SubsystemPickables.m_random.Float(-0.2f, 0.2f),
359 Position,
360 6f,
361 true
362 );
363 }
364 SplashGenerated = true;
365 }
366 else if (surfaceBlock == null) {
367 SplashGenerated = false;
368 }
369 //对于火焰的处理
370 if (SubsystemPickables != null) {
371 if (!IsFireProof
372 && SubsystemPickables.m_subsystemTime.PeriodicGameTimeEvent(1.0, GetHashCode() % 100 / 100.0)
373 && (SubsystemTerrain.Terrain.GetCellContents(
375 Terrain.ToCell(Position.Y + 0.1f),
377 )
378 == 104
379 || SubsystemPickables.m_subsystemFireBlockBehavior.IsCellOnFire(
381 Terrain.ToCell(Position.Y + 0.1f),
383 ))) {
384 SubsystemPickables.m_subsystemAudio.PlayRandomSound(
385 "Audio/Sizzles",
386 1f,
387 SubsystemPickables.m_random.Float(-0.2f, 0.2f),
388 Position,
389 3f,
390 true
391 );
392 ToRemove = true;
393 SubsystemPickables.m_subsystemExplosions.TryExplodeBlock(
397 Value
398 );
399 }
400 }
401 //掉落物在卡住的时候的更新
402 if (!StuckMatrix.HasValue) {
403 //TODO:这里的数值改为变量表示
404 if (vector2.HasValue
405 && surfaceHeight.HasValue) {
406 float num19 = surfaceHeight.Value - Position.Y;
407 float num20 = MathUtils.Saturate(3f * num19);
408 Velocity.X += 4f * dt * (vector2.Value.X - Velocity.X);
409 Velocity.Y -= 10f * dt;
410 Velocity.Y += 10f * (1f / block.GetDensity(Value) * num20) * dt;
411 Velocity.Z += 4f * dt * (vector2.Value.Y - Velocity.Z);
412 Velocity.Y *= MathF.Pow(0.001f, dt);
413 }
414 else {
415 Velocity.Y -= 10f * dt;
416 Velocity *= MathF.Pow(0.5f, dt);
417 }
418 }
419 }
420
421 public virtual void UpdateMovementWithTarget(ComponentPickableGatherer targetGatherer, float dt) {
422 if (!FlyToPosition.HasValue) {
423 return;
424 }
425 Vector3 v2 = FlyToPosition.Value - Position;
426 float num7 = v2.LengthSquared();
427 if (num7 >= 0.25f) {
428 Velocity = 6f * v2 / MathF.Sqrt(num7);
429 }
430 else {
431 FlyToPosition = null;
432 FlyToGatherer = null;
433 }
434 }
435
436 public override void UnderExplosion(Vector3 impulse, float damage) {
437 if (SubsystemExplosions == null) {
438 return;
439 }
440 if (IsExplosionProof) {
441 return;
442 }
444 if (damage / block.GetExplosionResilience(Value) > 0.1f) {
446 ToRemove = true;
447 }
448 else {
449 Vector3 vector = (impulse + new Vector3(0f, 0.1f * impulse.Length(), 0f)) * m_random.Float(0.75f, 1f);
450 if (vector.Length() > 10f) {
451 Projectile projectile = SubsystemExplosions.m_subsystemProjectiles.AddProjectile(
452 Value,
453 Position,
454 Velocity + vector,
455 m_random.Vector3(0f, 20f),
456 null
457 );
458 if (m_random.Float(0f, 1f) < 0.33f) {
459 SubsystemExplosions.m_subsystemProjectiles.AddTrail(
460 projectile,
462 new SmokeTrailParticleSystem(15, m_random.Float(0.75f, 1.5f), m_random.Float(1f, 6f), Color.White)
463 );
464 }
465 ToRemove = true;
466 }
467 else {
468 Velocity += vector;
469 }
470 }
471 }
472
473 public virtual void Draw(Camera camera, int drawOrder, double totalElapsedGameTime, Matrix rotationMatrix) {
474 float num = CalcVisibilityRange();
475 Vector3 position = Position;
476 Vector3 v = position - camera.ViewPosition;
477 float num2 = Vector3.Dot(camera.ViewDirection, v);
478 if (num2 < -0.5f
479 || num2 > num) {
480 return;
481 }
482 float num3 = v.Length();
483 if (!(num3 > num)) {
484 int num4 = Terrain.ExtractContents(Value);
485 Block block = BlocksManager.Blocks[num4];
486 float num5 = (float)(totalElapsedGameTime - CreationTime);
487 if (!StuckMatrix.HasValue) {
488 position.Y += 0.25f * MathUtils.Saturate(3f * num5);
489 }
490 int x = Terrain.ToCell(position.X);
491 int num6 = Terrain.ToCell(position.Y);
492 int z = Terrain.ToCell(position.Z);
493 TerrainChunk chunkAtCell = CurrnetTerrain().GetChunkAtCell(x, z);
494 if (chunkAtCell != null
495 && chunkAtCell.State >= TerrainChunkState.InvalidVertices1
496 && num6 >= 0
497 && num6 < TerrainChunk.HeightMinusOne) {
498 DrawBlockEnvironmentData().Humidity = CurrnetTerrain().GetSeasonalHumidity(x, z);
499 DrawBlockEnvironmentData().Temperature = CurrnetTerrain().GetSeasonalTemperature(x, z)
501 float f = MathUtils.Max(position.Y - num6 - 0.75f, 0f) / 0.25f;
502 Light = (int)MathUtils.Lerp(CurrnetTerrain().GetCellLightFast(x, num6, z), CurrnetTerrain().GetCellLightFast(x, num6 + 1, z), f);
503 }
505 DrawBlockEnvironmentData().BillboardDirection = Position - camera.ViewPosition;
506 DrawBlockEnvironmentData().InWorldMatrix.Translation = position;
507 float num7 = 1f - CalculateFog()(camera.ViewPosition, Position);
508 num7 *= MathUtils.Saturate(0.25f * (num - num3));
509 Matrix drawMatrix;
510 if (StuckMatrix.HasValue) {
511 drawMatrix = StuckMatrix.Value;
512 }
513 else {
514 rotationMatrix.Translation = position + new Vector3(0f, 0.04f * MathF.Sin(3f * num5), 0f);
515 drawMatrix = rotationMatrix;
516 }
517 bool shouldDrawBlock = true;
518 float drawBlockSize = 0.3f;
519 Color drawBlockColor = Color.MultiplyNotSaturated(Color.White, num7);
520 if (SubsystemPickables != null) {
522 "OnPickableDraw",
523 loader => {
524 loader.OnPickableDraw(
525 this,
527 camera,
528 drawOrder,
529 ref shouldDrawBlock,
530 ref drawBlockSize,
531 ref drawBlockColor
532 );
533 return false;
534 }
535 );
536 }
537 if (shouldDrawBlock) {
538 block.DrawBlock(PrimitivesRenderer(), Value, drawBlockColor, drawBlockSize, ref drawMatrix, DrawBlockEnvironmentData());
539 }
540 }
541 }
542
543 public virtual void Save(ValuesDictionary valuesDictionary) {
544 valuesDictionary.SetValue("Class", GetType().FullName);
545 valuesDictionary.SetValue("Value", Value);
546 valuesDictionary.SetValue("Count", Count);
547 valuesDictionary.SetValue("Position", Position);
548 valuesDictionary.SetValue("Velocity", Velocity);
549 valuesDictionary.SetValue("CreationTime", CreationTime);
550 if (StuckMatrix.HasValue) {
551 valuesDictionary.SetValue("StuckMatrix", StuckMatrix.Value);
552 }
553 if (OwnerEntity != null
554 && OwnerEntity.Id != 0) {
555 valuesDictionary.SetValue("OwnerID", OwnerEntity.Id);
556 }
557 }
558 }
559}
Engine.Vector3 Vector3
static float Saturate(float x)
static int Max(int x1, int x2)
static int Sqr(int x)
static float Lerp(float x1, float x2, float f)
virtual string GetCategory(int value)
virtual float GetDensity(int value)
virtual float GetExplosionResilience(int value)
void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData)
绘制方块_用于绘制方块物品形态
float ProjectileTipOffset
virtual bool IsCollidable_(int value)
virtual float GetNutritionalValue(int value)
Vector3 ViewPosition
Vector3 ViewDirection
virtual void UpdateMovement(float dt, ref Vector3 positionAtdt)
virtual void UpdateMovementWithTarget(ComponentPickableGatherer targetGatherer, float dt)
Func< SubsystemSky.CalculateFogDelegate > CalculateFog
SubsystemPickables SubsystemPickables
SubsystemTerrain SubsystemTerrain
Func< DrawBlockEnvironmentData > DrawBlockEnvironmentData
virtual void Initialize(int value, int count, Vector3 position, Vector3? velocity, Matrix? stuckMatrix, Entity owner)
virtual void Update(float dt)
virtual float DistanceToPick
override void Load(ValuesDictionary valuesDictionary)
virtual void InitializeData(Func< Terrain > terrain, Func< DrawBlockEnvironmentData > drawBlockEnvironmentData, Func< float > calcVisibilityRange, Func< SubsystemSky.CalculateFogDelegate > calculateFog, Func< PrimitivesRenderer3D > primitivesRenderer)
Func< Terrain > CurrnetTerrain
SubsystemPickables m_subsystemPickables
virtual float DistanceToFlyToTarget
SubsystemTerrain m_subsystemTerrain
Func< float > CalcVisibilityRange
SubsystemExplosions SubsystemExplosions
virtual void Draw(Camera camera, int drawOrder, double totalElapsedGameTime, Matrix rotationMatrix)
double m_timeWaitToAutoPick
TerrainRaycastResult? WrappedRaycast(Vector3 start, Vector3 end, bool useInteractionBoxes, bool skipAirBlocks, Func< int, float, bool > action)
virtual bool UpdateTimeToRemove()
SubsystemMovingBlocks SubsystemMovingBlocks
float m_distanceToFlyToTarget
SubsystemMovingBlocks m_subsystemMovingBlocks
Vector3? FlyToPosition
SubsystemExplosions m_subsystemExplosions
Matrix? StuckMatrix
Func< PrimitivesRenderer3D > PrimitivesRenderer
override void UnderExplosion(Vector3 impulse, float damage)
virtual double TimeWaitToAutoPick
virtual void Save(ValuesDictionary valuesDictionary)
ComponentPickableGatherer FlyToGatherer
virtual void OnHitByProjectile(CellFace cellFace, WorldItem worldItem)
delegate float CalculateFogDelegate(Vector3 viewPosition, Vector3 position)
static Func< int, int > GetTemperatureAdjustmentAtHeight
TerrainChunkState State
static int ExtractContents(int value)
static int ToCell(float x)
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
static Color White
static Color MultiplyNotSaturated(Color c, float s)
Vector3 Normal
定义 Plane.cs:3
static readonly Vector2 Zero
static readonly Vector3 Zero
float LengthSquared()
static float Dot(Vector3 v1, Vector3 v2)