Umbrella tree update
|
@ -25,11 +25,13 @@ import net.minecraft.state.property.IntProperty;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import ru.betterend.blocks.basis.BlockBase;
|
import ru.betterend.blocks.basis.BlockBase;
|
||||||
import ru.betterend.interfaces.IColorProvider;
|
import ru.betterend.interfaces.IColorProvider;
|
||||||
|
import ru.betterend.noise.OpenSimplexNoise;
|
||||||
import ru.betterend.registry.EndBlocks;
|
import ru.betterend.registry.EndBlocks;
|
||||||
import ru.betterend.util.MHelper;
|
import ru.betterend.util.MHelper;
|
||||||
|
|
||||||
public class BlockHelixTreeLeaves extends BlockBase implements IColorProvider {
|
public class BlockHelixTreeLeaves extends BlockBase implements IColorProvider {
|
||||||
public static final IntProperty COLOR = IntProperty.of("color", 0, 7);
|
public static final IntProperty COLOR = IntProperty.of("color", 0, 7);
|
||||||
|
private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0);
|
||||||
|
|
||||||
public BlockHelixTreeLeaves() {
|
public BlockHelixTreeLeaves() {
|
||||||
super(FabricBlockSettings.of(Material.LEAVES)
|
super(FabricBlockSettings.of(Material.LEAVES)
|
||||||
|
@ -61,7 +63,10 @@ public class BlockHelixTreeLeaves extends BlockBase implements IColorProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||||
return this.getDefaultState().with(COLOR, MHelper.randRange(3, 5, ctx.getWorld().getRandom()));
|
double px = ctx.getBlockPos().getX() * 0.1;
|
||||||
|
double py = ctx.getBlockPos().getY() * 0.1;
|
||||||
|
double pz = ctx.getBlockPos().getZ() * 0.1;
|
||||||
|
return this.getDefaultState().with(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getGreen(int color) {
|
private int getGreen(int color) {
|
||||||
|
|
|
@ -5,25 +5,51 @@ import java.util.List;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||||
import net.minecraft.block.AbstractGlassBlock;
|
import net.minecraft.block.AbstractGlassBlock;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.item.ItemPlacementContext;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.loot.context.LootContext;
|
import net.minecraft.loot.context.LootContext;
|
||||||
|
import net.minecraft.state.StateManager;
|
||||||
|
import net.minecraft.state.property.IntProperty;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.registry.Registry;
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraft.world.BlockView;
|
||||||
import ru.betterend.client.render.ERenderLayer;
|
import ru.betterend.client.render.ERenderLayer;
|
||||||
import ru.betterend.interfaces.IRenderTypeable;
|
import ru.betterend.interfaces.IRenderTypeable;
|
||||||
|
import ru.betterend.noise.OpenSimplexNoise;
|
||||||
import ru.betterend.patterns.BlockPatterned;
|
import ru.betterend.patterns.BlockPatterned;
|
||||||
import ru.betterend.patterns.Patterns;
|
import ru.betterend.patterns.Patterns;
|
||||||
import ru.betterend.registry.EndItems;
|
import ru.betterend.util.MHelper;
|
||||||
|
|
||||||
public class BlockUmbrellaTreeMembrane extends AbstractGlassBlock implements IRenderTypeable, BlockPatterned {
|
public class BlockUmbrellaTreeMembrane extends AbstractGlassBlock implements IRenderTypeable, BlockPatterned {
|
||||||
|
public static final IntProperty COLOR = IntProperty.of("color", 0, 7);
|
||||||
|
private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0);
|
||||||
|
|
||||||
public BlockUmbrellaTreeMembrane() {
|
public BlockUmbrellaTreeMembrane() {
|
||||||
super(FabricBlockSettings.copyOf(Blocks.SLIME_BLOCK));
|
super(FabricBlockSettings.copyOf(Blocks.SLIME_BLOCK));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||||
|
double px = ctx.getBlockPos().getX() * 0.1;
|
||||||
|
double py = ctx.getBlockPos().getY() * 0.1;
|
||||||
|
double pz = ctx.getBlockPos().getZ() * 0.1;
|
||||||
|
return this.getDefaultState().with(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
|
||||||
|
stateManager.add(COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ERenderLayer getRenderLayer() {
|
public ERenderLayer getRenderLayer() {
|
||||||
return ERenderLayer.TRANSLUCENT;
|
return ERenderLayer.TRANSLUCENT;
|
||||||
|
@ -31,7 +57,7 @@ public class BlockUmbrellaTreeMembrane extends AbstractGlassBlock implements IRe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||||
return Lists.newArrayList(new ItemStack(EndItems.CRYSTAL_SHARDS));
|
return Lists.newArrayList(new ItemStack(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,4 +76,19 @@ public class BlockUmbrellaTreeMembrane extends AbstractGlassBlock implements IRe
|
||||||
public Identifier statePatternId() {
|
public Identifier statePatternId() {
|
||||||
return Patterns.STATE_SIMPLE;
|
return Patterns.STATE_SIMPLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTranslucent(BlockState state, BlockView world, BlockPos pos) {
|
||||||
|
return state.get(COLOR) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
|
||||||
|
if (state.get(COLOR) > 0) {
|
||||||
|
return super.isSideInvisible(state, stateFrom, direction);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,10 @@ public class MHelper {
|
||||||
return (float) Math.sqrt(lengthSqr(x, y, z));
|
return (float) Math.sqrt(lengthSqr(x, y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double length(double x, double y, double z) {
|
||||||
|
return Math.sqrt(lengthSqr(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
public static float lengthSqr(float x, float y) {
|
public static float lengthSqr(float x, float y) {
|
||||||
return x * x + y * y;
|
return x * x + y * y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,14 +10,15 @@ import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Material;
|
import net.minecraft.block.Material;
|
||||||
import net.minecraft.client.util.math.Vector3f;
|
import net.minecraft.client.util.math.Vector3f;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.world.StructureWorldAccess;
|
import net.minecraft.world.StructureWorldAccess;
|
||||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||||
|
import ru.betterend.blocks.BlockUmbrellaTreeMembrane;
|
||||||
import ru.betterend.registry.EndBlocks;
|
import ru.betterend.registry.EndBlocks;
|
||||||
import ru.betterend.registry.EndTags;
|
import ru.betterend.registry.EndTags;
|
||||||
import ru.betterend.util.MHelper;
|
import ru.betterend.util.MHelper;
|
||||||
import ru.betterend.util.SplineHelper;
|
import ru.betterend.util.SplineHelper;
|
||||||
import ru.betterend.util.sdf.PosInfo;
|
|
||||||
import ru.betterend.util.sdf.SDF;
|
import ru.betterend.util.sdf.SDF;
|
||||||
import ru.betterend.util.sdf.operator.SDFFlatWave;
|
import ru.betterend.util.sdf.operator.SDFFlatWave;
|
||||||
import ru.betterend.util.sdf.operator.SDFScale3D;
|
import ru.betterend.util.sdf.operator.SDFScale3D;
|
||||||
|
@ -31,7 +32,6 @@ import ru.betterend.world.features.DefaultFeature;
|
||||||
public class UmbrellaTreeFeature extends DefaultFeature {
|
public class UmbrellaTreeFeature extends DefaultFeature {
|
||||||
private static final Function<BlockState, Boolean> REPLACE;
|
private static final Function<BlockState, Boolean> REPLACE;
|
||||||
private static final Function<BlockState, Boolean> IGNORE;
|
private static final Function<BlockState, Boolean> IGNORE;
|
||||||
private static final Function<PosInfo, BlockState> POST;
|
|
||||||
private static final List<Vector3f> SPLINE;
|
private static final List<Vector3f> SPLINE;
|
||||||
private static final List<Vector3f> ROOT;
|
private static final List<Vector3f> ROOT;
|
||||||
|
|
||||||
|
@ -40,14 +40,15 @@ public class UmbrellaTreeFeature extends DefaultFeature {
|
||||||
if (!world.getBlockState(pos.down()).getBlock().isIn(EndTags.END_GROUND)) return false;
|
if (!world.getBlockState(pos.down()).getBlock().isIn(EndTags.END_GROUND)) return false;
|
||||||
|
|
||||||
BlockState wood = EndBlocks.UMBRELLA_TREE.bark.getDefaultState();
|
BlockState wood = EndBlocks.UMBRELLA_TREE.bark.getDefaultState();
|
||||||
BlockState membrane = EndBlocks.UMBRELLA_TREE_MEMBRANE.getDefaultState();
|
BlockState membrane = EndBlocks.UMBRELLA_TREE_MEMBRANE.getDefaultState().with(BlockUmbrellaTreeMembrane.COLOR, 1);
|
||||||
BlockState center = EndBlocks.UMBRELLA_TREE.planks.getDefaultState();
|
BlockState center = EndBlocks.UMBRELLA_TREE_MEMBRANE.getDefaultState().with(BlockUmbrellaTreeMembrane.COLOR, 0);
|
||||||
|
|
||||||
float size = MHelper.randRange(10, 20, random);
|
float size = MHelper.randRange(10, 20, random);
|
||||||
int count = (int) (size * 0.15F);
|
int count = (int) (size * 0.15F);
|
||||||
float var = MHelper.PI2 / (float) (count * 3);
|
float var = MHelper.PI2 / (float) (count * 3);
|
||||||
float start = MHelper.randRange(0, MHelper.PI2, random);
|
float start = MHelper.randRange(0, MHelper.PI2, random);
|
||||||
SDF sdf = null;
|
SDF sdf = null;
|
||||||
|
List<Center> centers = Lists.newArrayList();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start;
|
float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start;
|
||||||
List<Vector3f> spline = SplineHelper.copySpline(SPLINE);
|
List<Vector3f> spline = SplineHelper.copySpline(SPLINE);
|
||||||
|
@ -73,6 +74,10 @@ public class UmbrellaTreeFeature extends DefaultFeature {
|
||||||
float pz = MHelper.floor(vec.getZ()) + 0.5F;
|
float pz = MHelper.floor(vec.getZ()) + 0.5F;
|
||||||
mem = new SDFTranslate().setTranslate(px, py, pz).setSource(mem);
|
mem = new SDFTranslate().setTranslate(px, py, pz).setSource(mem);
|
||||||
sdf = new SDFSmoothUnion().setRadius(2).setSourceA(sdf).setSourceB(mem);
|
sdf = new SDFSmoothUnion().setRadius(2).setSourceA(sdf).setSourceB(mem);
|
||||||
|
centers.add(new Center(pos.getX() + (double) px, pos.getZ() + (double) pz, radius));
|
||||||
|
|
||||||
|
vec = spline.get(0);
|
||||||
|
makeRoots(world, pos.add(vec.getX(), vec.getY() + 2, vec.getZ()), size * 0.3F + 3, random, wood);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +85,27 @@ public class UmbrellaTreeFeature extends DefaultFeature {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdf.setReplaceFunction(REPLACE).setPostProcess(POST).fillRecursiveIgnore(world, pos, IGNORE);
|
sdf.setReplaceFunction(REPLACE).setPostProcess((info) -> {
|
||||||
makeRoots(world, pos.add(0, 2, 0), size * 0.3F + 3, random, wood);
|
if (EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateUp()) && EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateDown())) {
|
||||||
|
return EndBlocks.UMBRELLA_TREE.log.getDefaultState();
|
||||||
|
}
|
||||||
|
else if (info.getState().equals(membrane)) {
|
||||||
|
Center min = centers.get(0);
|
||||||
|
double d = Double.MAX_VALUE;
|
||||||
|
BlockPos bpos = info.getPos();
|
||||||
|
for (Center c: centers) {
|
||||||
|
double d2 = c.distance(bpos.getX(), bpos.getZ());
|
||||||
|
if (d2 < d) {
|
||||||
|
d = d2;
|
||||||
|
min = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int color = MHelper.floor(d / min.radius * 7);
|
||||||
|
color = MathHelper.clamp(color, 1, 7);
|
||||||
|
return info.getState().with(BlockUmbrellaTreeMembrane.COLOR, color);
|
||||||
|
}
|
||||||
|
return info.getState();
|
||||||
|
}).fillRecursiveIgnore(world, pos, IGNORE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +156,7 @@ public class UmbrellaTreeFeature extends DefaultFeature {
|
||||||
new Vector3f(0.50F, 1.00F, 0.00F)
|
new Vector3f(0.50F, 1.00F, 0.00F)
|
||||||
);
|
);
|
||||||
|
|
||||||
ROOT = Lists.newArrayList(new Vector3f(0F, 1F, 0),
|
ROOT = Lists.newArrayList(
|
||||||
new Vector3f(0.1F, 0.70F, 0),
|
new Vector3f(0.1F, 0.70F, 0),
|
||||||
new Vector3f(0.3F, 0.30F, 0),
|
new Vector3f(0.3F, 0.30F, 0),
|
||||||
new Vector3f(0.7F, 0.05F, 0),
|
new Vector3f(0.7F, 0.05F, 0),
|
||||||
|
@ -150,12 +174,21 @@ public class UmbrellaTreeFeature extends DefaultFeature {
|
||||||
IGNORE = (state) -> {
|
IGNORE = (state) -> {
|
||||||
return EndBlocks.UMBRELLA_TREE.isTreeLog(state);
|
return EndBlocks.UMBRELLA_TREE.isTreeLog(state);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Center {
|
||||||
|
final double px;
|
||||||
|
final double pz;
|
||||||
|
final float radius;
|
||||||
|
|
||||||
POST = (info) -> {
|
Center(double x, double z, float radius) {
|
||||||
if (EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateUp()) && EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateDown())) {
|
this.px = x;
|
||||||
return EndBlocks.UMBRELLA_TREE.log.getDefaultState();
|
this.pz = z;
|
||||||
}
|
this.radius = radius;
|
||||||
return info.getState();
|
}
|
||||||
};
|
|
||||||
|
double distance(float x, float z) {
|
||||||
|
return MHelper.length(px - x, pz - z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"color=0": { "model": "betterend:block/umbrella_tree_membrane_0" },
|
||||||
|
"color=1": { "model": "betterend:block/umbrella_tree_membrane_1" },
|
||||||
|
"color=2": { "model": "betterend:block/umbrella_tree_membrane_2" },
|
||||||
|
"color=3": { "model": "betterend:block/umbrella_tree_membrane_3" },
|
||||||
|
"color=4": { "model": "betterend:block/umbrella_tree_membrane_4" },
|
||||||
|
"color=5": { "model": "betterend:block/umbrella_tree_membrane_5" },
|
||||||
|
"color=6": { "model": "betterend:block/umbrella_tree_membrane_6" },
|
||||||
|
"color=7": { "model": "betterend:block/umbrella_tree_membrane_7" }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_3"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_5"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_6"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "betterend:block/umbrella_tree_membrane_7"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 390 B |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 396 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 393 B |
After Width: | Height: | Size: 391 B |