Skip to content

Commit

Permalink
feat(flesh-mound): increase the minimum cradle room size and make it …
Browse files Browse the repository at this point in the history
…more likely that it generates with a solid floor
  • Loading branch information
Elenterius committed Jan 15, 2024
1 parent e5c7d4f commit 3efe121
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.github.elenterius.biomancy.block;

import com.github.elenterius.biomancy.block.cradle.PrimalEnergyHandler;
import com.github.elenterius.biomancy.block.veins.FleshVeinsBlock;
import com.github.elenterius.biomancy.init.ModBlocks;
import com.github.elenterius.biomancy.util.ArrayUtil;
import com.github.elenterius.biomancy.util.VectorUtil;
import com.github.elenterius.biomancy.world.PrimordialEcosystem;
import com.github.elenterius.biomancy.world.mound.MoundShape;
import com.github.elenterius.biomancy.world.spatial.SpatialShapeManager;
Expand All @@ -10,7 +14,6 @@
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;

import java.util.Arrays;
import java.util.Random;

public class SpreadingMembraneBlock extends MembraneBlock {
Expand All @@ -24,25 +27,31 @@ public void tick(BlockState state, ServerLevel level, BlockPos pos, Random rando
if (level.random.nextFloat() >= 0.5f) return;
if (!level.isAreaLoaded(pos, 2)) return;

BlockPos targetPos = pos.relative(Direction.getRandom(random));
BlockPos targetPos = pos.offset(VectorUtil.randomOffsetInCube3i(random));
BlockState stateAtTargetPos = level.getBlockState(targetPos);
if (!stateAtTargetPos.isAir() && !PrimordialEcosystem.isReplaceable(stateAtTargetPos)) return;

// boolean hasInvalidNeighborAtTargetPos = Direction.stream()
// .map(targetPos::relative)
// .filter(neighborPos -> !neighborPos.equals(pos))
// .anyMatch(neighborPos -> PrimordialEcosystem.isReplaceable(level.getBlockState(neighborPos)));
//
// if (hasInvalidNeighborAtTargetPos) return;
if (!stateAtTargetPos.isAir() && !(stateAtTargetPos.getBlock() instanceof FleshVeinsBlock) && !PrimordialEcosystem.isReplaceable(stateAtTargetPos)) return;

if (SpatialShapeManager.getClosestShape(level, pos, MoundShape.class::isInstance) instanceof MoundShape mound) {
BlockEntity blockEntity = level.getExistingBlockEntity(mound.getOrigin());
if (blockEntity instanceof PrimalEnergyHandler energyHandler && !mound.hasChamberAt(targetPos)) {

boolean isNeighborNextToAnyChamber = Arrays.stream(Direction.values()).anyMatch(direction -> mound.hasChamberAt(targetPos.relative(direction)));
int nextToAnyChamberCount = 0;
for (Direction direction : ArrayUtil.shuffleCopy(Direction.values(), random)) {
if (mound.hasChamberAt(targetPos.relative(direction))) {
nextToAnyChamberCount++;
if (nextToAnyChamberCount > 1) break;
}
}

if (isNeighborNextToAnyChamber && energyHandler.drainPrimalEnergy(5) > 0) {
level.setBlock(targetPos, defaultBlockState(), UPDATE_CLIENTS);
if (energyHandler.drainPrimalEnergy(4) > 0) {
if (nextToAnyChamberCount > 1) {
level.setBlock(targetPos, defaultBlockState(), UPDATE_CLIENTS);
}
else {
level.setBlock(targetPos, ModBlocks.MALIGNANT_FLESH.get().defaultBlockState(), UPDATE_CLIENTS);
PrimordialEcosystem.spreadMalignantVeinsFromSource(level, targetPos, PrimordialEcosystem.MAX_CHARGE_SUPPLIER);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public void onLoad() {
MoundShape.ProcGenValues values = moundShape.getProcGenValues();
if (!values.equals(procGenValues)) {
procGenValues = values;
setChangedSilent();
markChunkAsUnsaved();
}
}
}
Expand All @@ -105,7 +105,7 @@ public boolean insertItem(ItemStack stack) {
if (sacrificeHandler.isFull()) return false;

return sacrificeHandler.addItem(stack, tribute -> {
setChangedSilent();
markChunkAsUnsaved();
syncToClient();
spawnTributeParticles((ServerLevel) level, tribute);
});
Expand Down Expand Up @@ -160,14 +160,14 @@ public boolean hasModifiers() {

private void resetState() {
sacrificeHandler.reset();
setChangedSilent();
markChunkAsUnsaved();
syncToClient();
}

/**
* equivalent to calling #setChanged() but without notifying block neighbors of the change
*/
protected void setChangedSilent() {
protected void markChunkAsUnsaved() {
if (level != null && level.hasChunkAt(worldPosition)) {
level.getChunkAt(worldPosition).setUnsaved(true);
}
Expand Down Expand Up @@ -197,18 +197,17 @@ public void onSacrifice(ServerLevel level) {
SoundUtil.broadcastBlockSound(level, pos, ModSoundEvents.CREATOR_SPAWN_MOB);
}

if (level.random.nextFloat() >= sacrificeHandler.getTumorFactor() / 3) {
PrimordialEcosystem.tryToReplaceBlock(level, pos.below(), ModBlocks.PRIMAL_FLESH.get().defaultBlockState());
}
PrimordialEcosystem.tryToReplaceBlock(level, pos.below(), ModBlocks.MALIGNANT_FLESH.get().defaultBlockState());

level.sendParticles(ParticleTypes.EXPLOSION, pos.getX() + 0.5d, pos.getY() + 0.5d, pos.getZ() + 0.5d, 1, 0, 0, 0, 0);
}
else {
attackAOE(level, pos);
SoundUtil.broadcastBlockSound(level, pos, ModSoundEvents.CREATOR_SPIKE_ATTACK);
if (!PrimordialEcosystem.spreadMalignantVeinsFromSource(level, pos, PrimordialEcosystem.MAX_CHARGE_SUPPLIER)) {
PrimordialEcosystem.tryToReplaceBlock(level, pos.below(), ModBlocks.PRIMAL_FLESH.get().defaultBlockState());
}

PrimordialEcosystem.tryToReplaceBlock(level, pos.below(), ModBlocks.MALIGNANT_FLESH.get().defaultBlockState());
PrimordialEcosystem.spreadMalignantVeinsFromSource(level, pos, PrimordialEcosystem.MAX_CHARGE_SUPPLIER);

addPrimalEnergy(Math.round(3072 * energyMultiplier));
SoundUtil.broadcastBlockSound(level, pos, ModSoundEvents.FLESH_BLOCK_STEP.get(), 1f, 0.15f + level.random.nextFloat() * 0.5f);
}
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/github/elenterius/biomancy/util/VectorUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,37 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class VectorUtil {

public static final Vec3i XZ_PLANE = new Vec3i(1, 0, 1);
public static final Vec3i XY_PLANE = new Vec3i(1, 1, 0);
public static final Vec3i YZ_PLANE = new Vec3i(0, 1, 1);

private static final Vec3i[] OFFSETS_CUBE_3I;

static {
List<Vec3i> offsets = new ArrayList<>();
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
for (int z = -1; z <= 1; z++) {
if (x == 0 && y == 0 && z == 0) continue;
offsets.add(new Vec3i(x, y, z));
}
}
}
OFFSETS_CUBE_3I = offsets.toArray(new Vec3i[]{});
}

private VectorUtil() {}

public static Vec3i randomOffsetInCube3i(Random random) {
return OFFSETS_CUBE_3I[random.nextInt(OFFSETS_CUBE_3I.length)];
}

public static Vec3i abs(Vec3i vec) {
return new Vec3i(Math.abs(vec.getX()), Math.abs(vec.getY()), Math.abs(vec.getZ()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ public interface ChamberFactory {
consumer.accept(chamber);
};

wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x + p, y - p, z + p, halfR, quarterR, halfR, quarterR, halfR, quarterR)));
wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x - p, y - p, z + p, quarterR, quarterR, halfR, halfR, halfR, quarterR)));
wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x + p, y - p, z - p, halfR, quarterR, quarterR, quarterR, halfR, halfR)));
wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x - p, y - p, z - p, quarterR, quarterR, quarterR, halfR, halfR, halfR)));
float offset = 0.25f;
wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x + p, y - p - offset, z + p, halfR, quarterR, halfR, quarterR, halfR, quarterR)));
wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x - p, y - p - offset, z + p, quarterR, quarterR, halfR, halfR, halfR, quarterR)));
wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x + p, y - p - offset, z - p, halfR, quarterR, quarterR, quarterR, halfR, halfR)));
wrappedConsumer.accept(new MoundChamber(new OctantEllipsoidShape(x - p, y - p - offset, z - p, quarterR, quarterR, quarterR, halfR, halfR, halfR)));
};

SimpleWeightedRandomList<ChamberFactory> RANDOM_DEFAULTS_LIST = SimpleWeightedRandomList.<ChamberFactory>builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,17 @@ private static void genSpire(double x, double y, double z, float maxHeight, floa
float prevRadius = baseRadius + context.relativeWallThickness;
float totalHeight = 0;

genSphereWithChambers(x, y, z, prevRadius, prevRadius - context.relativeWallThickness / 2f, context, isMainSpire ? ChamberFactoryType.CRADLE : ChamberFactoryType.DEFAULT);
if (isMainSpire) {
prevRadius = Math.max(14f, prevRadius);
float chamberRadius = Math.max(12f, prevRadius - context.relativeWallThickness / 2f);

context.mainChamberRadius = chamberRadius * 0.9f;

genSphereWithChambers(x, y, z, prevRadius, chamberRadius, context, ChamberFactoryType.CRADLE, true);
}
else {
genSphereWithChambers(x, y, z, prevRadius, prevRadius - context.relativeWallThickness / 2f, context, ChamberFactoryType.DEFAULT, false);
}

while (totalHeight < maxHeight) {
float t = totalHeight / maxHeight;
Expand All @@ -121,7 +131,7 @@ private static void genSpire(double x, double y, double z, float maxHeight, floa
leanZ = prevLean.z - leanOffset.z;
}

genSphereWithChambers(x + leanX, y + height, z + leanZ, radius, radius - context.relativeWallThickness / 2f, context, ChamberFactoryType.DEFAULT);
genSphereWithChambers(x + leanX, y + height, z + leanZ, radius, radius - context.relativeWallThickness / 2f, context, ChamberFactoryType.DEFAULT, isMainSpire);

prevLean.set(leanX, 0, leanZ);
prevRadius = radius;
Expand All @@ -130,16 +140,14 @@ private static void genSpire(double x, double y, double z, float maxHeight, floa

//end cap shape
ChamberFactoryType chamberType = isMainSpire ? ChamberFactoryType.END_CAP_MAIN_SPIRE : ChamberFactoryType.END_CAP_SUB_SPIRE;
genSphereWithChambers(x + prevLean.x, y + totalHeight + (prevRadius / 2) * 1.5f, z + prevLean.z, prevRadius / 2f, prevRadius / 2f, context, chamberType);
genSphereWithChambers(x + prevLean.x, y + totalHeight + (prevRadius / 2) * 1.5f, z + prevLean.z, prevRadius / 2f, prevRadius / 2f, context, chamberType, isMainSpire);
}

private static void genSphereWithChambers(double x, double y, double z, float radius, float chamberRadius, Context context, ChamberFactoryType type) {
private static void genSphereWithChambers(double x, double y, double z, float radius, float chamberRadius, Context context, ChamberFactoryType type, boolean isMainSpire) {
Vec3 pos = new Vec3(x, y, z);
context.boundingShapes.add(new SphereShape(pos, radius));

if (type == ChamberFactoryType.CRADLE) {
context.mainChamberRadius = chamberRadius * 0.9f;

Consumer<MoundChamber> consumer = chamber -> {
context.cradleChambers.add(chamber);
context.chambers.add(chamber);
Expand All @@ -154,16 +162,22 @@ private static void genSphereWithChambers(double x, double y, double z, float ra
// double distSqr = closestPoint.distanceToSqr(context.origin);
// boolean noIntersectionWithCradleChambers = distSqr > context.mainChamberRadius * context.mainChamberRadius;

boolean intersectingWithCradleChamber = false;
for (MoundChamber cradleChamber : context.cradleChambers) {
if (cradleChamber.intersectsCuboid(chamber.getAABB())) {
intersectingWithCradleChamber = true;
break;
}
if (isMainSpire) {
context.chambers.add(chamber);
}
else {
boolean intersectingWithCradleChamber = false;

for (MoundChamber cradleChamber : context.cradleChambers) {
if (cradleChamber.intersectsCuboid(chamber.getAABB())) {
intersectingWithCradleChamber = true;
break;
}
}

if (!intersectingWithCradleChamber) {
context.chambers.add(chamber);
if (!intersectingWithCradleChamber) {
context.chambers.add(chamber);
}
}
};

Expand Down

0 comments on commit 3efe121

Please sign in to comment.