mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-24 05:10:42 -04:00
118 lines
3.8 KiB
C#
118 lines
3.8 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using ClassicalSharp.Map;
|
|
|
|
namespace ClassicalSharp.Singleplayer {
|
|
|
|
public class FoilagePhysics {
|
|
Game game;
|
|
World map;
|
|
Random rnd = new Random();
|
|
|
|
public FoilagePhysics( Game game, Physics physics ) {
|
|
this.game = game;
|
|
map = game.World;
|
|
|
|
physics.OnPlace[(byte)Block.Sapling] = HandleSapling;
|
|
physics.OnActivate[(byte)Block.Sapling] = HandleSapling;
|
|
physics.OnActivate[(byte)Block.Dirt] = HandleDirt;
|
|
physics.OnActivate[(byte)Block.Grass] = HandleGrass;
|
|
|
|
physics.OnActivate[(byte)Block.Dandelion] = HandleFlower;
|
|
physics.OnActivate[(byte)Block.Rose] = HandleFlower;
|
|
physics.OnActivate[(byte)Block.RedMushroom] = HandleFlower;
|
|
physics.OnActivate[(byte)Block.BrownMushroom] = HandleFlower;
|
|
}
|
|
|
|
void HandleSapling( int index, byte block ) {
|
|
int x = index % map.Width;
|
|
int y = (index / map.Width) / map.Length;
|
|
int z = (index / map.Width) % map.Length;
|
|
GrowTree( x, y, z );
|
|
}
|
|
|
|
void HandleDirt( int index, byte block ) {
|
|
int x = index % map.Width;
|
|
int y = (index / map.Width) / map.Length;
|
|
int z = (index / map.Width) % map.Length;
|
|
if( y > map.GetLightHeight( x, z ) )
|
|
game.UpdateBlock( x, y, z, (byte)Block.Grass );
|
|
}
|
|
|
|
void HandleGrass( int index, byte block ) {
|
|
int x = index % map.Width;
|
|
int y = (index / map.Width) / map.Length;
|
|
int z = (index / map.Width) % map.Length;
|
|
if( y <= map.GetLightHeight( x, z ) )
|
|
game.UpdateBlock( x, y, z, (byte)Block.Dirt );
|
|
}
|
|
|
|
void HandleFlower( int index, byte block ) {
|
|
int x = index % map.Width;
|
|
int y = (index / map.Width) / map.Length;
|
|
int z = (index / map.Width) % map.Length;
|
|
if( y <= map.GetLightHeight( x, z ) )
|
|
game.UpdateBlock( x, y, z, (byte)Block.Air );
|
|
}
|
|
|
|
// Algorithm source: Looking at the trees generated by the default classic server.
|
|
// Hence, the random thresholds may be slightly off.
|
|
public void GrowTree( int x, int y, int z ) {
|
|
int trunkH = rnd.Next( 1, 4 );
|
|
game.UpdateBlock( x, y, z, 0 );
|
|
|
|
// Can the new tree grow?
|
|
if( !CheckBounds( x, x, y, y + trunkH - 1, z, z ) ||
|
|
!CheckBounds( x - 2, x + 2, y + trunkH, y + trunkH + 1, z - 2, z + 2 ) ||
|
|
!CheckBounds( x - 1, x + 1, y + trunkH + 2, y + trunkH + 3, z - 1, z + 1 ) ) {
|
|
game.UpdateBlock( x, y, z, 0 );
|
|
return;
|
|
}
|
|
|
|
// Leaves bottom layer
|
|
y += trunkH;
|
|
for( int zz = -2; zz <= 2; zz++ ) {
|
|
for( int xx = -2; xx <= 2; xx++ ) {
|
|
if( Math.Abs( xx ) == 2 && Math.Abs( zz ) == 2 ) {
|
|
if( rnd.Next( 0, 5 ) < 4 ) game.UpdateBlock( x + xx, y, z + zz, (byte)Block.Leaves );
|
|
if( rnd.Next( 0, 5 ) < 2 ) game.UpdateBlock( x + xx, y + 1, z + zz, (byte)Block.Leaves );
|
|
} else {
|
|
game.UpdateBlock( x + xx, y, z + zz, (byte)Block.Leaves );
|
|
game.UpdateBlock( x + xx, y + 1, z + zz, (byte)Block.Leaves );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Leaves top layer
|
|
y += 2;
|
|
for( int zz = -1; zz <= 1; zz++ ) {
|
|
for( int xx = -1; xx <= 1; xx++ ) {
|
|
if( xx == 0 || zz == 0 ) {
|
|
game.UpdateBlock( x + xx, y, z + zz, (byte)Block.Leaves );
|
|
game.UpdateBlock( x + xx, y + 1, z + zz, (byte)Block.Leaves );
|
|
} else if( rnd.Next( 0, 5 ) == 0 ) {
|
|
game.UpdateBlock( x + xx, y, z + zz, (byte)Block.Leaves );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Base trunk
|
|
y -= 2 + trunkH;
|
|
for( int yy = 0; yy < trunkH + 3; yy++ )
|
|
game.UpdateBlock( x, y + yy, z, (byte)Block.Log );
|
|
}
|
|
|
|
bool CheckBounds( int x1, int x2, int y1, int y2, int z1, int z2 ) {
|
|
for( int y = y1; y <= y2; y++ )
|
|
for( int z = z1; z <= z2; z++ )
|
|
for( int x = x1; x <= x2; x++ )
|
|
{
|
|
if( !map.IsValidPos( x, y, z ) ) return false;
|
|
|
|
byte block = map.GetBlock( x, y, z );
|
|
if( !(block == 0 || block == (byte)Block.Leaves ) ) return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
} |