UnknownShadow200 98d435b110 fix licensing
2017-01-20 09:12:04 +11:00

152 lines
4.5 KiB
C#

// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using ClassicalSharp.Map;
namespace ClassicalSharp.Singleplayer {
public class FoilagePhysics {
Game game;
PhysicsBase physics;
World map;
Random rnd = new Random();
public FoilagePhysics(Game game, PhysicsBase physics) {
this.game = game;
this.physics = physics;
map = game.World;
physics.OnPlace[Block.Sapling] = HandleSapling;
physics.OnRandomTick[Block.Sapling] = HandleSapling;
physics.OnRandomTick[Block.Dirt] = HandleDirt;
physics.OnRandomTick[Block.Grass] = HandleGrass;
physics.OnRandomTick[Block.Dandelion] = HandleFlower;
physics.OnRandomTick[Block.Rose] = HandleFlower;
physics.OnRandomTick[Block.RedMushroom] = HandleMushroom;
physics.OnRandomTick[Block.BrownMushroom] = HandleMushroom;
}
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 (game.Lighting.IsLit(x, y, z))
game.UpdateBlock(x, y, z, 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 (!game.Lighting.IsLit(x, y, z))
game.UpdateBlock(x, y, z, 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 (!game.Lighting.IsLit(x, y, z)) {
game.UpdateBlock(x, y, z, Block.Air);
physics.ActivateNeighbours(x, y, z, index);
return;
}
byte below = Block.Dirt;
if (y > 0) below = map.blocks[index - map.Width * map.Length];
if (!(below == Block.Dirt || below == Block.Grass)) {
game.UpdateBlock(x, y, z, Block.Air);
physics.ActivateNeighbours(x, y, z, index);
}
}
void HandleMushroom(int index, byte block) {
int x = index % map.Width;
int y = (index / map.Width) / map.Length;
int z = (index / map.Width) % map.Length;
if (game.Lighting.IsLit(x, y, z)) {
game.UpdateBlock(x, y, z, Block.Air);
physics.ActivateNeighbours(x, y, z, index);
return;
}
byte below = Block.Stone;
if (y > 0) below = map.blocks[index - map.Width * map.Length];
if (!(below == Block.Stone || below == Block.Cobblestone)) {
game.UpdateBlock(x, y, z, Block.Air);
physics.ActivateNeighbours(x, y, z, index);
}
}
// 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, Block.Leaves);
if (rnd.Next(0, 5) < 2) game.UpdateBlock(x + xx, y + 1, z + zz, Block.Leaves);
} else {
game.UpdateBlock(x + xx, y, z + zz, Block.Leaves);
game.UpdateBlock(x + xx, y + 1, z + zz, 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, Block.Leaves);
game.UpdateBlock(x + xx, y + 1, z + zz, Block.Leaves);
} else if (rnd.Next(0, 5) == 0) {
game.UpdateBlock(x + xx, y, z + zz, Block.Leaves);
}
}
}
// Base trunk
y -= 2 + trunkH;
for (int yy = 0; yy < trunkH + 3; yy++)
game.UpdateBlock(x, y + yy, z, 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 == Block.Leaves)) return false;
}
return true;
}
}
}