From e3d5065e1201d371d9ca7b4cb21ae7962d5072f7 Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Thu, 26 Nov 2020 14:15:29 +0300 Subject: [PATCH] Tenanea feature & flowers --- .../ru/betterend/registry/EndFeatures.java | 2 +- .../world/features/trees/TenaneaFeature.java | 229 ++++++++++-------- .../textures/block/tenanea_flowers.png | Bin 2216 -> 2321 bytes .../textures/block/tenanea_flowers_bottom.png | Bin 2273 -> 2254 bytes .../textures/block/tenanea_flowers_top.png | Bin 2407 -> 2540 bytes .../textures/block/tenanea_leaves.png | Bin 1932 -> 2141 bytes 6 files changed, 128 insertions(+), 103 deletions(-) diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java index df3f1345..a6d406b1 100644 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ b/src/main/java/ru/betterend/registry/EndFeatures.java @@ -39,7 +39,7 @@ public class EndFeatures { public static final EndFeature PYTHADENDRON_TREE = new EndFeature("pythadendron_tree", new PythadendronTreeFeature(), 2); public static final EndFeature LACUGROVE = new EndFeature("lacugrove", new LacugroveFeature(), 4); public static final EndFeature DRAGON_TREE = new EndFeature("dragon_tree", new DragonTreeFeature(), 3); - public static final EndFeature TENANEA = new EndFeature("tenanea", new TenaneaFeature(), 7); + public static final EndFeature TENANEA = new EndFeature("tenanea", new TenaneaFeature(), 3); // Bushes // public static final EndFeature PYTHADENDRON_BUSH = new EndFeature("pythadendron_bush", new BushFeature(EndBlocks.PYTHADENDRON_LEAVES, EndBlocks.PYTHADENDRON.bark), 4); diff --git a/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java b/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java index 5fcea8ff..a9670faf 100644 --- a/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java +++ b/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java @@ -1,139 +1,164 @@ package ru.betterend.world.features.trees; +import java.util.List; import java.util.Random; -import java.util.Set; +import java.util.function.Function; -import com.google.common.collect.Sets; +import com.google.common.collect.Lists; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; +import net.minecraft.block.LeavesBlock; +import net.minecraft.block.Material; +import net.minecraft.client.util.math.Vector3f; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos.Mutable; import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3i; import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import ru.betterend.blocks.BlockProperties; +import ru.betterend.blocks.BlockProperties.TripleShape; +import ru.betterend.noise.OpenSimplexNoise; +import ru.betterend.registry.EndBlocks; +import ru.betterend.registry.EndTags; import ru.betterend.util.BlocksHelper; import ru.betterend.util.MHelper; +import ru.betterend.util.SplineHelper; +import ru.betterend.util.sdf.SDF; +import ru.betterend.util.sdf.operator.SDFDisplacement; +import ru.betterend.util.sdf.operator.SDFScale; +import ru.betterend.util.sdf.operator.SDFScale3D; +import ru.betterend.util.sdf.operator.SDFSubtraction; +import ru.betterend.util.sdf.operator.SDFTranslate; +import ru.betterend.util.sdf.primitive.SDFSphere; import ru.betterend.world.features.DefaultFeature; public class TenaneaFeature extends DefaultFeature { - private static final Vec3i[] DIRECTIONS; - private static final Vec3i UP; + private static final Function REPLACE; + private static final Function IGNORE; + private static final List SPLINE; @Override public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { - Set set = branch(Sets.newHashSet(), world, pos, UP, 100, random); - set.forEach((bpos) -> { - BlocksHelper.setWithoutUpdate(world, bpos, Blocks.DIAMOND_BLOCK); - }); + if (!world.getBlockState(pos.down()).getBlock().isIn(EndTags.END_GROUND)) return false; + + float size = MHelper.randRange(7, 10, random); + int count = (int) (size * 0.45F); + float var = MHelper.PI2 / (float) (count * 3); + float start = MHelper.randRange(0, MHelper.PI2, random); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; + List spline = SplineHelper.copySpline(SPLINE); + SplineHelper.rotateSpline(spline, angle); + SplineHelper.scale(spline, size + MHelper.randRange(0, size * 0.5F, random)); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + SplineHelper.fillSpline(spline, world, EndBlocks.TENANEA.bark.getDefaultState(), pos, REPLACE); + Vector3f last = spline.get(spline.size() - 1); + float leavesRadius = (size * 0.3F + MHelper.randRange(0.8F, 1.5F, random)); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + leavesBall(world, pos.add(last.getX(), last.getY(), last.getZ()), leavesRadius, random, noise); + } + return true; } - private Set branch(Set set, StructureWorldAccess world, BlockPos pos, Vec3i dir, int length, Random random) { - Mutable mut = new Mutable().set(pos); - int upCount = 0; - for (int i = 0; i < length; i++) { - MHelper.shuffle(DIRECTIONS, random); - boolean up = false; - - set.add(mut.toImmutable()); - - for (Direction hor: BlocksHelper.HORIZONTAL) { - if (!isReplaceable(world.getBlockState(mut.offset(hor))) || !isReplaceable(world.getBlockState(mut.offset(hor).down()))) { - upCount = -1; - up = true; - break; - } + private void leavesBall(StructureWorldAccess world, BlockPos pos, float radius, Random random, OpenSimplexNoise noise) { + SDF sphere = new SDFSphere().setRadius(radius).setBlock(EndBlocks.TENANEA_LEAVES.getDefaultState().with(LeavesBlock.DISTANCE, 6)); + SDF sub = new SDFScale().setScale(5).setSource(sphere); + sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); + sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { return (float) noise.eval(vec.getX() * 0.2, vec.getY() * 0.2, vec.getZ() * 0.2) * 1F; }).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { return random.nextFloat() * 3F - 1.5F; }).setSource(sphere); + Mutable mut = new Mutable(); + List support = Lists.newArrayList(); + sphere.setPostProcess((info) -> { + if (random.nextBoolean() && info.getStateDown().isAir()) { + support.add(info.getPos().toImmutable()); } - if (up) { - upCount ++; - mut.move(Direction.UP); - if (upCount > 8) { - break; - } - - if (random.nextInt(4) == 0) { - Direction d = BlocksHelper.randomHorizontal(random); - mut.move(d); - } - - /*if (random.nextInt(16) == 0) { - int l = length - i; - if (l > 5) { - l = MHelper.randRange(l / 2, l, random); - Vec3i d = DIRECTIONS[random.nextInt(DIRECTIONS.length)]; - if (d != dir) { - branch(set, world, mut.add(d), d, l, random); - } + if (random.nextInt(5) == 0) { + for (Direction dir: Direction.values()) { + BlockState state = info.getState(dir, 2); + if (state.isAir()) { + return info.getState(); } - }*/ - - continue; - } - else { - up = true; - for (Vec3i d: DIRECTIONS) { - BlockPos offseted = mut.add(d.getX(), d.getY(), d.getZ()); - boolean canOffset = Math.abs(offseted.getX() - pos.getX()) < 16 && Math.abs(offseted.getZ() - pos.getZ()) < 16; - if (canOffset && isReplaceable(world.getBlockState(offseted))) { - int dist = BlocksHelper.raycastSqr(world, offseted, d.getX(), d.getY(), d.getZ(), 10); - if (dist < 64) { - mut.move(d.getX(), d.getY(), d.getZ()); - upCount = 0; - up = false; - dir = d; - break; + } + info.setState(EndBlocks.TENANEA.bark.getDefaultState()); + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.get(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.with(LeavesBlock.DISTANCE, d)); + } + } + } } } } - if (up) { - upCount ++; - mut.move(Direction.UP); - if (upCount > 8) { - break; - } - } } - - if (!world.getBlockState(mut).getMaterial().isReplaceable()) { - boolean br = true; - for (Direction hor: BlocksHelper.HORIZONTAL) { - if (isReplaceable(world.getBlockState(mut.offset(hor)))) { - mut.move(hor); - br = false; - } - } - if (br) { - break; - } - } - } + return info.getState(); + }); + sphere.fillRecursiveIgnore(world, pos, IGNORE); - return set; - } - - private boolean isReplaceable(BlockState state) { - return state.getMaterial().isReplaceable(); + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.TENANEA.bark); + + BlockState top = EndBlocks.TENANEA_FLOWERS.getDefaultState().with(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); + BlockState middle = EndBlocks.TENANEA_FLOWERS.getDefaultState().with(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); + BlockState bottom = EndBlocks.TENANEA_FLOWERS.getDefaultState().with(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); + + support.forEach((bpos) -> { + int count = MHelper.randRange(5, 9, random); + mut.set(bpos).move(Direction.DOWN); + BlocksHelper.setWithoutUpdate(world, mut, top); + for (int i = 1; i < count; i++) { + mut.setY(mut.getY() - 1); + if (world.isAir(mut.down())) { + BlocksHelper.setWithoutUpdate(world, mut, middle); + } + else { + break; + } + } + BlocksHelper.setWithoutUpdate(world, mut, bottom); + }); } static { - DIRECTIONS = new Vec3i[] { - new Vec3i(0, 0, 1), - new Vec3i(0, 0, -1), - new Vec3i(1, 0, 0), - new Vec3i(-1, 0, 0), - new Vec3i(1, 0, 1), - new Vec3i(1, 0, -1), - new Vec3i(-1, 0, 1), - new Vec3i(-1, 0, -1), - new Vec3i(1, 1, 1), - new Vec3i(1, 1, -1), - new Vec3i(-1, 1, 1), - new Vec3i(-1, 1, -1) + REPLACE = (state) -> { + if (state.isIn(EndTags.END_GROUND)) { + return true; + } + if (state.getBlock() == EndBlocks.TENANEA_LEAVES) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); }; - UP = new Vec3i(0, 1, 0); + IGNORE = (state) -> { + return EndBlocks.TENANEA.isTreeLog(state); + }; + + SPLINE = Lists.newArrayList( + new Vector3f(0.00F, 0.00F, 0.00F), + new Vector3f(0.10F, 0.35F, 0.00F), + new Vector3f(0.20F, 0.50F, 0.00F), + new Vector3f(0.30F, 0.55F, 0.00F), + new Vector3f(0.42F, 0.70F, 0.00F), + new Vector3f(0.50F, 1.00F, 0.00F) + ); } } diff --git a/src/main/resources/assets/betterend/textures/block/tenanea_flowers.png b/src/main/resources/assets/betterend/textures/block/tenanea_flowers.png index 5ce1df8455c81aac9356f47a2b70fc5e9d540c38..bd8ea393b989493d99f1bcf6bad4166c307acf2d 100644 GIT binary patch delta 742 zcmZ1>I8kVV1ryukjaHMG*p01B&8&=!Ctqe#fwTWHS*Ro>rn5h8nd>GQm?s)0nV4EynkR0KV)kR2e1pZzl^E4Z3dJR^WhGYS8L4@;N=61o2D*lZ zx<+OphA=lwWwD<;i8a4oz-v-J0|S$ar;B5V#p&M3vHq6>B#!@2&&zvzFKb)a@kczu zB^?*LQ}?+hi3s_m#7z7l`Q`QxMUJc<&K3zhfnH7E1pM}AZH;;zd`20D|8l`M@q{eT}s{Muf^#>B89(Dfz zE46fL?F#JSaXW!qc;GVOR_Z3ft;A0ty66*~m1szwG`(`vx_xSsF z85?t#-*ac1m(xPsHn$%aclGIzkv#jlB+ay4dT*l6hTqe8g>qUHx68it5-ons+Vj;z z;^~_iN$2$=Coj~Udv4zE@H^8UOgvuS$G_%9?8c^v3i*OFTr4Yh8#m^wIdeXDdQ`;m zZ2BH;*Ql`4FKsL}eHFS*7Rs}I)h;%t1?CKm;ka!^V_>#PYZ#nIDC#Ge=WZ~K|9qa7M* zWI9<}r+#wvg`fLhRCC36epPIH*z>a_+-Pb$X88r^@y{A%67UNHb90J+|#c)pu=M>6({+X@9f{*>9r zjE* zQr7=1g|BWE8h>*3cb^3@1t0+s zDXf>m!>9bRSkszi?jb9S%uW^!o;_*u*Hy<_I--UefCK=ZEWM0(elNNCPRf&QY6;Vm zhi+bMxAwSVxIgQ+#RJXlZ4n>=Ah>bmRpI5HJ5vm{(@$->%-ItF{s;ft2G@vNNxuL9002ov JPDHLkV1kt_Scw1t diff --git a/src/main/resources/assets/betterend/textures/block/tenanea_flowers_bottom.png b/src/main/resources/assets/betterend/textures/block/tenanea_flowers_bottom.png index 16334402b5ab4fe90330dcff7d03a8aa44e70d78..a7e013b6c7689ef2a4f1c2a8aa2f50fac76f5eca 100644 GIT binary patch delta 598 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 diff --git a/src/main/resources/assets/betterend/textures/block/tenanea_leaves.png b/src/main/resources/assets/betterend/textures/block/tenanea_leaves.png index 845e07a74d3e0272305b32a68c189db916e5afbb..bcc87a6244ab676a44f0fc9a108fb56d8fdf4940 100644 GIT binary patch delta 844 zcmeC-zbi1of{FF;MyrWT9EQeLrUq69rjsu-DI+-lm@HHbEK*I9(=1bTjSVf0bS*4Q z%yg5?ElhNiEzB%ZEetJ_4NMF+M={qi))%FuS>=(FAEv)NBNb?*k%5tcuA!l>ky!}L+1duiR+DG4 zSPMceO3p~kOHWO)Rnnh)nI*3NS?lvA1_mYvPZ!4!i{8@7@g9={C63K6-eypubZ}ar z-o_JchO4?K25>r>Pjqp8)5{cNpy0-sn=S9XV_0=&M z)!&1b>}e0ldnEkn@#7Caqzf0<&VJEn6QJCwSD1cnxy$dnYaTrf%42IRzB{ANq{-@k zoh<)xtE~lZS_87}_Z_TOXgG8`Q)HRi#$Tm!%iY-(`R8XIlk&3qnVuP0eN5ybxAW(( zT2(%rYSZU-iLFc!y}D1$;%c;F=T6%jt0vc%w|&bzKSSx?wOFf8xBN%DY#ntkZ8T6+ z(f`Rb`ShiwuG98EF}P9e@_|)oQ<|FbvT(hG_b2&u-+|02 z+}c>ZZ-VH{X^U6oDr(!Av59yJ&x}&-J@8c5IBDaH2ch+cWL~B;dwa*da<=#vbMtA} z-Gkk)D(e5J*`?bl{QtsvYU-lA6qOK>iz#t};T8^|zPw)A+7Yv6J81}AJMylJ+0!O? zx97j+=Ybo~u?6lvyngb{+FuJ_FK^MD9w*fQBQ|t%)8fq^eVX42-gvQKZmzHP6Py7VBh1*ov9KL6#^j8E$m1ULEYo%{Of$^Q>8&hCA} z@iTu3`@8&G0hx~_AGcjBR=#Vu-p;#Kc(&P;mP^N!_3XFB8+af6^zUv!*U2+`4R2JK l%s$Z(c&B6Hg+I>w86>aAJ=&csZXx)^eKXLu`ORl?gm4AYjtEh3fPdy9m;cu@;Dfe!Gd{xzSYTGOYvtUYhzs$(w~C$bISQ<=qe5nsW+y(;&%!iq zxp;+i?cq2%R1$EhRFI4_NKoPNM1+rSV+F9|IzqxUPb&gpa?69HAu~|3S%1J4^$n77 z21(WS1rP$+oc-ZiA=y8kQW}q_0I;LWgk&y1No_4Lg$hsz&j90$%pNKfJ0Qf%P4fVb z?yRTD!8D!N7ZLAcmpc~a?#(_|Z)#e((W{ybZD1&U_&&he5F9KUQTdr4l)2k&t^{o4 zA_mX5Q%~P8+jdn&bO&!det(W~=?|0}c||VINh6PJnpM61Q;ZVI^`!dz^lQFI#p!X+ z)+tfE%q@|IJmcMf7vz<5A|6pIgHZva`^aZncPV2RSwkM=H~Z2GqqF6i2HPXF?Pdp_ zl7`1SFY+vn^hRe-W3j>32(hWS%Or2eG_;Wi5{%B4mrQ-+&ffmNMqdb<2xCwGPad+_ zNQ@Bw##pjz$%blMo(XIiGB#4LUL$uy9T%2tC=_a29^~R