Upload from upload_mods.ps1

This commit is contained in:
Nathaniel Cosford
2025-06-04 16:44:53 +09:30
commit f1fbbe67bb
1722 changed files with 165268 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
namespace Features.Fire.Harmony
{
[HarmonyPatch(typeof(Chunk))]
[HarmonyPatch("SetBlock")]
public class ChunkSetBlock
{
public static void Postfix(Chunk __instance, int ___m_X, int ___m_Z, int x, int y, int z, bool _fromReset)
{
if (!_fromReset) return;
// If the POI is being reset, clear the fire.
var vector3I = new Vector3i((___m_X << 4) + x, y, (___m_Z << 4) + z);
var fireMap = FireManager.Instance?.GetFireMap();
if (fireMap == null) return;
if (fireMap.ContainsKey(vector3I))
{
FireManager.Instance?.RemoveFire(vector3I);
}
}
}
}

View File

@@ -0,0 +1,43 @@
namespace Features.Fire.Harmony
{
// Allows the spread of the particles to catch things on fire.
[HarmonyPatch(typeof(Explosion))]
[HarmonyPatch("AttackBlocks")]
public class SCoreExplosionattackBlocks
{
public static void Postfix(Explosion __instance, int _entityThatCausedExplosion, ExplosionData ___explosionData)
{
if (FireManager.Instance == null) return;
if (FireManager.Instance.Enabled == false) return;
// BlockDamage set to 0 does nothing.
if (___explosionData.BlockDamage == 0) return;
if (___explosionData.ParticleIndex == 0) return;
var entityAlive = GameManager.Instance.World.GetEntity(_entityThatCausedExplosion) as EntityAlive;
if (entityAlive != null)
{
if (entityAlive.EntityClass.Properties.Contains("SpreadFire"))
{
if (entityAlive.EntityClass.Properties.GetBool("SpreadFire") == false)
return;
}
if (entityAlive.Buffs.HasCustomVar("SpreadFire"))
{
var spreadFire = entityAlive.Buffs.GetCustomVar("SpreadFire");
if (spreadFire == -1f) return;
}
}
foreach (var position in __instance.ChangedBlockPositions)
{
// Negative block damages extinguishes
if (___explosionData.BlockDamage < 0f)
FireManager.Instance.Extinguish(position.Key);
else
FireManager.Instance.Add(position.Key);
}
}
}
}

View File

@@ -0,0 +1,28 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace Features.Fire.Harmony
{
// Allows the spread of the particles to catch things on fire.
/*[HarmonyPatch(typeof(GameStateManager))]
[HarmonyPatch("StartGame")]
public class GameStateManagerStartGame
{
public static void Postfix()
{
if (GamePrefs.GetString(EnumGamePrefs.GameWorld) == "Empty"
|| GamePrefs.GetString(EnumGamePrefs.GameWorld) == "Playtesting"
|| GamePrefs.GetString(EnumGamePrefs.GameMode) == "GameModeEditWorld")
{
Debug.Log("Disabling Fire Manager in Play Testing / Prefab editor");
return;
}
FireManager.Init();
}
}*/
}

View File

@@ -0,0 +1,34 @@
namespace Features.Fire.Harmony
{
// Light reduction patch from ocbMaurice
[HarmonyPatch(typeof(ParticleEffect))]
[HarmonyPatch("SpawnParticleEffect")]
public class ParticleEffectspawnParticleEffect
{
private const int Odds = 4;
private static int _count = Odds;
public static void Postfix(ref Transform __result)
{
if (__result == null) return;
bool optionFireManager = CustomGameOptions.GetBool("CustomFireManager");
if (!optionFireManager) return;
if (__result.GetComponentInChildren<Light>() is not Light light) return;
if (_count == Odds)
{
_count = 0;
return;
}
light.enabled = false;
var go = light.gameObject;
//Log.Out($"SpawnParticleEffect - Destroy Light gameObject: {go}, parent: {go.transform.parent}");
go.transform.parent = null;
UnityEngine.Object.Destroy(go);
_count += 1;
}
}
}

View File

@@ -0,0 +1,27 @@
namespace Features.Fire.Harmony
{
[HarmonyPatch(typeof(Block))]
[HarmonyPatch("OnEntityWalking")]
public class BlockOnEntityWalking
{
public static void Postfix(int _x, int _y, int _z, Entity entity)
{
if (FireManager.Instance == null) return;
var blockPosition = new Vector3i(_x, _y, _z);
if (!FireManager.IsBurning(blockPosition)) return;
if (!GameManager.IsDedicatedServer)
if (!GameManager.Instance.HasBlockParticleEffect(blockPosition)) return;
if (entity is not EntityAlive entityAlive) return;
var buff = "buffBurningMolotov";
if (!string.IsNullOrEmpty(buff))
{
entityAlive.Buffs.AddBuff(buff, -1, entityAlive.isEntityRemote);
}
}
}
}

259
Score/Fire/Readme.md Normal file
View File

@@ -0,0 +1,259 @@
Fire Manager
---
The Fire Manager introduces fire mechanics into the game. This includes starting, spreading and extinguishing fires, and
allowing blocks to explode.
# Table of Contents
1. [Summary](#summary)
2. [Fire Manage Global Configuration](#fire-manager-global-configuration)
3. [Block-Specific Configuration](#block-specific-configuration)
4. [Examples](#examples)
## Summary
A block may catch on fire through a variety of means, depending on the mod in question. For example, a thrown molotov would certainly catch
blocks on fire, potentially triggering a cascading fire that may burn a building down.
When a block is on fire, it will have damage dealt to it over time, using the CheckInterval time.
When a block is checked during its CheckInterval time, neighboring blocks may catch on fire if they are flammable. A FireSpread property can disable this.
When a block has taken more damage than its max damage, the block will downgrade itself to its defined Downgrade block. By default, this is an air block.
When a block has an Explosion.ParticleIndex defined, the Fire Manage will use that data to trigger an explosion.
When a block is extinguished, a smoke particle will be placed on it, showing the player that it has been extinguished. An extinguished block will not immediately
catch fire again.
To determine if a block is flammable or not, several checks are performed. The checks here are listed in the order they are checked in code. Once a block is
determined to not be flammable, then the other checks are not performed.
- Does the block have tag of "inflammable"?
- Is the position a child of a block? ( think of multi-dim's here)
- Not Flammable.
- Is the position air?
- Not Flammable.
- is the position water?
- Not Flammable.
- Does The block have the tag of "flammable"?
- Flammable
- Does the Config block have the Property "MaterialID", and does it match our Block?
- Flammable
- Does the Config block have the Property "MaterialDamage", and does it match our Block?
- Flammable
- Does the Config block have the Property "MaterialSurface", and does it match our Block?
- Flammable
The block must return a "Flammable" check to be added to the Fire Manager's system, and be lit on fire.
## Fire Manager Global Configuration
The blocks.xml contains configurations and settings to adjust the fire behaviour from its defaults.
Note: Some of these properties may be defined on the block or material entry to over-ride the default.
#### Logging
```xml
<!-- Enables or disables verbose logging for troubleshooting -->
<property name="Logging" value="false"/>
```
#### FireEnable
```xml
<!-- Enables or disables the fire manager completely -->
<property name="FireEnable" value="false"/>
```
#### CheckInterval
```xml
<!-- Determines how often the fire manager should damage a block, determine fire spreading, etc -->
<property name="CheckInterval" value="20"/>
```
#### FireDamage
```xml
<!-- Determines how much damage is done to a block per CheckInterval. -->
<!-- If this property is defined on a specific block, that value will be used, rather than the default -->
<!-- If this property is defined on a materials.xml entry, that value will be used. -->
<property name="FireDamage" value="10"/>
```
#### SmokeTime
```xml
<!-- Determines the length of time, in seconds, that the smoke particle will appear on an extinguished block -->
<!-- If this property is defined on a specific block, that value will be used, rather than the default -->
<property name="SmokeTime" value="60"/>
```
#### FireSound
```xml
<!-- Determines which SoundDataNode entry will be used to play the sound -->
<!-- If this property is defined on a specific block, that value will be used, rather than the default -->
<property name="FireSound" value="ScoreMediumLoop"/>
```
#### BuffOnFire
```xml
<!-- Defines which buff to apply to a player / zombie / NPC when they touch a block on fire -->
<property name="BuffOnFire" value="buffBurningMolotov"/>
```
#### MaterialID
```xml
<!-- Defines which materials are considered flammable, by material ID in materials.xml -->
<property name="MaterialID" value="Mplants, Mcorn, Mhay"/>
```
#### MaterialDamage
```xml
<!-- Defines which materials are considered flammable, by material Damage in materials.xml -->
<property name="MaterialDamage" value="wood, cloth, corn, grass, plastic, leaves, cactus, mushroom, hay, paper, trash, backpack, organic"/>
```
#### MaterialSurface
```xml
<!-- Defines which materials are considered flammable, by material Surface in materials.xml -->
<property name="MaterialDamage" value="wood, cloth, corn, grass, plastic, leaves, cactus, mushroom, hay, paper, trash, backpack, organic"/>
```
#### SmokeParticle
```xml
<!-- Defines the Smoke Particle to be used on an extinguished block -->
<!-- If this property is defined on a specific block, that value will be used, rather than the default -->
<property name="SmokeParticle" value="#@modfolder:Resources/PathSmoke.unity3d?P_PathSmoke_X"/>
```
#### FireParticle
```xml
<!-- Defines the Fire Particle to be used on a block that is burning. -->
<!-- If this property is defined on a specific block, that value will be used, rather than the default -->
<property name="FireParticle" value="#@modfolder:Resources/gupFireParticles.unity3d?gupBeavis05-Heavy"/>
<!-- Other particles that may be available, but may cause more performance overhead -->
<!--
<property name="FireParticle" value="#@modfolder:Resources/gupFireParticles.unity3d?gupBeavis02-CampFire" />
<property name="FireParticle" value="#@modfolder:Resources/gupFireParticles.unity3d?gupBeavis03-Cartoon" />
<property name="FireParticle" value="#@modfolder:Resources/gupFireParticles.unity3d?gupBeavis04-SlowFire" />
<property name="FireParticle" value="#@modfolder:Resources/gupFireParticles.unity3d?gupBeavis05-Heavy" />
<property name="FireParticle" value="#@modfolder:Resources/gupFireParticles.unity3d?gupBeavis06-HeavyLight" />
-->
```
#### FireSpread
```xml
<!-- Defines is fire can be spread to neighboring blocks -->
<property name="FireSpread" value="true"/>
```
#### ChanceToExtinguish
```xml
<!-- The chance, in percentage as defined from 0 to 1 to denote 0% to 100%, for a block to self-extinguish -->
<!-- This is re-checked on each CheckInterval -->
<!-- If this property is defined on a specific block, that value will be used, rather than the default -->
<property name="ChanceToExtinguish" value="0.05"/>
```
## Block-specific Configuration
In addition to the above settings in the Fire Manager's overall blocks.xml, further properties may be optionally added to blocks.xml to further define the behaviour.
These per-block settings will over-ride the global value for that block in which they are defined on.
#### FireDowngradeBlock
```xml
<!-- When a block is destroyed by fire, it will downgrade to this block -->
<!-- By default, this is air -->
<property name="FireDowngradeBlock" value="burnBlock"/>
```
#### Explosion.ParticleIndex
```xml
<!-- If a block has a defined Explosion.ParticleIndex and is destroyed by fire, the fire manager will set an explosion based on those settings. -->
<property name="Explosion.ParticleIndex" value="0"/>
```
#### ChanceToExtinguish
```xml
<!-- The chance, in percentage as defined from 0 to 1 to denote 0% to 100%, for a block to self-extinguish -->
<property name="ChanceToExtinguish" value="0.05"/>
```
#### FireDamage
```xml
<!-- Determines how much damage is done to a block per CheckInterval. -->
<property name="FireDamage" value="10"/>
```
## MinEvents
A few MinEvents have been written to help modders interact with the fire system. These MinEvents may be added to buffs or item actions.
The trigger may change depending on context and use.
#### MinEventActionAddFireDamage
This effect will set a block on fire, using the target's position, and the range. There is an optional delay time, which will delay the fire from starting.
```xml
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamage, SCore" target="positionAOE" range="5" delayTime="10" />
```
#### MinEventActionAddFireDamageCascade
This effect can allow fire to spread to to surrounding blocks. You can set up a filter based on the type of blocks you wanted affected.
```xml
<!-- The same type of block -->
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="Type" />
<!-- Shares the same material -->
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="Material" />
<!-- Shares the same material damage classification -->
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="MaterialDamage" />
<!-- Shares the same material surface classification -->
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="MaterialSurface" />
```
#### MinEventActionCheckFireProximity
Checks to see if there's any fire blocks within the specified range, using the player's position as center.
```xml
<!-- The cvar specified, by default _closeFires, will contain the number of burning blocks in the range. -->
<triggered_effect trigger="onSelfBuffUpdate" action="CheckFireProximity, SCore" range="5" cvar="_closeFires" />
```
#### MinEventActionRemoveFire
Remove Fire within the specified range, using the specified target.
```xml
<!-- This will remove fire from all blocks with a range of 5 from the position of the target. -->
<triggered_effect trigger="onSelfDamagedBlock" action="RemoveFire, SCore" target="positionAOE" range="5"/>
```
## Examples
### XPath
Here are some examples on how to modify the ConfigFeatureBlock, which holds the Fire Management settings, from another modlet.
```xml
<!-- Enable fire -->
<set xpath="/blocks/block[@name='ConfigFeatureBlock']/property[@class='FireManagement']/property[@name='FireEnable']/@value">true</set>
<!-- Turn on verbose logging -->
<set xpath="/blocks/block[@name='ConfigFeatureBlock']/property[@class='FireManagement']/property[@name='Logging']/@value">true</set>
<!-- Adding materials -->
<set xpath="/blocks/block[@name='ConfigFeatureBlock']/property[@class='FireManagement']/property[@name='MaterialDamage']/@value">wood, cloth, corn, grass, plastic, leaves, cactus, mushroom, hay, paper, trash, backpack, organic</set>
<set xpath="/blocks/block[@name='ConfigFeatureBlock']/property[@class='FireManagement']/property[@name='MaterialSurface']/@value">wood, cloth, corn, grass, plastic, leaves, cactus, mushroom, hay, paper, trash, backpack, organic</set>
```
To adding Fire Damage to the flaming crossbow bolts
```xml
<append xpath="/items/item[@name='ammoCrossbowBoltFlaming']/effect_group" >
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamage, SCore" delayTime="5000"/> <!-- Delay Time in ms -->
</append>
```
### Triggers
```xml
<!-- Adds fire to the block being hit, if it's flammable. -->
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamage, SCore" />
<!-- Remove fire from an area -->
<triggered_effect trigger="onSelfPrimaryActionRayHit" action="RemoveFire, SCore" target="positionAOE" range="5"/>
<!-- Spread fire to all surrounding blocks that have the same material as the target being hit, such as cloth -->
<triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="Material" />
```

View File

@@ -0,0 +1,786 @@
using Audio;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
/// <summary>
/// SCore's FireManager allows flammable blocks to catch and spread fire.
/// </summary>
/// <remarks>
/// The Fire Manager allows blocks to catch on fire, and allows them to spread to other blocks around it at a timed interval.
/// The following parameters are configured through the blocks.xml
/// </remarks>
public class FireManager
{
private const string AdvFeatureClass = "FireManagement";
private static readonly object Locker = new object();
private static readonly ConcurrentDictionary<Vector3i, BlockValue>
FireMap = new ConcurrentDictionary<Vector3i, BlockValue>();
private static readonly ConcurrentDictionary<Vector3i, float> ExtinguishPositions =
new ConcurrentDictionary<Vector3i, float>();
private float _checkTime = 120f;
private float _currentTime;
private const float CheckTimeLights = 0.8f;
private float _currentTimeLights;
private float _fireDamage = 1f;
private float _smokeTime = 60f;
private readonly GameRandom _random = GameManager.Instance.World.GetGameRandom();
private bool _fireSpread = true;
// Used to throttle sounds playing.
private static readonly List<Vector3i> SoundPlaying = new List<Vector3i>();
private static readonly List<Vector3i> ParticlePlaying = new List<Vector3i>();
private const int MaxLights = 32;
private static readonly HashSet<Light> Shutoff =
new HashSet<Light>();
private string _fireSound;
private string _fireParticle;
private string _smokeParticle;
private const string SaveFile = "FireManager.dat";
private ThreadManager.ThreadInfo _dataSaveThreadInfo;
private float _chanceToExtinguish = 0.05f;
public bool Enabled; // { private set; get; }
public static FireManager Instance { get; private set; }
public static void Init()
{
Instance = new FireManager();
Instance.ReadConfig();
}
private void ReadConfig()
{
var fireSpreadString = "true";
if (!StringParsers.ParseBool(fireSpreadString))
{
Debug.Log("Fire Spread Disabled.");
_fireSpread = false;
}
Enabled = true;
string option = "";
bool optionFireManager = CustomGameOptions.GetBool("CustomFireManager");
if (!optionFireManager)
{
Log.Out("Fire Manager is disabled.");
Enabled = false;
return;
}
option = "20";
if (!string.IsNullOrEmpty(option))
_checkTime = StringParsers.ParseFloat(option);
var strDamage = "50";
if (!string.IsNullOrWhiteSpace(strDamage))
_fireDamage = StringParsers.ParseFloat(strDamage);
_currentTime = -1;
var smoke = "60";
if (!string.IsNullOrWhiteSpace(smoke))
_smokeTime = StringParsers.ParseFloat(smoke);
var strFireSound = "SCoreMediumLoop";
if (!string.IsNullOrWhiteSpace(strFireSound))
_fireSound = strFireSound;
if (_fireSound == "None")
_fireSound = string.Empty;
Log.Out("Starting Fire Manager");
_fireParticle = "#@modfolder(zzz_REBIRTH__Utils):Resources/gupFireParticles.unity3d?gupBeavis05-Heavy";
_smokeParticle = "#@modfolder(zzz_REBIRTH__Utils):Resources/PathSmoke.unity3d?P_PathSmoke_X";
var optionChanceToExtinguish = "0.05";
if (!string.IsNullOrEmpty(option))
_chanceToExtinguish = StringParsers.ParseFloat(optionChanceToExtinguish);
// Read the FireManager
Load();
// Only run the Update on the server, then just distribute the data to the clients using NetPackages.
if (!SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer) return;
Log.Out($" :: Fire Interval Check time: {_checkTime}");
ModEvents.GameUpdate.RegisterHandler(FireUpdate);
ModEvents.GameUpdate.RegisterHandler(LightsUpdate);
}
#region LightCode
private void LightsUpdate()
{
// Make sure to only run it once
lock (Locker)
{
_currentTimeLights -= Time.deltaTime;
if (_currentTimeLights > 0f) return;
_currentTimeLights = CheckTimeLights;
ShutoffLights();
CheckLights();
}
}
private static void ShutoffLights()
{
if (Shutoff.Count == 0) return;
if (GameManager.Instance.IsPaused()) return;
Shutoff.RemoveWhere(light => light == null);
foreach (var light in Shutoff)
{
light.intensity -= Time.deltaTime;
// Log.Out("Toning down {0}", light.intensity);
if (light.intensity > 0f) continue;
// Log.Out("Culling light out of this world");
var gameObject = light.gameObject;
gameObject.transform.parent = null;
UnityEngine.Object.Destroy(gameObject);
}
Shutoff.RemoveWhere(light => light.intensity <= 0f);
}
private static void CheckLights()
{
if (GameManager.Instance.IsPaused()) return;
var allLights = UnityEngine.Object.FindObjectsOfType<Light>();
if (allLights.Length <= MaxLights) return;
var curLights = new List<Light>();
for (var n = 0; n < allLights.Length; n += 1)
{
if (allLights[n].name != "FireLight") continue;
if (Shutoff.Contains(allLights[n])) continue;
curLights.Add(allLights[n]);
}
// AdvLogging.DisplayLog(AdvFeatureClass,$"Detect currently {curLights.Count} lights, {Shutoff.Count} being culled");
// Do nothing if we are (or will be) within limits
if (curLights.Count <= MaxLights) return;
// Otherwise choose more lights to shutoff
while (curLights.Count >= MaxLights)
{
var idx = GameManager.Instance.World.GetGameRandom().RandomRange(curLights.Count);
if (Shutoff.Contains(curLights[idx])) continue;
// Log.Out("Selected {0} for culling", idx);
Shutoff.Add(curLights[idx]);
curLights.RemoveAt(idx);
}
}
#endregion
// Poor man's timed cache
private void CheckExtinguishedPosition()
{
var worldTime = GameManager.Instance.World.GetWorldTime();
foreach (var position in ExtinguishPositions)
{
Remove(position.Key);
if (!(position.Value < worldTime) &&
!GameManager.Instance.World.GetBlock(position.Key + Vector3i.down).isair) continue;
ExtinguishPositions.TryRemove(position.Key, out var _);
ClearPos(position.Key);
}
}
public ConcurrentDictionary<Vector3i, BlockValue> GetFireMap()
{
return FireMap;
}
public int CloseFires(Vector3i position, int range = 5)
{
var count = 0;
for (var x = position.x - range; x <= position.x + range; x++)
{
for (var z = position.z - range; z <= position.z + range; z++)
{
for (int y = position.y - 2; y <= position.y + 2; y++)
{
var localPosition = new Vector3i(x, y, z);
if (IsBurning(localPosition)) count++;
}
}
}
return count;
}
public bool IsPositionCloseToFire(Vector3i position, int range = 5)
{
for (var x = position.x - range; x <= position.x + range; x++)
{
for (var z = position.z - range; z <= position.z + range; z++)
{
for (var y = position.y - 2; y <= position.y + 2; y++)
{
var localPosition = new Vector3i(x, y, z);
if (IsBurning(localPosition)) return true;
}
}
}
return false;
}
private void FireUpdate()
{
// Make sure to only run it once
lock (Locker)
{
_currentTime -= Time.deltaTime;
if (_currentTime > 0f) return;
GameManager.Instance.StopCoroutine(CheckBlocks());
GameManager.Instance.StartCoroutine(CheckBlocks());
}
}
private IEnumerator CheckBlocks()
{
if (GameManager.Instance.IsPaused()) yield break;
if (!GameManager.Instance.gameStateManager.IsGameStarted()) yield break;
//Log.Out(AdvFeatureClass,
//$"Checking Blocks for Fire: {FireMap.Count} Blocks registered. Extinguished Blocks: {ExtinguishPositions.Count}");
_currentTime = _checkTime;
var changes = new List<BlockChangeInfo>();
var neighbors = new List<Vector3i>();
CheckExtinguishedPosition();
var chunkCluster = GameManager.Instance.World.ChunkClusters[0];
if (chunkCluster == null) yield break;
var counter = 0;
var rainfallValue = WeatherManager.Instance.GetCurrentRainfallValue();
foreach (var posDict in FireMap)
{
counter++;
// only process 10 blocks per frame.
if (counter % 10 == 0)
yield return null;
var blockPos = posDict.Key;
if (!IsFlammable(blockPos))
{
Remove(blockPos);
continue;
}
var block = GameManager.Instance.World.GetBlock(blockPos);
// Get block specific damages
var damage = (int)_fireDamage;
if (block.Block.Properties.Contains("FireDamage"))
damage = block.Block.Properties.GetInt("FireDamage");
if (block.Block.blockMaterial.Properties.Contains("FireDamage"))
damage = block.Block.blockMaterial.Properties.GetInt("FireDamage");
if (block.Block.Properties.Contains("ChanceToExtinguish"))
block.Block.Properties.ParseFloat("ChanceToExtinguish", ref _chanceToExtinguish);
block.damage += damage;
if (block.damage >= block.Block.MaxDamage)
{
block.Block.SpawnDestroyParticleEffect(GameManager.Instance.World, block, blockPos, 1f,
block.Block.tintColor, -1);
var blockValue2 = block.Block.DowngradeBlock;
if (block.Block.Properties.Values.ContainsKey("FireDowngradeBlock"))
blockValue2 = Block.GetBlockValue(block.Block.Properties.Values["FireDowngradeBlock"]);
if (block.Block.Properties.Values.ContainsKey("Explosion.ParticleIndex") ||
block.Block.Properties.Classes.ContainsKey("Explosion"))
block.Block.OnBlockDestroyedByExplosion(GameManager.Instance.World, 0, blockPos, block, -1);
// Check if there's another placeholder for this block.
if (!blockValue2.isair)
blockValue2 = BlockPlaceholderMap.Instance.Replace(blockValue2,
GameManager.Instance.World.GetGameRandom(), blockPos.x, blockPos.z);
blockValue2.rotation = block.rotation;
blockValue2.meta = block.meta;
block = blockValue2;
}
if (!block.isair)
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(
NetPackageManager.GetPackage<NetPackageAddFirePosition>().Setup(blockPos, -1));
}
else
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(
NetPackageManager.GetPackage<NetPackageRemoveFirePosition>().Setup(blockPos, -1));
}
changes.Add(new BlockChangeInfo(0, blockPos, block));
var rand = _random.RandomRange(0f, 1f);
var extinguishChange = _chanceToExtinguish;
if (rainfallValue > 0.25)
{
extinguishChange = _chanceToExtinguish * 2f;
}
var blchanceToExtinguish = rand < extinguishChange;
// If the new block has changed, check to make sure the new block is flammable. Note: it checks the blockValue, not blockPos, since the change hasn't been committed yet.
if (!IsFlammable(block) || block.isair || blchanceToExtinguish)
{
// queue up the change
if (DynamicMeshManager.Instance != null)
DynamicMeshManager.Instance.AddChunk(blockPos, true);
Extinguish(blockPos);
continue;
}
ToggleSound(blockPos, rand < 0.10);
ToggleParticle(blockPos, true);
// If we are damaging a block, allow the fire to spread.
if (_fireSpread)
neighbors.AddRange(CheckNeighbors(blockPos));
FireMap[blockPos] = block;
}
// Send all the changes in one shot
if (changes.Count > 0)
GameManager.Instance.SetBlocksRPC(changes);
if (_fireSpread == false) yield break;
// Spread the fire to the neighbors. We delay this here so the fire does not spread too quickly or immediately, getting stuck in the above loop.
foreach (var pos in neighbors)
Add(pos);
//Debug.Log($"Sound Counter: {SoundPlaying.Count}, Fire Counter: {FireMap.Count} Particle Count: {ParticlePlaying.Count}: Heat: {heatMeter}");
}
private void ToggleSound(Vector3i blockPos, bool turnOn)
{
//if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer) return;
if (!ThreadManager.IsMainThread()) return;
// If there's a lot of fires going on, turn off the sounds.
if (turnOn && FireMap.Count > 60)
{
turnOn = false;
}
var sound = GetFireSound(blockPos);
if (string.IsNullOrEmpty(sound)) return;
if (turnOn)
{
if (SoundPlaying.Contains(blockPos))
return;
SoundPlaying.Add(blockPos);
Manager.Play(blockPos, sound);
return;
}
// No sound?
if (!SoundPlaying.Contains(blockPos)) return;
Manager.Stop(blockPos, sound);
SoundPlaying.Remove(blockPos);
}
private void ToggleParticle(Vector3i blockPos, bool turnOn)
{
// if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer) return;
if (!ThreadManager.IsMainThread()) return;
var randomFireParticle = GetRandomFireParticle(blockPos);
if (turnOn)
{
if (ParticlePlaying.Contains(blockPos)) return;
if (GameManager.Instance.HasBlockParticleEffect(blockPos)) return;
ParticlePlaying.Add(blockPos);
RebirthUtilities.addParticlesCentered(randomFireParticle, blockPos);
return;
}
ParticlePlaying.Remove(blockPos);
RebirthUtilities.removeParticles(blockPos);
}
private string GetFireSound(Vector3i blockPos)
{
var block = GameManager.Instance.World.GetBlock(blockPos);
var fireSound = _fireSound;
if (block.Block.Properties.Contains("FireSound"))
fireSound = block.Block.Properties.GetString("FireSound");
return fireSound;
}
private string GetRandomFireParticle(Vector3i blockPos)
{
var block = GameManager.Instance.World.GetBlock(blockPos);
var fireParticle = _fireParticle;
if (block.Block.Properties.Contains("FireParticle"))
fireParticle = block.Block.Properties.GetString("FireParticle");
if (block.Block.blockMaterial.Properties.Contains("FireParticle"))
fireParticle = block.Block.blockMaterial.Properties.GetString("FireParticle");
var randomFire = ""; // Configuration.GetPropertyValue(AdvFeatureClass, "RandomFireParticle");
if (string.IsNullOrEmpty(randomFire)) return fireParticle;
var fireParticles = randomFire.Split(',');
var randomIndex = _random.RandomRange(0, fireParticles.Length);
fireParticle = fireParticles[randomIndex];
return fireParticle;
}
private string GetRandomSmokeParticle(Vector3i blockPos)
{
var block = GameManager.Instance.World.GetBlock(blockPos);
var smokeParticle = _smokeParticle;
if (block.Block.Properties.Contains("SmokeParticle"))
smokeParticle = block.Block.Properties.GetString("SmokeParticle");
if (block.Block.blockMaterial.Properties.Contains("SmokeParticle"))
smokeParticle = block.Block.blockMaterial.Properties.GetString("SmokeParticle");
var randomSmoke = ""; // Configuration.GetPropertyValue(AdvFeatureClass, "RandomSmokeParticle");
if (string.IsNullOrEmpty(randomSmoke)) return smokeParticle;
var smokeParticles = randomSmoke.Split(',');
var randomIndex = GameManager.Instance.World.GetGameRandom().RandomRange(0, smokeParticles.Length);
smokeParticle = smokeParticles[randomIndex];
return smokeParticle;
}
// Check to see if the nearby blocks can catch fire.
private static List<Vector3i> CheckNeighbors(Vector3i blockPos)
{
var neighbors = new List<Vector3i>();
foreach (var direction in Vector3i.AllDirections)
{
var position = blockPos + direction;
if (FireMap.ContainsKey(position))
continue;
if (IsFlammable(position))
neighbors.Add(position);
}
return neighbors;
}
private static bool IsNearWater(Vector3i blockPos)
{
foreach (var direction in Vector3i.AllDirections)
{
var position = blockPos + direction;
var blockValue = GameManager.Instance.World.GetBlock(position);
if (blockValue.isWater) return true;
if (blockValue.Block is BlockLiquidv2) return true;
// A21 water check.
if (GameManager.Instance.World.GetWaterPercent(position) > 0.25f) return true;
}
return false;
}
private static bool IsFlammable(BlockValue blockValue)
{
if (blockValue.Block.HasAnyFastTags(FastTags<TagGroup.Global>.Parse("inflammable"))) return false;
if (blockValue.ischild) return false;
if (blockValue.isair) return false;
if (blockValue.isWater) return false;
// if (blockValue.Block.Properties.Values.ContainsKey("Explosion.ParticleIndex")) return true;
if (blockValue.Block.HasAnyFastTags(FastTags<TagGroup.Global>.Parse("flammable"))) return true;
var blockMaterial = blockValue.Block.blockMaterial;
var matID = "Mplants, Mcorn, Mhay"; // Configuration.GetPropertyValue(AdvFeatureClass, "MaterialID");
if (matID.Contains(blockMaterial.id)) return true;
var matDamage = "wood, cloth, corn, grass, plastic, leaves, cactus, mushroom, hay, paper, trash, backpack, organic"; // Configuration.GetPropertyValue(AdvFeatureClass, "MaterialDamage");
if (!string.IsNullOrEmpty(matDamage) && blockMaterial.DamageCategory != null)
if (matDamage.Contains(blockMaterial.DamageCategory))
return true;
var matSurface = "wood, cloth, corn, grass, plastic, leaves, cactus, mushroom, hay, paper, trash, backpack, organic"; // Configuration.GetPropertyValue(AdvFeatureClass, "MaterialSurface");
if (string.IsNullOrEmpty(matSurface) || blockMaterial.SurfaceCategory == null) return false;
return matSurface.Contains(blockMaterial.SurfaceCategory);
}
private static bool IsFlammable(Vector3i blockPos)
{
if (GameManager.Instance.World.IsWithinTraderArea(blockPos)) return false;
if (ExtinguishPositions.ContainsKey(blockPos)) return false;
// If its already burning, then don't do any other check
if (IsBurning(blockPos)) return true;
if (IsNearWater(blockPos)) return false;
// Check the block value.
var blockValue = GameManager.Instance.World.GetBlock(blockPos);
return IsFlammable(blockValue);
}
private static void Write(BinaryWriter bw)
{
// Save the burning blocks.
var writeOut = "";
foreach (var temp in FireMap)
writeOut += $"{temp.Key};";
writeOut = writeOut.TrimEnd(';');
bw.Write(writeOut);
// Save the blocks we've put out
var writeOut2 = "";
foreach (var temp in ExtinguishPositions.Keys)
writeOut2 += $"{temp};";
writeOut2 = writeOut2.TrimEnd(';');
bw.Write(writeOut2);
}
private void Read(BinaryReader br)
{
// Read burning blocks
var positions = br.ReadString();
foreach (var position in positions.Split(';'))
{
if (string.IsNullOrEmpty(position)) continue;
var vector = StringParsers.ParseVector3i(position);
AddBlock(vector);
}
// Read extinguished blocks.
var extingished = br.ReadString();
foreach (var position in extingished.Split(';'))
{
if (string.IsNullOrEmpty(position)) continue;
var vector = StringParsers.ParseVector3i(position);
ExtinguishBlock(vector);
}
}
public void ClearPosOnly(Vector3i blockPos)
{
ToggleSound(blockPos, false);
ToggleParticle(blockPos, false);
}
public void ClearPos(Vector3i blockPos)
{
ClearPosOnly(blockPos);
if (!SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(
NetPackageManager.GetPackage<NetPackageRemoveParticleEffect>().Setup(blockPos, -1));
return;
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(
NetPackageManager.GetPackage<NetPackageRemoveParticleEffect>().Setup(blockPos, -1));
}
public void Add(Vector3i blockPos, int entityID = -1)
{
if (!IsFlammable(blockPos))
return;
AddBlock(blockPos);
if (!SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(
NetPackageManager.GetPackage<NetPackageAddFirePosition>().Setup(blockPos, entityID));
return;
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(
NetPackageManager.GetPackage<NetPackageAddFirePosition>().Setup(blockPos, entityID));
}
// General call to remove the fire from a block, and add an extinguished counter, so blocks can be temporarily immune to restarting.
public void Extinguish(Vector3i blockPos, int entityID = -1)
{
ExtinguishBlock(blockPos);
if (!SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(
NetPackageManager.GetPackage<NetPackageAddExtinguishPosition>().Setup(blockPos, entityID));
return;
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(
NetPackageManager.GetPackage<NetPackageAddExtinguishPosition>().Setup(blockPos, entityID));
}
public void Remove(Vector3i blockPos, int entityID = -1)
{
RemoveFire(blockPos);
if (!SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(
NetPackageManager.GetPackage<NetPackageRemoveFirePosition>().Setup(blockPos, entityID));
return;
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(
NetPackageManager.GetPackage<NetPackageRemoveFirePosition>().Setup(blockPos, entityID));
}
public void RemoveFire(Vector3i blockPos)
{
//if (!FireMap.ContainsKey(blockPos)) return;
ToggleSound(blockPos, false);
ToggleParticle(blockPos, false);
FireMap.TryRemove(blockPos, out _);
}
public void ExtinguishBlock(Vector3i blockPos)
{
//Log.Out("FireManager-ExtinguishBlock START");
var worldTime = GameManager.Instance.World.GetWorldTime();
var expiry = worldTime + _smokeTime;
// Seems like sometimes the dedicated and clients are out of sync, so this is a shot in the dark to see if we just skip the expired position check, and just
// keep resetting the expired time.
ExtinguishPositions[blockPos] = expiry;
FireMap.TryRemove(blockPos, out _);
var block = GameManager.Instance.World.GetBlock(blockPos);
ToggleSound(blockPos, false);
if (block.isair || !(_smokeTime > 0))
{
//Log.Out("FireManager-ExtinguishBlock 1");
return;
}
var randomSmokeParticle = GetRandomSmokeParticle(blockPos);
//Log.Out("FireManager-ExtinguishBlock randomSmokeParticle: " + randomSmokeParticle);
RebirthUtilities.addParticlesCentered(randomSmokeParticle, blockPos);
}
// Add flammable blocks to the Fire Map
public void AddBlock(Vector3i blockPos)
{
var block = GameManager.Instance.World.GetBlock(blockPos);
if (!FireMap.TryAdd(blockPos, block)) return;
ToggleSound(blockPos, true);
ToggleParticle(blockPos, true);
}
public static bool IsBurning(Vector3i blockPos)
{
return Instance.Enabled && FireMap.ContainsKey(blockPos);
}
private int SaveDataThreaded(ThreadManager.ThreadInfo threadInfo)
{
var pooledExpandableMemoryStream =
(PooledExpandableMemoryStream)threadInfo.parameter;
var text = $"{GameIO.GetSaveGameDir()}/{SaveFile}";
if (File.Exists(text))
File.Copy(text, $"{GameIO.GetSaveGameDir()}/{SaveFile}.bak", true);
pooledExpandableMemoryStream.Position = 0L;
StreamUtils.WriteStreamToFile(pooledExpandableMemoryStream, text);
Log.Out("FireManager saved {0} bytes", new object[]
{
pooledExpandableMemoryStream.Length
});
MemoryPools.poolMemoryStream.FreeSync(pooledExpandableMemoryStream);
return -1;
}
private void Save()
{
if (_dataSaveThreadInfo == null || !ThreadManager.ActiveThreads.ContainsKey("silent_FireDataSave"))
{
Log.Out($"FireManager saving {FireMap.Count} Fires...");
var pooledExpandableMemoryStream = MemoryPools.poolMemoryStream.AllocSync(true);
using (var pooledBinaryWriter = MemoryPools.poolBinaryWriter.AllocSync(false))
{
pooledBinaryWriter.SetBaseStream(pooledExpandableMemoryStream);
Write(pooledBinaryWriter);
}
_dataSaveThreadInfo = ThreadManager.StartThread("silent_FireDataSave", null,
SaveDataThreaded, null,
System.Threading.ThreadPriority.Normal, pooledExpandableMemoryStream);
}
else
{
Log.Out("Not Saving. Thread still running?");
}
}
private void Load()
{
var path = $"{GameIO.GetSaveGameDir()}/{SaveFile}";
if (!Directory.Exists(GameIO.GetSaveGameDir()) || !File.Exists(path)) return;
try
{
using var fileStream = File.OpenRead(path);
using var pooledBinaryReader = MemoryPools.poolBinaryReader.AllocSync(false);
pooledBinaryReader.SetBaseStream(fileStream);
Read(pooledBinaryReader);
}
catch (Exception)
{
path = $"{GameIO.GetSaveGameDir()}/{SaveFile}.bak";
if (File.Exists(path))
{
using var fileStream2 = File.OpenRead(path);
using var pooledBinaryReader2 = MemoryPools.poolBinaryReader.AllocSync(false);
pooledBinaryReader2.SetBaseStream(fileStream2);
Read(pooledBinaryReader2);
}
}
Log.Out($"Fire Manager {path} Loaded: {FireMap.Count}");
}
public void Reset()
{
//Log.Out("Removing all blocks that are on fire and smoke.");
lock (Locker)
{
foreach (var position in FireMap.Keys)
Remove(position);
foreach (var position in ExtinguishPositions.Keys)
RebirthUtilities.removeParticles(position);
FireMap.Clear();
ExtinguishPositions.Clear();
Save();
}
}
}

View File

@@ -0,0 +1,81 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using System.Xml.Linq;
/// <summary>
/// Set's a single block on fire.
/// </summary>
/// <remarks>
/// This effect will set a block on fire, using the target's position, and the range. There is an optional delay time, which will delay the fire from starting.
/// Example:
/// <triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamage, SCore" target="positionAOE" range="5" delayTime="10" />
/// </remarks>
[UsedImplicitly]
public class MinEventActionAddFireDamage : MinEventActionRemoveBuff
{
private static readonly string AdvFeatureClass = "FireManagement";
private float _delayTime;
public override void Execute(MinEventParams @params)
{
if (FireManager.Instance == null) return;
if (FireManager.Instance.Enabled == false) return;
var position = @params.Position;
if (targetType != TargetTypes.positionAOE)
{
if (Voxel.voxelRayHitInfo.bHitValid)
{
var hitInfo = Voxel.voxelRayHitInfo;
if (hitInfo == null) return;
// modification from FuriousRamsay to fix issue where the lookray is behind a door, which is setting fire to blocks on the other side of metal doors.
var itemAction = @params.Self.inventory.holdingItemData.item.Actions[0];
if (itemAction is ItemActionMelee)
{
float blockRange = 0;
if (itemAction.Properties.Values.ContainsKey("Block_range"))
{
blockRange = StringParsers.ParseFloat(itemAction.Properties.Values["Block_range"]);
}
if ((blockRange > 0) && (Vector3.Distance(hitInfo.hit.blockPos, @params.Position) > blockRange))
{
return;
}
}
position = hitInfo.hit.blockPos;
}
}
//AdvLogging.DisplayLog(AdvFeatureClass, $"Executing AddFireDamage() at {position} Self: {@params.Self.position} Range: {maxRange} Delay: {_delayTime}");
Task.Delay((int)_delayTime)
.ContinueWith(_ => AddFire(position));
}
private void AddFire(Vector3 position)
{
var range = (int)maxRange;
for (var x = -range; x <= range; x++)
{
for (var z = -range; z <= range; z++)
{
for (var y = -range; y <= range; y++)
{
var vector = new Vector3i(position.x + x, position.y + y, position.z + z);
FireManager.Instance.Add(vector);
}
}
}
}
public override bool ParseXmlAttribute(XAttribute attribute)
{
var flag = base.ParseXmlAttribute(attribute);
if (flag) return true;
var name = attribute.Name.LocalName;
if (name != "delayTime") return false;
_delayTime = StringParsers.ParseFloat(attribute.Value);
return true;
}
}

View File

@@ -0,0 +1,99 @@
using JetBrains.Annotations;
using System.Xml.Linq;
/// <summary>
/// Spreads fire over a wider area than a single block.
/// </summary>
/// <remarks>
/// This effect can allow fire to spread to to surrounding blocks. You can set up a filter based on the type of blocks you wanted affected.
/// Example:
/// <!-- The same type of block -->
/// <triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="Type" />
///
/// <!-- Shares the same material -->
/// <triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="Material" />
///
/// <!-- Shares the same material damage classification -->
/// <triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="MaterialDamage" />
///
/// <!-- Shares the same material surface classification -->
/// <triggered_effect trigger="onSelfDamagedBlock" action="AddFireDamageCascade, SCore" range="4" filter="MaterialSurface" />
/// </remarks>
[UsedImplicitly]
public class MinEventActionAddFireDamageCascade : MinEventActionRemoveBuff
{
private enum FilterTypeCascade
{
Type,
Material,
MaterialDamage,
MaterialSurface
}
private FilterTypeCascade _filterType = FilterTypeCascade.Type;
public override void Execute(MinEventParams @params)
{
var position = @params.Position;
if (targetType != TargetTypes.positionAOE)
{
if (Voxel.voxelRayHitInfo.bHitValid)
{
var hitInfo = Voxel.voxelRayHitInfo;
if (hitInfo == null) return;
position = hitInfo.hit.blockPos;
}
}
SpreadFire(position);
}
private void SpreadFire(Vector3 position)
{
var targetBlock = GameManager.Instance.World.GetBlock(new Vector3i(position));
var range = (int)maxRange;
for (var x = -range; x <= range; x++)
{
for (var z = -range; z <= range; z++)
{
for (var y = -range; y <= range; y++)
{
var vector = new Vector3i(position.x + x, position.y + y, position.z + z);
var neighborBlock = GameManager.Instance.World.GetBlock(vector);
switch (_filterType)
{
case FilterTypeCascade.Type:
if (neighborBlock.type == targetBlock.type)
FireManager.Instance.Add(vector);
break;
case FilterTypeCascade.Material:
if (neighborBlock.Block.blockMaterial.id == targetBlock.Block.blockMaterial.id)
FireManager.Instance.Add(vector);
break;
case FilterTypeCascade.MaterialDamage:
if (neighborBlock.Block.blockMaterial.DamageCategory ==
targetBlock.Block.blockMaterial.DamageCategory)
FireManager.Instance.Add(vector);
break;
case FilterTypeCascade.MaterialSurface:
if (neighborBlock.Block.blockMaterial.SurfaceCategory ==
targetBlock.Block.blockMaterial.SurfaceCategory)
FireManager.Instance.Add(vector);
break;
}
}
}
}
}
public override bool ParseXmlAttribute(XAttribute attribute)
{
var flag = base.ParseXmlAttribute(attribute);
if (flag) return true;
var name = attribute.Name.LocalName;
if (name != "filter") return false;
_filterType = EnumUtils.Parse<FilterTypeCascade>(attribute.Value, true);
return true;
}
}

View File

@@ -0,0 +1,42 @@
using JetBrains.Annotations;
using System.Xml.Linq;
/// <summary>
/// Checks to see if there's any fire blocks within the specified range, using the player's position as center.
/// </summary>
/// <remarks>
/// Example:
///
/// The cvar specified, by default _closeFires, will contain the number of burning blocks in the range.
/// <triggered_effect trigger="onSelfBuffUpdate" action="CheckFireProximity, SCore" range="5" cvar="_closeFires" />
/// </remarks>
[UsedImplicitly]
public class MinEventActionCheckFireProximity : MinEventActionRemoveBuff
{
string cvar = "_closeFires";
public override void Execute(MinEventParams @params)
{
if (FireManager.Instance.Enabled == false) return;
var position = new Vector3i(@params.Self.position);
var count = FireManager.Instance.CloseFires(position, (int)maxRange);
if (count == 0)
count = -1;
@params.Self.Buffs.SetCustomVar(cvar, count);
}
public override bool ParseXmlAttribute(XAttribute attribute)
{
var flag = base.ParseXmlAttribute(attribute);
if (flag) return true;
var name = attribute.Name.LocalName;
if (name != "cvar") return false;
cvar = attribute.Value;
return true;
}
}

View File

@@ -0,0 +1,46 @@
using JetBrains.Annotations;
/// <summary>
/// Remove Fire within the specified range, using the specified target.
/// </summary>
/// <remarks>
/// Example:
/// This will remove fire from all blocks with a range of 5 from the position of the target.
/// <triggered_effect trigger="onSelfDamagedBlock" action="RemoveFire, SCore" target="positionAOE" range="5"/>
/// </remarks>
[UsedImplicitly]
public class MinEventActionRemoveFire : MinEventActionRemoveBuff
{
private static readonly string AdvFeatureClass = "FireManagement";
public override void Execute(MinEventParams @params)
{
if (FireManager.Instance == null) return;
if (FireManager.Instance.Enabled == false) return;
var position = @params.Position;
if (targetType != TargetTypes.positionAOE)
{
if (Voxel.voxelRayHitInfo.bHitValid)
{
var hitInfo = Voxel.voxelRayHitInfo;
if (hitInfo == null) return;
position = hitInfo.hit.blockPos;
}
}
var range = (int)maxRange;
for (var x = -range; x <= range; x++)
{
for (var z = -range; z <= range; z++)
{
for (var y = -range; y <= range; y++)
{
var vector = new Vector3i(position.x + x, position.y + y, position.z + z);
if (!FireManager.IsBurning(vector)) continue;
FireManager.Instance.Extinguish(vector);
}
}
}
}
}

View File

@@ -0,0 +1,47 @@
using JetBrains.Annotations;
/// <summary>
/// Distributes the call to all clients to extinguish a block
/// </summary>
[UsedImplicitly]
public class NetPackageAddExtinguishPosition : NetPackage
{
private Vector3i _position;
private int _entityThatCausedIt;
public NetPackageAddExtinguishPosition Setup(Vector3i position, int entityThatCausedIt)
{
_position = position;
_entityThatCausedIt = entityThatCausedIt;
return this;
}
public override void read(PooledBinaryReader br)
{
_position = new Vector3i(br.ReadInt32(), br.ReadInt32(), br.ReadInt32());
_entityThatCausedIt = br.ReadInt32();
}
public override void write(PooledBinaryWriter bw)
{
base.write(bw);
bw.Write(_position.x);
bw.Write(_position.y);
bw.Write(_position.z);
bw.Write(_entityThatCausedIt);
}
public override int GetLength()
{
return 20;
}
public override void ProcessPackage(World world, GameManager callbacks)
{
if (world == null || FireManager.Instance == null) return;
FireManager.Instance.ExtinguishBlock(_position);
}
}

View File

@@ -0,0 +1,47 @@
using JetBrains.Annotations;
/// <summary>
/// Distributes the call to all clients to add a block that is considered burning.
/// </summary>
[UsedImplicitly]
public class NetPackageAddFirePosition : NetPackage
{
private Vector3i _position;
private int _entityThatCausedIt;
public NetPackageAddFirePosition Setup(Vector3i position, int entityThatCausedIt)
{
_position = position;
_entityThatCausedIt = entityThatCausedIt;
return this;
}
public override void read(PooledBinaryReader br)
{
_position = new Vector3i(br.ReadInt32(), br.ReadInt32(), br.ReadInt32());
_entityThatCausedIt = br.ReadInt32();
}
public override void write(PooledBinaryWriter bw)
{
base.write(bw);
bw.Write(_position.x);
bw.Write(_position.y);
bw.Write(_position.z);
bw.Write(_entityThatCausedIt);
}
public override int GetLength()
{
return 20;
}
public override void ProcessPackage(World world, GameManager callbacks)
{
if (world == null || FireManager.Instance == null) return;
FireManager.Instance.AddBlock(_position);
}
}

View File

@@ -0,0 +1,52 @@
using JetBrains.Annotations;
/// <summary>
/// Distributes the call to all clients to remove a block that is considered burning.
/// </summary>
[UsedImplicitly]
public class NetPackageRemoveFirePosition : NetPackage
{
private Vector3i _position;
private int _entityThatCausedIt;
public NetPackageRemoveFirePosition Setup(Vector3i position, int entityThatCausedIt)
{
_position = position;
_entityThatCausedIt = entityThatCausedIt;
return this;
}
public override void read(PooledBinaryReader br)
{
_position = new Vector3i(br.ReadInt32(), br.ReadInt32(), br.ReadInt32());
_entityThatCausedIt = br.ReadInt32();
}
public override void write(PooledBinaryWriter bw)
{
base.write(bw);
bw.Write(_position.x);
bw.Write(_position.y);
bw.Write(_position.z);
bw.Write(_entityThatCausedIt);
}
public override int GetLength()
{
return 20;
}
public override void ProcessPackage(World world, GameManager callbacks)
{
if (world == null)
{
return;
}
if (FireManager.Instance != null)
{
FireManager.Instance.RemoveFire(_position);
}
}
}

View File

@@ -0,0 +1,51 @@
using JetBrains.Annotations;
/// <summary>
/// Distributes the call to remove a particle effect to all clients. This is used by the Fire management system.
/// </summary>
/// <remarks>
/// This allows us to distribute which block is showing a fire particle.
/// </remarks>
///
[UsedImplicitly]
public class NetPackageRemoveParticleEffect : NetPackage
{
private Vector3i _position;
private int _entityThatCausedIt;
public NetPackageRemoveParticleEffect Setup(Vector3i position, int entityThatCausedIt)
{
_position = position;
_entityThatCausedIt = entityThatCausedIt;
return this;
}
public override void read(PooledBinaryReader br)
{
_position = new Vector3i(br.ReadInt32(), br.ReadInt32(), br.ReadInt32());
_entityThatCausedIt = br.ReadInt32();
}
public override void write(PooledBinaryWriter bw)
{
base.write(bw);
bw.Write(_position.x);
bw.Write(_position.y);
bw.Write(_position.z);
bw.Write(_entityThatCausedIt);
}
public override int GetLength()
{
return 20;
}
public override void ProcessPackage(World world, GameManager callbacks)
{
if (world == null || FireManager.Instance == null) return;
FireManager.Instance.ClearPosOnly(_position);
}
}