87 lines
3.1 KiB
C#
87 lines
3.1 KiB
C#
using Cysharp.Threading.Tasks;
|
|
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
using Random = Unity.Mathematics.Random;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
public class TreeResourcesGeneratorOperation : IWorldGeneratorOperation
|
|
{
|
|
[InjectService]
|
|
private GameConfig _config;
|
|
|
|
[InjectService]
|
|
private ITileSpace _tileSpace;
|
|
|
|
public async UniTask Execute(World world)
|
|
{
|
|
await GenerateTreesAsync(world);
|
|
}
|
|
|
|
private async UniTask GenerateTreesAsync(World world)
|
|
{
|
|
var config = _config.WorldGen;
|
|
var treeDefinition = await config.Trees.TreeDefinition.LoadAssetAsync<ResourceNodeDefinition>();
|
|
|
|
var horizontalResolution = Mathf.FloorToInt(world.Size.x / config.Trees.Spacing);
|
|
var verticalResolution = Mathf.FloorToInt(world.Size.y / config.Trees.Spacing);
|
|
|
|
var random = new Random((uint)world.Seed);
|
|
var noiseSalt = world.Seed % ushort.MaxValue * 37;
|
|
|
|
for (var x = 0; x < horizontalResolution; x++)
|
|
for (var z = 0; z < verticalResolution; z++)
|
|
{
|
|
var treePosition = new Vector3((x + 0.5f) * config.Trees.Spacing, 0, (z + 0.5f) * config.Trees.Spacing);
|
|
if (z % 2 == 0) treePosition.x += 0.5f * config.Trees.Spacing;
|
|
|
|
treePosition.x += Mathf.Lerp(config.Trees.OffsetRange.x, config.Trees.OffsetRange.y, random.NextFloat());
|
|
treePosition.z += Mathf.Lerp(config.Trees.OffsetRange.x, config.Trees.OffsetRange.y, random.NextFloat());
|
|
|
|
var tile = _tileSpace.WorldToTile(treePosition);
|
|
|
|
if (!EnoughSpaceAround(world, tile)) continue;
|
|
|
|
var h = world.Heightmap.GetValue(tile);
|
|
if (h == 0) continue;
|
|
|
|
treePosition.y = h;
|
|
|
|
var noiseSamplePos = new float2(h * 997 + x, noiseSalt + z) * config.Trees.NoiseScale;
|
|
var n = noise.snoise(noiseSamplePos);
|
|
if (n < 1 - config.Trees.Coverage && random.NextFloat() < 1 - config.Trees.RandomTreeChance) continue;
|
|
|
|
world.RawResources.AddResourceNode(
|
|
new ResourceNode
|
|
{
|
|
Id = 1 + world.RawResources.Count,
|
|
DefinitionId = treeDefinition.RuntimeId,
|
|
Position = treePosition,
|
|
Tile = tile,
|
|
Elevation = _tileSpace.GetElevation(treePosition.y),
|
|
CanBeDeleted = true
|
|
});
|
|
|
|
world.BlockMap.AddReason(tile, BlockReason.RawResource);
|
|
}
|
|
}
|
|
|
|
private static bool EnoughSpaceAround(World world, int2 center)
|
|
{
|
|
const int radius = 1;
|
|
|
|
for (var x = -radius; x <= radius; x++)
|
|
for (var y = -radius; y <= radius; y++)
|
|
{
|
|
var p = center + new int2(x, y);
|
|
|
|
if (!world.Contains(p)) continue;
|
|
|
|
if (world.Fertility.GetValue(p).MaxFertility > 0) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|