Skip to content

Commit d6c1c34

Browse files
jstzwjsunnycase
authored andcommitted
Add decorations of terrain (#45)
* Improve block id. * Improve blocks state. * Improve blocks state. * Add plants generators * Improve blocks state. * clean code style * Fix name. * Add BlockAccessorGrain * Add grass generator * Add flowers generator * Add world extensions and blockstate extensions * Add minable generator * Update generate settings * Generate generator settings from server settings * Test Ore Generator * Add different position types * Add more methods * Merge from position types branch * Add tree generator * Better ore generator * clean code
1 parent 134a2c8 commit d6c1c34

23 files changed

+1416
-92
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using System.Threading.Tasks;
5+
using Orleans;
6+
using Orleans.Concurrency;
7+
8+
namespace MineCase.Server.World
9+
{
10+
[StatelessWorker]
11+
public class BlockAccessorGrain : Grain, IBlockAccessor
12+
{
13+
private IWorld _world;
14+
15+
public override Task OnActivateAsync()
16+
{
17+
_world = GrainFactory.GetGrain<IWorld>(this.GetPrimaryKeyString());
18+
return base.OnActivateAsync();
19+
}
20+
21+
public async Task<BlockState> GetBlockState(int x, int y, int z)
22+
{
23+
// 需要优化??
24+
var chunkColumn = GrainFactory.GetGrain<IChunkColumn>(_world.MakeChunkColumnKey(x / 16, z / 16));
25+
int offsetX = x % 16;
26+
int offsetZ = z % 16;
27+
if (offsetX < 0) offsetX += 16;
28+
if (offsetZ < 0) offsetZ += 16;
29+
return await chunkColumn.GetBlockState(offsetX, y, offsetZ);
30+
}
31+
32+
public Task SetBlockState(int x, int y, int z, BlockState state)
33+
{
34+
// 需要优化??
35+
var chunkColumn = GrainFactory.GetGrain<IChunkColumn>(_world.MakeChunkColumnKey(x / 16, z / 16));
36+
int offsetX = x % 16;
37+
int offsetZ = z % 16;
38+
if (offsetX < 0) offsetX += 16;
39+
if (offsetZ < 0) offsetZ += 16;
40+
41+
// await chunkColumn.SetBlockState(state, offsetX, y, offsetZ);
42+
return Task.CompletedTask;
43+
}
44+
45+
public async Task<bool> CanBlockStay(int x, int y, int z, BlockState state)
46+
{
47+
if (state == BlockStates.Poppy())
48+
{
49+
if (y > 0)
50+
{
51+
var downState = await GetBlockState(x, y - 1, z);
52+
if (downState == BlockStates.Dirt() ||
53+
downState == BlockStates.Grass())
54+
{
55+
return true;
56+
}
57+
}
58+
59+
return false;
60+
}
61+
else
62+
{
63+
return true;
64+
}
65+
}
66+
}
67+
}

src/MineCase.Server.Grains/World/ChunkColumnGrain.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private async Task EnsureChunkGenerated()
124124
GeneratorSettings settings = new GeneratorSettings
125125
{
126126
};
127-
_state = await generator.Generate(_chunkX, _chunkZ, settings);
127+
_state = await generator.Generate(_world, _chunkX, _chunkZ, settings);
128128
}
129129
}
130130
}

src/MineCase.Server.Grains/World/Generation/ChunkGeneratorFlatGrain.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@ namespace MineCase.Server.World.Generation
1212
[StatelessWorker]
1313
internal class ChunkGeneratorFlatGrain : Grain, IChunkGeneratorFlat
1414
{
15-
public Task<ChunkColumnStorage> Generate(int x, int z, GeneratorSettings settings)
15+
public Task<ChunkColumnStorage> Generate(IWorld world, int x, int z, GeneratorSettings settings)
1616
{
1717
var chunkColumn = new ChunkColumnStorage();
1818
for (int i = 0; i < chunkColumn.Sections.Length; ++i)
1919
chunkColumn.Sections[i] = new ChunkSectionStorage(true);
2020

21-
GenerateChunk(chunkColumn, x, z, settings);
22-
PopulateChunk(chunkColumn, x, z, settings);
21+
GenerateChunk(world, chunkColumn, x, z, settings);
22+
PopulateChunk(world, chunkColumn, x, z, settings);
2323
return Task.FromResult(chunkColumn);
2424
}
2525

26-
private void GenerateChunk(ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
26+
private void GenerateChunk(IWorld world, ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
2727
{
2828
// 按照flat模式每层的设置给chunk赋值
29-
for (int y = 0; y < settings.FlatGeneratorInfo.FlatBlockId.Length; ++y)
29+
for (int y = 0; y < settings.FlatBlockId.Length; ++y)
3030
{
3131
var section = chunk.Sections[y / 16];
32-
var state = settings.FlatGeneratorInfo.FlatBlockId[y];
32+
var state = settings.FlatBlockId[y];
3333
if (state != null)
3434
{
3535
for (int j = 0; j < 16; ++j)
@@ -46,7 +46,7 @@ private void GenerateChunk(ChunkColumnStorage chunk, int x, int z, GeneratorSett
4646
// todo biomes
4747
}
4848

49-
private void PopulateChunk(ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
49+
private void PopulateChunk(IWorld world, ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
5050
{
5151
// TODO generator tree, grass, structures\
5252
}

src/MineCase.Server.Grains/World/Generation/ChunkGeneratorOverworldGrain.cs

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ public override Task OnActivateAsync()
4848

4949
int seed = (int)this.GetPrimaryKeyLong();
5050
_random = new Random(seed);
51-
_depthNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 4, 0.5f);
52-
_mainNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 4, 0.5f);
53-
_maxNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 4, 0.5f);
54-
_minNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 4, 0.5f);
55-
_surfaceNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 4, 0.5f);
51+
_depthNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 8, 0.5F);
52+
_mainNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 8, 0.5F);
53+
_maxNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 8, 0.5F);
54+
_minNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 8, 0.5F);
55+
_surfaceNoise = new OctavedNoise<PerlinNoise>(new PerlinNoise(_random.Next()), 8, 0.5F);
5656

5757
_biomeWeights = new float[5, 5];
5858
for (int i = -2; i <= 2; ++i)
@@ -64,45 +64,62 @@ public override Task OnActivateAsync()
6464
}
6565
}
6666

67-
// 生物群系先暂时初始化成这样,以后修改
68-
_biomesForGeneration = new Biome[16, 16];
69-
for (int i = 0; i < 16; ++i)
70-
{
71-
for (int j = 0; j < 16; ++j)
72-
{
73-
_biomesForGeneration[i, j] = new BiomePlains(new BiomeProperties("plains"));
74-
}
75-
}
76-
7767
return Task.CompletedTask;
7868
}
7969

80-
public async Task<ChunkColumnStorage> Generate(int x, int z, GeneratorSettings settings)
70+
public async Task<ChunkColumnStorage> Generate(IWorld world, int x, int z, GeneratorSettings settings)
8171
{
8272
var chunkColumn = new ChunkColumnStorage();
8373
for (int i = 0; i < chunkColumn.Sections.Length; ++i)
8474
chunkColumn.Sections[i] = new ChunkSectionStorage(true);
8575

86-
await GenerateChunk(chunkColumn, x, z, settings);
87-
await PopulateChunk(chunkColumn, x, z, settings);
76+
await GenerateChunk(world, chunkColumn, x, z, settings);
77+
await PopulateChunk(world, chunkColumn, x, z, settings);
8878
return chunkColumn;
8979
}
9080

91-
public async Task GenerateChunk(ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
81+
public async Task GenerateChunk(IWorld world, ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
9282
{
9383
// GetBiomesForGeneration(_biomesForGeneration, x * 4 - 2, z * 4 - 2, 10, 10);
84+
// 生物群系生成
85+
// 生物群系先暂时初始化成这样,以后修改
86+
_biomesForGeneration = new Biome[16, 16];
87+
for (int i = 0; i < 16; ++i)
88+
{
89+
for (int j = 0; j < 16; ++j)
90+
{
91+
_biomesForGeneration[i, j] = new BiomePlains(new BiomeProperties { BiomeName = "plains" }, settings);
92+
}
93+
}
94+
95+
// 设置生物群系
96+
for (int i = 0; i < 16; ++i)
97+
{
98+
for (int j = 0; j < 16; ++j)
99+
{
100+
chunk.Biomes[i * 16 + j] = (byte)_biomesForGeneration[i, j].GetBiomeId();
101+
}
102+
}
103+
104+
// 基本地形生成
94105
await GenerateBasicTerrain(chunk, x, z, settings);
95106

96-
// Todo add biomes blocks
107+
// 添加生物群系特有方块
97108
await ReplaceBiomeBlocks(settings, x, z, chunk, _biomesForGeneration);
98109

99110
// Todo genrate structure
111+
112+
// 计算skylight
100113
await GenerateSkylightMap(chunk);
101114
}
102115

103-
public Task PopulateChunk(ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
116+
public async Task PopulateChunk(IWorld world, ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
104117
{
105-
return Task.CompletedTask;
118+
int blockX = x * 16;
119+
int blockZ = z * 16;
120+
Biome chunkBiome = Biome.GetBiome(chunk.Biomes[7 * 16 + 7], settings);
121+
122+
await chunkBiome.Decorate(world, GrainFactory, chunk, _random, new BlockWorldPos { X = blockX, Y = 0, Z = blockZ });
106123
}
107124

108125
private async Task GenerateBasicTerrain(ChunkColumnStorage chunk, int x, int z, GeneratorSettings settings)
@@ -112,16 +129,14 @@ private async Task GenerateBasicTerrain(ChunkColumnStorage chunk, int x, int z,
112129

113130
for (int xHigh = 0; xHigh < 4; ++xHigh)
114131
{
115-
int xPart1 = xHigh * 5;
116-
int xPart2 = (xHigh + 1) * 5;
117-
132+
// int xPart1 = xHigh * 5;
133+
// int xPart2 = (xHigh + 1) * 5;
118134
for (int zHigh = 0; zHigh < 4; ++zHigh)
119135
{
120-
int zPart11 = (xPart1 + zHigh) * 33;
121-
int zPart12 = (xPart1 + zHigh + 1) * 33;
122-
int zPart21 = (xPart2 + zHigh) * 33;
123-
int zPart22 = (xPart2 + zHigh + 1) * 33;
124-
136+
// int zPart11 = (xPart1 + zHigh) * 33;
137+
// int zPart12 = (xPart1 + zHigh + 1) * 33;
138+
// int zPart21 = (xPart2 + zHigh) * 33;
139+
// int zPart22 = (xPart2 + zHigh + 1) * 33;
125140
for (int yHigh = 0; yHigh < 32; ++yHigh)
126141
{
127142
double yPart111 = _densityMap[xHigh, yHigh, zHigh];

src/MineCase.Server.Grains/World/WorldGrain.cs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.Text;
44
using System.Threading.Tasks;
55
using MineCase.Server.Game;
6+
using MineCase.Server.Settings;
7+
using MineCase.Server.World.Generation;
68
using Orleans;
79
using Orleans.Concurrency;
810

@@ -14,12 +16,20 @@ internal class WorldGrain : Grain, IWorld
1416
private Dictionary<uint, IEntity> _entities;
1517
private uint _nextAvailEId;
1618
private long _worldAge;
19+
private IBlockAccessor _blockAccessor;
20+
private GeneratorSettings _genSettings; // 生成设置
21+
private string _seed; // 世界种子
1722

18-
public override Task OnActivateAsync()
23+
public override async Task OnActivateAsync()
1924
{
25+
IServerSettings serverSettings = GrainFactory.GetGrain<IServerSettings>(0);
2026
_nextAvailEId = 0;
2127
_entities = new Dictionary<uint, IEntity>();
22-
return base.OnActivateAsync();
28+
_blockAccessor = GrainFactory.GetGrain<IBlockAccessor>(this.GetPrimaryKeyString());
29+
_genSettings = new GeneratorSettings();
30+
await InitGeneratorSettings(_genSettings);
31+
_seed = (await serverSettings.GetSettings()).LevelSeed;
32+
await base.OnActivateAsync();
2333
}
2434

2535
public Task AttachEntity(IEntity entity)
@@ -53,5 +63,34 @@ public Task OnGameTick(TimeSpan deltaTime)
5363
}
5464

5565
public Task<long> GetAge() => Task.FromResult(_worldAge);
66+
67+
public Task<IBlockAccessor> GetBlockAccessor()
68+
{
69+
return Task.FromResult(_blockAccessor);
70+
}
71+
72+
public Task<int> GetSeed()
73+
{
74+
int result = 0;
75+
foreach (char c in _seed)
76+
{
77+
result = result * 127 + (int)c;
78+
}
79+
80+
return Task.FromResult(result);
81+
}
82+
83+
public Task<GeneratorSettings> GetGeneratorSettings()
84+
{
85+
return Task.FromResult(_genSettings);
86+
}
87+
88+
private Task InitGeneratorSettings(GeneratorSettings settings)
89+
{
90+
IServerSettings serverSettings = GrainFactory.GetGrain<IServerSettings>(0);
91+
92+
// TODO move server settings to generator settings
93+
return Task.CompletedTask;
94+
}
5695
}
5796
}

src/MineCase.Server.Interfaces/MineCase.Server.Interfaces.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
</ItemGroup>
1616

1717
<ItemGroup>
18+
<ProjectReference Include="..\MineCase.Algorithm\MineCase.Algorithm.csproj" />
1819
<ProjectReference Include="..\MineCase.Protocol\MineCase.Protocol.csproj" />
1920
</ItemGroup>
2021

0 commit comments

Comments
 (0)