Bile vein with temp texture, cysts and funal ouranwood forest biome

This commit is contained in:
craisinlord committed 2026-06-27 14:31:51 -05:00
1 parent b416c96ea2
commit aad8a1e1c5
52 files changed
+1361 -343

No files matched your search

@@ -225,6 +225,8 @@ public final class AntarchyObjects {
public static Supplier<BlockEntityType<HushweedBlockEntity>> HUSHWEED_BLOCK_ENTITY = (Supplier<BlockEntityType<HushweedBlockEntity>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<SimpleParticleType> STINKY_GAS = (Supplier<SimpleParticleType>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<SimpleParticleType> STINKY_FLY = (Supplier<SimpleParticleType>) UNBOUND;
private AntarchyObjects() {
}
@@ -316,6 +318,7 @@ public final class AntarchyObjects {
Supplier<BlockEntityType<WaspNestBlockEntity>> waspNestBlockEntity,
Supplier<BlockEntityType<HushweedBlockEntity>> hushweedBlockEntity,
Supplier<SimpleParticleType> stinkyGas,
Supplier<SimpleParticleType> stinkyFly,
Supplier<Holder<Attribute>> doubleDamageChance,
Supplier<Holder<Attribute>> bloodglassMaxHearts,
Supplier<Holder<MobEffect>> bloodglassWard
@@ -406,6 +409,7 @@ public final class AntarchyObjects {
WASP_NEST_BLOCK_ENTITY = waspNestBlockEntity;
HUSHWEED_BLOCK_ENTITY = hushweedBlockEntity;
STINKY_GAS = stinkyGas;
STINKY_FLY = stinkyFly;
DOUBLE_DAMAGE_CHANCE = doubleDamageChance;
BLOODGLASS_MAX_HEARTS = bloodglassMaxHearts;
BLOODGLASS_WARD = bloodglassWard;
@@ -12,7 +12,6 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
public final class StinkyBehavior {
public static final int STINKY_EFFECT_DURATION_TICKS = 60;
public static final double STINK_BUG_AURA_RADIUS = 5.0D;
public static final double STINKY_NAUSEA_RADIUS = 4.0D;
private static final int TRAIL_INTERVAL_TICKS = 4;
@@ -59,6 +58,17 @@ public final class StinkyBehavior {
entity.getBbWidth() * 0.12D,
0.005D
);
serverLevel.sendParticles(
AntarchyObjects.STINKY_FLY.get(),
entity.getX(),
entity.getY(0.45D),
entity.getZ(),
1,
entity.getBbWidth() * 0.35D,
entity.getBbHeight() * 0.2D,
entity.getBbWidth() * 0.35D,
0.0D
);
applyNearbyNausea(entity, STINKY_NAUSEA_RADIUS, STINKY_NAUSEA_DURATION_TICKS);
if (entity.tickCount % REACTION_INTERVAL_TICKS == 0) {
reactToStinkySource(entity);
@@ -80,6 +90,17 @@ public final class StinkyBehavior {
entity.getBbWidth() * 0.35D,
0.045D
);
serverLevel.sendParticles(
AntarchyObjects.STINKY_FLY.get(),
entity.getX(),
entity.getY(0.45D),
entity.getZ(),
Math.max(2, count / 6),
entity.getBbWidth() * 0.45D,
entity.getBbHeight() * 0.25D,
entity.getBbWidth() * 0.45D,
0.0D
);
applyNearbyNausea(entity, STINK_BUG_AURA_RADIUS, STINK_BUG_BURST_NAUSEA_DURATION_TICKS);
}
@@ -108,6 +129,9 @@ public final class StinkyBehavior {
mob -> mob.isAlive() && mob != source
)) {
if (mob.getType().is(EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS)) {
if (source.getType().is(EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS)) {
continue;
}
attractArthropod(mob, source);
continue;
}
@@ -167,4 +191,5 @@ public final class StinkyBehavior {
}
return !mob.isAlliedTo(source);
}
}
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.block;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.entity.CreepingHorrorEntity;
import com.craisinlord.antarchy.content.block.AmberMossBlock;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -87,7 +88,7 @@ public class CreepingHorrorEggBlock extends Block {
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!this.shouldUpdateHatchLevel(level)) {
if (!this.shouldUpdateHatchLevel(level, pos)) {
return;
}
@@ -174,8 +175,9 @@ public class CreepingHorrorEggBlock extends Block {
level.setBlock(pos, state.setValue(EGGS, eggs - 1), 2);
}
private boolean shouldUpdateHatchLevel(Level level) {
return level.random.nextInt(500) == 0;
private boolean shouldUpdateHatchLevel(Level level, BlockPos pos) {
boolean onAmberMoss = level.getBlockState(pos.below()).getBlock() instanceof AmberMossBlock;
return level.random.nextInt(onAmberMoss ? 150 : 500) == 0;
}
private boolean canDestroyEgg(Level level, Entity entity) {
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.block;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.entity.LurkingTerrorEntity;
import com.craisinlord.antarchy.content.block.AmberMossBlock;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -87,7 +88,7 @@ public class LurkingTerrorEggBlock extends Block {
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!this.shouldUpdateHatchLevel(level)) {
if (!this.shouldUpdateHatchLevel(level, pos)) {
return;
}
@@ -174,8 +175,9 @@ public class LurkingTerrorEggBlock extends Block {
level.setBlock(pos, state.setValue(EGGS, eggs - 1), 2);
}
private boolean shouldUpdateHatchLevel(Level level) {
return level.random.nextInt(500) == 0;
private boolean shouldUpdateHatchLevel(Level level, BlockPos pos) {
boolean onAmberMoss = level.getBlockState(pos.below()).getBlock() instanceof AmberMossBlock;
return level.random.nextInt(onAmberMoss ? 150 : 500) == 0;
}
private boolean canDestroyEgg(Level level, Entity entity) {
@@ -111,8 +111,11 @@ public class LurkingTerrorEntity extends Monster implements GeoEntity {
}
return state.setAndContinue(ATTACK_LAND_ANIM);
}
if (!this.onGround()) {
return state.setAndContinue(FLY_ANIM);
}
if (state.isMoving()) {
return state.setAndContinue(this.onGround() ? WALK_ANIM : FLY_ANIM);
return state.setAndContinue(WALK_ANIM);
}
return state.setAndContinue(IDLE_ANIM);
}
@@ -334,11 +334,18 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
if (--this.wanderRetargetTicks <= 0) {
this.wanderRetargetTicks = 40 + this.random.nextInt(40);
float angle = this.random.nextFloat() * (float) (Math.PI * 2);
this.wanderDx = Mth.cos(angle) * 0.1f;
this.wanderDy = -0.05f + this.random.nextFloat() * 0.1f;
this.wanderDz = Mth.sin(angle) * 0.1f;
this.wanderDx = Mth.cos(angle) * 0.015f;
this.wanderDz = Mth.sin(angle) * 0.015f;
this.wanderDy = -0.01f + this.random.nextFloat() * 0.01f; // slight downward bias
}
this.setDeltaMovement(this.getDeltaMovement().add(this.wanderDx, this.wanderDy, this.wanderDz));
// Surface avoidance: if the block above is not water, push down
float dy = this.wanderDy;
if (!this.level().getFluidState(this.blockPosition().above()).is(net.minecraft.tags.FluidTags.WATER)) {
dy = -0.03f;
}
this.setDeltaMovement(this.getDeltaMovement().add(this.wanderDx, dy, this.wanderDz));
}
// -------------------------------------------------------------------------
@@ -4,6 +4,7 @@ import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.config.AntarchySettings;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.EntityType;
@@ -18,10 +19,21 @@ import software.bernie.geckolib.animatable.GeoEntity;
public class TermiteEntity extends BaseAntEntity implements GeoEntity {
private static final int WOOD_BITE_ANIMATION_TICKS = 8;
private static final int WOOD_SEARCH_INTERVAL_TICKS = 10;
private static final int WOOD_SEARCH_INTERVAL_TICKS = 20;
private static final int WOOD_REPATH_INTERVAL_TICKS = 6;
private static final int WOOD_SEARCH_RADIUS_HORIZONTAL = 12;
private static final int WOOD_SEARCH_RADIUS_VERTICAL = 4;
private static final Vec3i[] IMMEDIATE_WOOD_OFFSETS = {
new Vec3i(0, 1, 0),
new Vec3i(0, 0, -1),
new Vec3i(0, 0, 1),
new Vec3i(1, 0, 0),
new Vec3i(-1, 0, 0),
new Vec3i(0, 1, -1),
new Vec3i(0, 1, 1),
new Vec3i(1, 1, 0),
new Vec3i(-1, 1, 0),
};
@Nullable
private BlockPos targetWoodPos;
private int nextWoodSearchTick;
@@ -125,7 +137,9 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
}
private boolean tryEatNearbyWood() {
for (BlockPos targetPos : this.getImmediateWoodChecks()) {
BlockPos basePos = this.blockPosition();
for (Vec3i offset : IMMEDIATE_WOOD_OFFSETS) {
BlockPos targetPos = basePos.offset(offset);
BlockState targetState = this.level().getBlockState(targetPos);
if (!targetState.is(AntarchyTags.Blocks.TERMITE_FOODS)) {
continue;
@@ -141,22 +155,6 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
return false;
}
private BlockPos[] getImmediateWoodChecks() {
BlockPos basePos = this.blockPosition();
BlockPos abovePos = basePos.above();
return new BlockPos[] {
basePos.above(),
basePos.north(),
basePos.south(),
basePos.east(),
basePos.west(),
abovePos.north(),
abovePos.south(),
abovePos.east(),
abovePos.west()
};
}
@Nullable
private BlockPos getCurrentWoodTarget() {
if (this.targetWoodPos != null && this.isValidWoodTarget(this.targetWoodPos)) {
@@ -175,20 +173,52 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
@Nullable
private BlockPos findClosestWoodTarget() {
BlockPos origin = this.blockPosition();
int ox = origin.getX();
int oy = origin.getY();
int oz = origin.getZ();
BlockPos bestPos = null;
double bestDistance = Double.MAX_VALUE;
double bestDistSq = Double.MAX_VALUE;
BlockPos.MutableBlockPos candidate = new BlockPos.MutableBlockPos();
for (BlockPos pos : BlockPos.betweenClosed(
origin.offset(-WOOD_SEARCH_RADIUS_HORIZONTAL, -WOOD_SEARCH_RADIUS_VERTICAL, -WOOD_SEARCH_RADIUS_HORIZONTAL),
origin.offset(WOOD_SEARCH_RADIUS_HORIZONTAL, WOOD_SEARCH_RADIUS_VERTICAL + 2, WOOD_SEARCH_RADIUS_HORIZONTAL))) {
if (!this.isValidWoodTarget(pos)) {
continue;
for (int r = 0; r <= WOOD_SEARCH_RADIUS_HORIZONTAL; r++) {
if (bestPos != null && bestDistSq <= (double)(r * r)) {
break;
}
double distance = pos.distSqr(origin);
if (distance < bestDistance) {
bestDistance = distance;
bestPos = pos.immutable();
for (int dy = -WOOD_SEARCH_RADIUS_VERTICAL; dy <= WOOD_SEARCH_RADIUS_VERTICAL + 2; dy++) {
if (r == 0) {
candidate.set(ox, oy + dy, oz);
if (this.isValidWoodTarget(candidate)) {
double d = candidate.distSqr(origin);
if (d < bestDistSq) { bestDistSq = d; bestPos = candidate.immutable(); }
}
continue;
}
// North/South faces (dz = ±r)
for (int dx = -r; dx <= r; dx++) {
candidate.set(ox + dx, oy + dy, oz - r);
if (this.isValidWoodTarget(candidate)) {
double d = candidate.distSqr(origin);
if (d < bestDistSq) { bestDistSq = d; bestPos = candidate.immutable(); }
}
candidate.set(ox + dx, oy + dy, oz + r);
if (this.isValidWoodTarget(candidate)) {
double d = candidate.distSqr(origin);
if (d < bestDistSq) { bestDistSq = d; bestPos = candidate.immutable(); }
}
}
// East/West faces (dx = ±r, corners already covered above)
for (int dz = -r + 1; dz <= r - 1; dz++) {
candidate.set(ox - r, oy + dy, oz + dz);
if (this.isValidWoodTarget(candidate)) {
double d = candidate.distSqr(origin);
if (d < bestDistSq) { bestDistSq = d; bestPos = candidate.immutable(); }
}
candidate.set(ox + r, oy + dy, oz + dz);
if (this.isValidWoodTarget(candidate)) {
double d = candidate.distSqr(origin);
if (d < bestDistSq) { bestDistSq = d; bestPos = candidate.immutable(); }
}
}
}
}
@@ -222,9 +252,10 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
}
private boolean isWalkableStandPos(BlockPos pos) {
BlockState floorState = this.level().getBlockState(pos.below());
BlockPos floor = pos.below();
BlockState floorState = this.level().getBlockState(floor);
return this.level().getBlockState(pos).isAir()
&& this.level().getBlockState(pos.above()).isAir()
&& floorState.isFaceSturdy(this.level(), pos.below(), Direction.UP);
&& floorState.isFaceSturdy(this.level(), floor, Direction.UP);
}
}
@@ -62,6 +62,14 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
private static final String SPIN_TICKS_TAG = "antarchy.big_bertha_spin_ticks";
private static final String SPIN_DIRECTION_X_TAG = "antarchy.big_bertha_spin_direction_x";
private static final String SPIN_DIRECTION_Z_TAG = "antarchy.big_bertha_spin_direction_z";
private static final String TORETERROR_JUMPING_TAG = "antarchy.toreterror_jumping";
private static final String TORETERROR_LAUNCHED_TAG = "antarchy.toreterror_launched";
private static final int TORETERROR_LANDING_RADIUS = 6;
private static final int TORETERROR_COOLDOWN_TICKS = 200;
private static final int TORETERROR_SHAKE_TICKS = 25;
/** Client-side only: how many ticks of camera shake remain from a Toreterror landing. */
public static int clientShakeTicks = 0;
private static final ResourceLocation ATTACK_RANGE_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "big_bertha_attack_range");
private final Tier tier;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
@@ -116,6 +124,14 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
}
if (mode == BossMode.TORETERROR) {
if (player.getCooldowns().isOnCooldown(this)) {
return InteractionResultHolder.fail(stack);
}
startToreterrorJump(level, player, stack);
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
}
if (mode != BossMode.MOLEVORE) {
return InteractionResultHolder.pass(stack);
}
@@ -144,7 +160,7 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
case LUCID -> applyLucidHit(target, player, serverLevel);
case NIGHTMARE -> applyNightmareHit(target, serverLevel);
case KRAKEN -> applyKrakenHit(player, target, serverLevel);
case MOLEVORE -> {
case MOLEVORE, TORETERROR -> {
}
}
@@ -158,6 +174,32 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
return;
}
// Toreterror jump tracking
if (isToreterrorJumping(stack) && player.getMainHandItem() == stack) {
player.fallDistance = 0.0F; // prevent fall damage during the crash-down
boolean launched = readInt(stack, TORETERROR_LAUNCHED_TAG) == 1;
if (!launched && !player.onGround()) {
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putInt(TORETERROR_LAUNCHED_TAG, 1));
}
if (launched && player.onGround()) {
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> {
tag.remove(TORETERROR_JUMPING_TAG);
tag.remove(TORETERROR_LAUNCHED_TAG);
});
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer) {
applyToreterrorLanding((ServerLevel) level, serverPlayer);
}
if (level.isClientSide) {
clientShakeTicks = TORETERROR_SHAKE_TICKS;
}
}
}
// Tick client shake counter
if (level.isClientSide && clientShakeTicks > 0) {
clientShakeTicks--;
}
int spinTicks = getSpinTicks(stack);
if (spinTicks <= 0) {
return;
@@ -317,6 +359,43 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
}
}
private void startToreterrorJump(Level level, Player player, ItemStack stack) {
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> {
tag.putInt(TORETERROR_JUMPING_TAG, 1);
tag.remove(TORETERROR_LAUNCHED_TAG);
});
player.setDeltaMovement(player.getDeltaMovement().x, 1.5D, player.getDeltaMovement().z);
player.hasImpulse = true;
player.fallDistance = 0.0F;
player.getCooldowns().addCooldown(this, TORETERROR_COOLDOWN_TICKS);
player.awardStat(Stats.ITEM_USED.get(this));
level.playSound(null, player.blockPosition(), SoundEvents.GENERIC_EXPLODE.value(), SoundSource.PLAYERS, 1.0F, 0.6F);
}
private void applyToreterrorLanding(ServerLevel level, ServerPlayer player) {
ItemStack heldStack = player.getMainHandItem();
float damage = (float) (player.getAttributeValue(Attributes.ATTACK_DAMAGE) * 2.0D);
AABB aoe = player.getBoundingBox().inflate(TORETERROR_LANDING_RADIUS, 3.0D, TORETERROR_LANDING_RADIUS);
for (LivingEntity victim : level.getEntitiesOfClass(LivingEntity.class, aoe,
e -> e.isAlive() && e != player && !e.isSpectator())) {
victim.hurt(player.damageSources().playerAttack(player), damage);
Vec3 knockDir = victim.position().subtract(player.position()).multiply(1.0D, 0.0D, 1.0D);
if (knockDir.lengthSqr() < 1.0E-4D) knockDir = player.getLookAngle().multiply(1.0D, 0.0D, 1.0D);
Vec3 normalized = knockDir.normalize();
victim.push(normalized.x * 2.5D, 0.6D, normalized.z * 2.5D);
victim.hurtMarked = true;
}
level.playSound(null, player.blockPosition(), SoundEvents.GENERIC_EXPLODE.value(), SoundSource.PLAYERS, 1.5F, 0.75F);
level.sendParticles(ParticleTypes.EXPLOSION, player.getX(), player.getY() + 0.5D, player.getZ(), 4, 1.5D, 0.3D, 1.5D, 0.0D);
level.sendParticles(ParticleTypes.SPLASH, player.getX(), player.getY() + 0.5D, player.getZ(), 60, 3.0D, 0.5D, 3.0D, 0.2D);
level.sendParticles(ParticleTypes.CRIT, player.getX(), player.getY() + 0.5D, player.getZ(), 20, 2.0D, 0.5D, 2.0D, 0.1D);
heldStack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND);
}
private static boolean isToreterrorJumping(ItemStack stack) {
return readInt(stack, TORETERROR_JUMPING_TAG) == 1;
}
private void tickMolevoreSpin(ServerLevel level, ServerPlayer player, ItemStack stack, int spinTicks) {
Vec3 direction = getStoredSpinDirection(stack);
double verticalBoost = player.onGround() ? 0.08D : Math.max(-0.08D, player.getDeltaMovement().y);
@@ -505,7 +584,8 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
NIGHTMARE(1, "tooltip.antarchy.big_bertha.mode.nightmare", "message.antarchy.big_bertha.mode.nightmare"),
KRAKEN(2, "tooltip.antarchy.big_bertha.mode.kraken", "message.antarchy.big_bertha.mode.kraken"),
MOLEVORE(3, "tooltip.antarchy.big_bertha.mode.molevore", "message.antarchy.big_bertha.mode.molevore"),
LUCID(4, "tooltip.antarchy.big_bertha.mode.lucid", "message.antarchy.big_bertha.mode.lucid");
LUCID(4, "tooltip.antarchy.big_bertha.mode.lucid", "message.antarchy.big_bertha.mode.lucid"),
TORETERROR(5, "tooltip.antarchy.big_bertha.mode.toreterror", "message.antarchy.big_bertha.mode.toreterror");
private final int id;
private final String tooltipKey;
@@ -523,7 +603,8 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
case LUCID -> NIGHTMARE;
case NIGHTMARE -> KRAKEN;
case KRAKEN -> MOLEVORE;
case MOLEVORE -> BASILISK;
case MOLEVORE -> TORETERROR;
case TORETERROR -> BASILISK;
};
}
@@ -0,0 +1,196 @@
package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy;
import com.mojang.serialization.Codec;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.material.FluidState;
public final class CavarynBileCystFeature extends Feature<NoneFeatureConfiguration> {
private static final ResourceLocation BILE_VEIN_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile_vein");
private static final ResourceLocation BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile");
private static final int SEARCH_RADIUS = 8;
private static final int SEARCH_ATTEMPTS = 20;
private static final int VERTICAL_SCAN = 10;
// Chance that each exposed vein face oozes bile liquid outward into the cave
private static final float OOZE_CHANCE = 0.22f;
public CavarynBileCystFeature(Codec<NoneFeatureConfiguration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
Block bileVeinBlock = getBlock(BILE_VEIN_ID);
Block bileBlock = getBlock(BILE_ID);
if (bileVeinBlock == null || !(bileBlock instanceof LiquidBlock)) {
return false;
}
WorldGenLevel level = context.level();
RandomSource random = context.random();
BlockPos center = findCenter(level, context.origin(), random);
if (center == null) {
return false;
}
return placeCyst(level, center, bileVeinBlock, bileBlock, random);
}
// Find a solid block adjacent to cave air, then step 1-2 blocks deeper into the wall
// so the cyst is embedded rather than sitting right on the surface.
private static BlockPos findCenter(WorldGenLevel level, BlockPos origin, RandomSource random) {
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (int attempt = 0; attempt < SEARCH_ATTEMPTS; attempt++) {
int x = origin.getX() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int z = origin.getZ() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int y = origin.getY() + random.nextInt(VERTICAL_SCAN * 2 + 1) - VERTICAL_SCAN;
y = Mth.clamp(y, level.getMinBuildHeight() + 6, level.getMaxBuildHeight() - 6);
mutable.set(x, y, z);
if (!isSolid(level.getBlockState(mutable))) {
continue;
}
// Need at least one open neighbor (at cave surface)
Direction openDir = null;
for (Direction dir : Direction.values()) {
if (level.getBlockState(mutable.relative(dir)).canBeReplaced()) {
openDir = dir;
break;
}
}
if (openDir == null) {
continue;
}
// Step 1-2 blocks away from the opening so the cyst sits inside the wall
int depth = 1 + random.nextInt(2);
BlockPos candidate = mutable.immutable().relative(openDir.getOpposite(), depth);
if (isSolid(level.getBlockState(candidate))) {
return candidate;
}
}
return null;
}
private boolean placeCyst(WorldGenLevel level, BlockPos center, Block veinBlock, Block bileBlock, RandomSource random) {
// Per-axis radii: 1.5–13.5 so the cyst diameter ranges roughly 3–27
double rx = 1.5 + random.nextDouble() * 12.0;
double ry = 1.5 + random.nextDouble() * 12.0;
double rz = 1.5 + random.nextDouble() * 12.0;
// Random stretch: pick one axis and scale it up 1.3–2x for elongated cysts
int stretchAxis = random.nextInt(3);
if (stretchAxis == 0) rx *= 1.3 + random.nextDouble() * 0.7;
else if (stretchAxis == 1) ry *= 1.3 + random.nextDouble() * 0.7;
else rz *= 1.3 + random.nextDouble() * 0.7;
// Independent sine frequencies per wobble term — drives the lumpy distortion
double f1x = 0.6 + random.nextDouble() * 1.2;
double f1z = 0.6 + random.nextDouble() * 1.2;
double f2y = 0.7 + random.nextDouble() * 1.0;
double f2x = 0.5 + random.nextDouble() * 0.9;
double f3z = 0.8 + random.nextDouble() * 1.1;
double f3y = 0.5 + random.nextDouble() * 0.8;
double wobbleAmp = 0.15 + random.nextDouble() * 0.2; // surface roughness
int maxR = (int) Math.ceil(Math.max(Math.max(rx, ry), rz)) + 2;
List<BlockPos> placed = new ArrayList<>();
for (int dx = -maxR; dx <= maxR; dx++) {
for (int dy = -maxR; dy <= maxR; dy++) {
for (int dz = -maxR; dz <= maxR; dz++) {
double baseDist = Math.sqrt(
(dx * dx) / (rx * rx) +
(dy * dy) / (ry * ry) +
(dz * dz) / (rz * rz));
// Multi-frequency sine interference — gives lumpy, non-spherical surface
double wobble = wobbleAmp * (
0.4 * Math.sin(dx * f1x + dz * f1z) +
0.35 * Math.cos(dy * f2y + dx * f2x) +
0.25 * Math.sin(dz * f3z + dy * f3y));
double distorted = baseDist + wobble;
if (distorted > 1.0) {
continue;
}
BlockPos pos = center.offset(dx, dy, dz);
BlockState existing = level.getBlockState(pos);
if (!isSolid(existing)) {
continue;
}
if (distorted < 0.7) {
// Interior — fill with bile liquid
BlockState bileState = bileBlock.defaultBlockState();
level.setBlock(pos, bileState, 2);
scheduleFluidTick(level, pos, bileState);
} else {
// Outer shell — bile vein blocks
level.setBlock(pos, veinBlock.defaultBlockState(), 2);
placed.add(pos.immutable());
}
}
}
}
if (placed.isEmpty()) {
return false;
}
// 30% chance this cyst oozes at all
if (random.nextFloat() >= 0.30f) {
return true;
}
// Ooze bile out of exposed faces — "popped pimple" seep
for (BlockPos cystPos : placed) {
for (Direction dir : Direction.values()) {
BlockPos adj = cystPos.relative(dir);
BlockState adjState = level.getBlockState(adj);
if ((adjState.isAir() || adjState.canBeReplaced()) && random.nextFloat() < OOZE_CHANCE) {
BlockState bileState = bileBlock.defaultBlockState();
level.setBlock(adj, bileState, 2);
scheduleFluidTick(level, adj, bileState);
}
}
}
return true;
}
private static boolean isSolid(BlockState state) {
return state.blocksMotion() && !state.is(Blocks.BEDROCK) && state.getFluidState().isEmpty();
}
private static void scheduleFluidTick(WorldGenLevel level, BlockPos pos, BlockState state) {
FluidState fluidState = state.getFluidState();
if (!fluidState.isEmpty()) {
level.scheduleTick(pos, fluidState.getType(), fluidState.getType().getTickDelay(level));
}
}
private static Block getBlock(ResourceLocation id) {
Optional<Block> block = BuiltInRegistries.BLOCK.getOptional(id);
return block.orElse(null);
}
}
@@ -1,150 +0,0 @@
package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy;
import com.mojang.serialization.Codec;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.material.FluidState;
public final class CavarynBilePoolFeature extends Feature<NoneFeatureConfiguration> {
private static final ResourceLocation BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile");
private static final int SEARCH_RADIUS = 8;
private static final int SEARCH_ATTEMPTS = 24;
private static final int FLOOR_SCAN_RANGE = 14;
public CavarynBilePoolFeature(Codec<NoneFeatureConfiguration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
Block bileBlock = getBlock(BILE_ID);
if (!(bileBlock instanceof LiquidBlock)) {
return false;
}
WorldGenLevel level = context.level();
RandomSource random = context.random();
BlockPos floorCenter = findPoolFloor(level, context.origin(), random);
if (floorCenter == null) {
return false;
}
return placePool(level, floorCenter, bileBlock.defaultBlockState(), random);
}
private static BlockPos findPoolFloor(WorldGenLevel level, BlockPos origin, RandomSource random) {
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (int attempt = 0; attempt < SEARCH_ATTEMPTS; attempt++) {
int x = origin.getX() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int z = origin.getZ() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int startY = origin.getY() + random.nextInt(FLOOR_SCAN_RANGE * 2 + 1) - FLOOR_SCAN_RANGE;
startY = Math.max(level.getMinBuildHeight() + 3, Math.min(level.getMaxBuildHeight() - 4, startY));
for (int y = startY; y >= Math.max(level.getMinBuildHeight() + 2, startY - FLOOR_SCAN_RANGE); y--) {
mutable.set(x, y, z);
BlockState floorState = level.getBlockState(mutable);
if (!isValidFloor(level, mutable, floorState)) {
continue;
}
BlockState aboveState = level.getBlockState(mutable.above());
if (!isOpenBlock(aboveState)) {
continue;
}
if (countSolidNeighbors(level, mutable) >= 3) {
return mutable.immutable();
}
}
}
return null;
}
private static boolean placePool(WorldGenLevel level, BlockPos center, BlockState bileState, RandomSource random) {
boolean placedAny = false;
int radius = 2 + random.nextInt(3);
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (int dx = -radius; dx <= radius; dx++) {
for (int dz = -radius; dz <= radius; dz++) {
double normalized = (dx * dx + dz * dz) / (double) Math.max(1, radius * radius);
if (normalized > 1.0D + random.nextDouble() * 0.2D) {
continue;
}
double density = 1.0D - Math.min(1.0D, normalized);
int localDepth = density > 0.45D || random.nextFloat() < 0.35F ? 2 : 1;
localDepth = Mth.clamp(localDepth, 1, 2);
for (int depth = 0; depth < localDepth; depth++) {
mutable.set(center.getX() + dx, center.getY() - depth, center.getZ() + dz);
BlockState existing = level.getBlockState(mutable);
FluidState existingFluid = existing.getFluidState();
if (existing.is(Blocks.BEDROCK)) {
break;
}
if (!existing.canBeReplaced() && existingFluid.isEmpty() && !existing.blocksMotion()) {
continue;
}
level.setBlock(mutable, bileState, 2);
scheduleFluidTick(level, mutable, bileState);
placedAny = true;
}
}
}
return placedAny;
}
private static boolean isValidFloor(WorldGenLevel level, BlockPos pos, BlockState state) {
return !state.isAir()
&& !state.is(Blocks.BEDROCK)
&& state.getFluidState().isEmpty()
&& state.blocksMotion()
&& state.isFaceSturdy(level, pos, Direction.UP);
}
private static boolean isOpenBlock(BlockState state) {
return state.isAir() || state.canBeReplaced() || !state.getFluidState().isEmpty();
}
private static int countSolidNeighbors(WorldGenLevel level, BlockPos pos) {
int solidNeighbors = 0;
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (Direction direction : Direction.Plane.HORIZONTAL) {
mutable.setWithOffset(pos, direction);
if (isValidFloor(level, mutable, level.getBlockState(mutable))) {
solidNeighbors++;
}
}
return solidNeighbors;
}
private static void scheduleFluidTick(WorldGenLevel level, BlockPos pos, BlockState state) {
FluidState fluidState = state.getFluidState();
if (!fluidState.isEmpty()) {
level.scheduleTick(pos, fluidState.getType(), fluidState.getType().getTickDelay(level));
}
}
private static Block getBlock(ResourceLocation id) {
Optional<Block> block = BuiltInRegistries.BLOCK.getOptional(id);
return block.orElse(null);
}
}
@@ -0,0 +1,238 @@
package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy;
import com.mojang.serialization.Codec;
import java.util.*;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.material.FluidState;
public final class CavarynBileVeinFeature extends Feature<NoneFeatureConfiguration> {
private static final ResourceLocation BILE_VEIN_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile_vein");
private static final ResourceLocation BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile");
private static final int SEARCH_RADIUS = 10;
private static final int SEARCH_ATTEMPTS = 24;
private static final int VERTICAL_SCAN = 12;
private static final float BRANCH_CHANCE = 0.12f;
private static final float LIQUID_POCKET_CHANCE = 0.04f;
public CavarynBileVeinFeature(Codec<NoneFeatureConfiguration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
Block bileVeinBlock = getBlock(BILE_VEIN_ID);
Block bileBlock = getBlock(BILE_ID);
if (bileVeinBlock == null || !(bileBlock instanceof LiquidBlock)) {
return false;
}
WorldGenLevel level = context.level();
RandomSource random = context.random();
BlockPos start = findStart(level, context.origin(), random);
if (start == null) {
return false;
}
return growVeinNetwork(level, start, bileVeinBlock, bileBlock, random);
}
// Find a solid block that sits at a cave boundary
private static BlockPos findStart(WorldGenLevel level, BlockPos origin, RandomSource random) {
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (int attempt = 0; attempt < SEARCH_ATTEMPTS; attempt++) {
int x = origin.getX() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int z = origin.getZ() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int y = origin.getY() + random.nextInt(VERTICAL_SCAN * 2 + 1) - VERTICAL_SCAN;
y = Mth.clamp(y, level.getMinBuildHeight() + 2, level.getMaxBuildHeight() - 3);
mutable.set(x, y, z);
if (!isVeinCandidate(level.getBlockState(mutable))) {
continue;
}
for (Direction dir : Direction.values()) {
if (level.getBlockState(mutable.relative(dir)).canBeReplaced()) {
return mutable.immutable();
}
}
}
return null;
}
private boolean growVeinNetwork(WorldGenLevel level, BlockPos start, Block veinBlock, Block bileBlock, RandomSource random) {
Set<BlockPos> visited = new HashSet<>();
List<BranchStart> pendingBranches = new ArrayList<>();
boolean placedAny = false;
Direction mainDir = Direction.values()[random.nextInt(6)];
placedAny |= growArm(level, start, mainDir, 45 + random.nextInt(25), visited, pendingBranches, veinBlock, bileBlock, random);
for (BranchStart branch : pendingBranches) {
Direction branchDir = perpendiculars(branch.dir())[random.nextInt(4)];
int branchLen = 15 + random.nextInt(20);
growArm(level, branch.pos(), branchDir, branchLen, visited, null, veinBlock, bileBlock, random);
}
return placedAny;
}
private boolean growArm(
WorldGenLevel level,
BlockPos start,
Direction initialDir,
int maxSteps,
Set<BlockPos> visited,
List<BranchStart> branches,
Block veinBlock,
Block bileBlock,
RandomSource random
) {
BlockPos current = start;
Direction dir = initialDir;
boolean placedAny = false;
for (int step = 0; step < maxSteps; step++) {
if (visited.contains(current)) {
current = current.relative(biasedNextDir(dir, random));
continue;
}
BlockState state = level.getBlockState(current);
if (!isVeinCandidate(state)) {
// Try to redirect
BlockPos redirect = findSolidNeighbor(current, dir, visited, level, random);
if (redirect == null) {
break;
}
current = redirect;
state = level.getBlockState(current);
if (!isVeinCandidate(state)) {
break;
}
}
visited.add(current);
level.setBlock(current, veinBlock.defaultBlockState(), 2);
placedAny = true;
if (random.nextFloat() < LIQUID_POCKET_CHANCE) {
tryPlaceLiquidPocket(level, current, bileBlock, visited, random);
}
if (branches != null && random.nextFloat() < BRANCH_CHANCE) {
Direction[] perps = perpendiculars(dir);
branches.add(new BranchStart(current, perps[random.nextInt(perps.length)]));
}
dir = biasedNextDir(dir, random);
current = current.relative(dir);
}
return placedAny;
}
private static Direction biasedNextDir(Direction current, RandomSource random) {
int roll = random.nextInt(10);
if (roll < 6) {
return current;
}
return perpendiculars(current)[roll - 6];
}
private static BlockPos findSolidNeighbor(BlockPos from, Direction preferredDir, Set<BlockPos> visited, WorldGenLevel level, RandomSource random) {
Direction[] perps = perpendiculars(preferredDir);
for (int i = perps.length - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
Direction tmp = perps[i];
perps[i] = perps[j];
perps[j] = tmp;
}
for (Direction d : perps) {
BlockPos candidate = from.relative(d);
if (!visited.contains(candidate) && isVeinCandidate(level.getBlockState(candidate))) {
return candidate;
}
}
return null;
}
private static void tryPlaceLiquidPocket(WorldGenLevel level, BlockPos veinPos, Block bileBlock, Set<BlockPos> visited, RandomSource random) {
Direction[] dirs = Direction.values().clone();
for (int i = dirs.length - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
Direction tmp = dirs[i];
dirs[i] = dirs[j];
dirs[j] = tmp;
}
for (Direction d : dirs) {
BlockPos candidate = veinPos.relative(d);
if (visited.contains(candidate)) {
continue;
}
BlockState candidateState = level.getBlockState(candidate);
if (!isVeinCandidate(candidateState)) {
continue;
}
if (isEnclosed(level, candidate) || random.nextFloat() < 0.05f) {
BlockState bileState = bileBlock.defaultBlockState();
level.setBlock(candidate, bileState, 2);
scheduleFluidTick(level, candidate, bileState);
visited.add(candidate);
return;
}
}
}
private static boolean isEnclosed(WorldGenLevel level, BlockPos pos) {
for (Direction d : Direction.values()) {
BlockState neighbor = level.getBlockState(pos.relative(d));
if (neighbor.isAir() || neighbor.canBeReplaced()) {
return false;
}
}
return true;
}
private static boolean isVeinCandidate(BlockState state) {
return state.blocksMotion() && !state.is(Blocks.BEDROCK) && state.getFluidState().isEmpty();
}
private static Direction[] perpendiculars(Direction dir) {
return switch (dir.getAxis()) {
case X -> new Direction[]{Direction.UP, Direction.DOWN, Direction.NORTH, Direction.SOUTH};
case Z -> new Direction[]{Direction.UP, Direction.DOWN, Direction.EAST, Direction.WEST};
case Y -> new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST};
};
}
private static void scheduleFluidTick(WorldGenLevel level, BlockPos pos, BlockState state) {
FluidState fluidState = state.getFluidState();
if (!fluidState.isEmpty()) {
level.scheduleTick(pos, fluidState.getType(), fluidState.getType().getTickDelay(level));
}
}
private static Block getBlock(ResourceLocation id) {
Optional<Block> block = BuiltInRegistries.BLOCK.getOptional(id);
return block.orElse(null);
}
private record BranchStart(BlockPos pos, Direction dir) {}
}
@@ -1,23 +1,33 @@
package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.block.CreepingHorrorEggBlock;
import com.craisinlord.antarchy.content.block.LurkingTerrorEggBlock;
import com.mojang.serialization.Codec;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public final class CavarynEggPatchFeature extends Feature<NoneFeatureConfiguration> {
private static final ResourceLocation AMBER_MOSS_BLOCK_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "amber_moss_block");
private static final int SEARCH_RADIUS = 8;
private static final int SEARCH_ATTEMPTS = 20;
private static final int FLOOR_SCAN_RANGE = 10;
private static final int SEARCH_ATTEMPTS = 24;
private static final int VERTICAL_SCAN = 12;
private static final int MAX_RADIUS_Y = 3;
public CavarynEggPatchFeature(Codec<NoneFeatureConfiguration> codec) {
super(codec);
@@ -29,77 +39,118 @@ public final class CavarynEggPatchFeature extends Feature<NoneFeatureConfigurati
RandomSource random = context.random();
BlockPos origin = context.origin();
BlockPos surfacePos = findSurfacePos(level, origin, random);
if (surfacePos == null) {
Block amberMossBlock = getBlock(AMBER_MOSS_BLOCK_ID);
BlockPos center = findCavityCenter(level, origin, random);
if (center == null) {
return false;
}
EggType eggType = random.nextBoolean() ? EggType.CREEPING_HORROR : EggType.LURKING_TERROR;
return placePatch(level, surfacePos, random, eggType);
return carveCavityAndPlaceEggs(level, center, random, eggType, amberMossBlock);
}
private static BlockPos findSurfacePos(WorldGenLevel level, BlockPos origin, RandomSource random) {
private static BlockPos findCavityCenter(WorldGenLevel level, BlockPos origin, RandomSource random) {
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (int attempt = 0; attempt < SEARCH_ATTEMPTS; attempt++) {
int x = origin.getX() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int z = origin.getZ() + random.nextInt(SEARCH_RADIUS * 2 + 1) - SEARCH_RADIUS;
int startY = origin.getY() + random.nextInt(FLOOR_SCAN_RANGE * 2 + 1) - FLOOR_SCAN_RANGE;
startY = Math.max(level.getMinBuildHeight() + 2, Math.min(level.getMaxBuildHeight() - 3, startY));
int y = origin.getY() + random.nextInt(VERTICAL_SCAN * 2 + 1) - VERTICAL_SCAN;
y = Mth.clamp(y, level.getMinBuildHeight() + MAX_RADIUS_Y + 2, level.getMaxBuildHeight() - MAX_RADIUS_Y - 2);
for (int y = startY; y >= Math.max(level.getMinBuildHeight() + 1, startY - FLOOR_SCAN_RANGE); y--) {
mutable.set(x, y, z);
BlockState floorState = level.getBlockState(mutable);
BlockState airState = level.getBlockState(mutable.above());
if (floorState.getFluidState().isEmpty()
&& floorState.blocksMotion()
&& floorState.isFaceSturdy(level, mutable, Direction.UP)
&& airState.canBeReplaced()) {
return mutable.immutable();
}
mutable.set(x, y, z);
if (isSolidEnoughForCavity(level, mutable)) {
return mutable.immutable();
}
}
return null;
}
private boolean placePatch(WorldGenLevel level, BlockPos center, RandomSource random, EggType eggType) {
int radius = 2 + random.nextInt(3);
boolean placedAny = false;
List<BlockPos> eggSpots = new java.util.ArrayList<>();
private static boolean isSolidEnoughForCavity(WorldGenLevel level, BlockPos center) {
BlockState centerState = level.getBlockState(center);
if (!centerState.blocksMotion() || centerState.is(Blocks.BEDROCK)) {
return false;
}
for (int dx = -radius; dx <= radius; dx++) {
for (int dz = -radius; dz <= radius; dz++) {
double distance = dx * dx + dz * dz;
if (distance > radius * radius + random.nextInt(2)) {
continue;
int solidCount = 0;
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (int dx = -2; dx <= 2; dx += 2) {
for (int dy = -1; dy <= 1; dy++) {
for (int dz = -2; dz <= 2; dz += 2) {
mutable.set(center.getX() + dx, center.getY() + dy, center.getZ() + dz);
if (level.getBlockState(mutable).blocksMotion()) {
solidCount++;
}
}
}
}
return solidCount >= 9;
}
BlockPos floorPos = center.offset(dx, 0, dz);
BlockState floorState = level.getBlockState(floorPos);
BlockPos eggPos = floorPos.above();
BlockState aboveState = level.getBlockState(eggPos);
if (!isValidEggFloor(level, floorPos, floorState, aboveState)) {
continue;
private boolean carveCavityAndPlaceEggs(WorldGenLevel level, BlockPos center, RandomSource random, EggType eggType, Block amberMossBlock) {
int rx = 3 + random.nextInt(3);
int ry = 2 + random.nextInt(2);
int rz = 3 + random.nextInt(3);
for (int dx = -rx; dx <= rx; dx++) {
for (int dy = -ry; dy <= ry; dy++) {
for (int dz = -rz; dz <= rz; dz++) {
double norm = (double)(dx * dx) / (rx * rx)
+ (double)(dy * dy) / (ry * ry)
+ (double)(dz * dz) / (rz * rz);
if (norm > 1.0) {
continue;
}
BlockPos pos = center.offset(dx, dy, dz);
BlockState existing = level.getBlockState(pos);
if (!existing.is(Blocks.BEDROCK) && existing.blocksMotion() && existing.getFluidState().isEmpty()) {
level.setBlock(pos, Blocks.AIR.defaultBlockState(), 2);
}
}
eggSpots.add(eggPos);
}
}
if (eggSpots.isEmpty()) {
return placedAny;
List<BlockPos> eggPositions = new ArrayList<>();
for (int dx = -rx; dx <= rx; dx++) {
for (int dy = -ry - 1; dy <= ry; dy++) {
for (int dz = -rz; dz <= rz; dz++) {
BlockPos pos = center.offset(dx, dy, dz);
if (!level.getBlockState(pos).isAir()) {
continue;
}
BlockPos below = pos.below();
BlockState belowState = level.getBlockState(below);
if (belowState.blocksMotion() && !belowState.isAir() && belowState.isFaceSturdy(level, below, Direction.UP)) {
eggPositions.add(pos);
}
}
}
}
int eggCount = Math.min(eggSpots.size(), 2 + random.nextInt(3));
for (int i = 0; i < eggCount; i++) {
BlockPos eggPos = eggSpots.get(random.nextInt(eggSpots.size()));
if (!level.getBlockState(eggPos).canBeReplaced()) {
if (eggPositions.isEmpty()) {
return false;
}
boolean placedAny = false;
for (BlockPos eggPos : eggPositions) {
if (random.nextFloat() > 0.65f) {
continue;
}
// Replace the floor block with amber moss so eggs hatch faster
if (amberMossBlock != null) {
BlockPos floorPos = eggPos.below();
BlockState floorState = level.getBlockState(floorPos);
if (floorState.blocksMotion() && !floorState.is(Blocks.BEDROCK) && floorState.getFluidState().isEmpty()) {
level.setBlock(floorPos, amberMossBlock.defaultBlockState(), 2);
}
}
BlockState eggState = eggType == EggType.CREEPING_HORROR
? AntarchyObjects.CREEPING_HORROR_EGGS.get().defaultBlockState()
: AntarchyObjects.LURKING_TERROR_EGGS.get().defaultBlockState();
eggState = eggState.setValue(eggType == EggType.CREEPING_HORROR ? CreepingHorrorEggBlock.EGGS : LurkingTerrorEggBlock.EGGS, 1 + random.nextInt(4));
eggState = eggState.setValue(
eggType == EggType.CREEPING_HORROR ? CreepingHorrorEggBlock.EGGS : LurkingTerrorEggBlock.EGGS,
1 + random.nextInt(4));
level.setBlock(eggPos, eggState, 3);
placedAny = true;
}
@@ -107,12 +158,9 @@ public final class CavarynEggPatchFeature extends Feature<NoneFeatureConfigurati
return placedAny;
}
private static boolean isValidEggFloor(WorldGenLevel level, BlockPos floorPos, BlockState floorState, BlockState aboveState) {
return !floorState.isAir()
&& floorState.getFluidState().isEmpty()
&& floorState.blocksMotion()
&& floorState.isFaceSturdy(level, floorPos, Direction.UP)
&& aboveState.canBeReplaced();
private static Block getBlock(ResourceLocation id) {
Optional<Block> block = BuiltInRegistries.BLOCK.getOptional(id);
return block.orElse(null);
}
private enum EggType {
@@ -118,12 +118,15 @@ public class ElythiaBiomeSource extends BiomeSource {
// and ambient effects work correctly above the water surface.
Climate.TargetPoint target = sampler.sample(x, this.seaLevelQuartY, z);
if (target.continentalness() < OCEAN_CONTINENTALNESS_THRESHOLD) {
return this.delegate.getNoiseBiome(x, this.seaLevelQuartY, z, sampler);
Holder<Biome> seaLevelBiome = this.delegate.getNoiseBiome(x, this.seaLevelQuartY, z, sampler);
// MultiNoise can return a land biome at sea-level depth — force ocean if so
if (isOceanBiome(seaLevelBiome)) return seaLevelBiome;
return oceanHolder != null ? oceanHolder : seaLevelBiome;
}
// Land column below or at sea level: force ocean for any biome not allowed there.
// Use <= so quart 19 (blocks 76-79, partly underwater) is covered.
if (y <= this.seaLevelQuartY && oceanHolder != null && !allowedBelowSeaLevel(biome)) {
// Land column at or below sea level: force ocean for any biome not allowed there.
// +1 quart above seaLevelQuartY so blocks 76-83 (around the waterline) are all caught.
if (y <= this.seaLevelQuartY + 1 && oceanHolder != null && !allowedBelowSeaLevel(biome)) {
return oceanHolder;
}
@@ -0,0 +1,144 @@
package com.craisinlord.antarchy.content.worldgen.elythia;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class FallenOuranwoodFeature extends Feature<NoneFeatureConfiguration> {
public FallenOuranwoodFeature(Codec<NoneFeatureConfiguration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
WorldGenLevel level = context.level();
RandomSource random = context.random();
BlockPos origin = context.origin();
Direction.Axis axis = random.nextBoolean() ? Direction.Axis.X : Direction.Axis.Z;
int length = 36 + random.nextInt(44); // 36–79 blocks long
int outerRadius = 1 + random.nextInt(3); // 1–3 (cross-section up to 7-wide)
boolean hollow = outerRadius >= 2;
Block ouranwoodLog = BuiltInRegistries.BLOCK.getOptional(
ResourceLocation.fromNamespaceAndPath("antarchy", "ouranwood_log"))
.orElse(AntarchyObjects.MOSSY_OURANWOOD_LOG.get());
BlockState mossyLogState = AntarchyObjects.MOSSY_OURANWOOD_LOG.get().defaultBlockState()
.setValue(RotatedPillarBlock.AXIS, axis);
BlockState freshLogState = ouranwoodLog.defaultBlockState()
.setValue(RotatedPillarBlock.AXIS, axis);
BlockState woodState = AntarchyObjects.MOSSY_OURANWOOD_WOOD.get().defaultBlockState()
.setValue(RotatedPillarBlock.AXIS, Direction.Axis.Y);
// Pre-generate a smoothed damage profile along the length (0=solid, 1=gap)
float[] damage = new float[length];
for (int i = 0; i < length; i++) damage[i] = random.nextFloat();
for (int pass = 0; pass < 4; pass++) {
for (int i = 1; i < length - 1; i++) {
damage[i] = (damage[i - 1] + damage[i] * 2 + damage[i + 1]) / 4f;
}
}
// Bias upward so more sections are heavily damaged
for (int i = 0; i < length; i++) damage[i] = damage[i] * damage[i];
int anchorY = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, origin.getX(), origin.getZ());
boolean placed = false;
for (int step = 0; step < length; step++) {
int bx = axis == Direction.Axis.X ? origin.getX() + step : origin.getX();
int bz = axis == Direction.Axis.Z ? origin.getZ() + step : origin.getZ();
float dmg = damage[step];
// Full gap sections — log has completely rotted through here
if (dmg > 0.78f) continue;
int surfaceY = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, bx, bz);
int centerY = Math.max(anchorY, Math.min(anchorY + 2, surfaceY)) + outerRadius;
for (int dy = -outerRadius; dy <= outerRadius; dy++) {
for (int dp = -outerRadius; dp <= outerRadius; dp++) {
double dist = Math.sqrt(dy * dy + dp * dp);
if (dist > outerRadius + 0.5) continue;
boolean isShell = dist >= outerRadius - 0.5;
// Hollow interior: always skip center when hollow
if (hollow && dist < outerRadius - 0.5) continue;
// Heavy-damage sections: only keep fragments of the shell
if (dmg > 0.55f && !isShell) continue;
if (dmg > 0.55f && random.nextFloat() < (dmg - 0.55f) * 3.5f) continue;
// All sections: random rot holes punched through the shell
if (isShell && random.nextFloat() < dmg * 0.4f) continue;
int px = axis == Direction.Axis.X ? bx : bx + dp;
int pz = axis == Direction.Axis.Z ? bz : bz + dp;
BlockPos pos = new BlockPos(px, centerY + dy, pz);
if (!canReplace(level.getBlockState(pos))) continue;
// Block material mix: mostly mossy log, some fresh log patches, some moss
float r = random.nextFloat();
BlockState toPlace;
if (r < 0.08f) {
toPlace = Blocks.MOSS_BLOCK.defaultBlockState();
} else if (r < 0.22f) {
toPlace = freshLogState; // fresher wood, less decayed patch
} else if (r < 0.32f) {
toPlace = woodState;
} else {
toPlace = mossyLogState;
}
level.setBlock(pos, toPlace, 2);
placed = true;
}
}
}
// Moss patches scattered along the log's footprint
int mossCount = 20 + random.nextInt(25);
for (int i = 0; i < mossCount; i++) {
int mx = origin.getX() + random.nextInt(length + 6) - 3;
int mz = axis == Direction.Axis.X
? origin.getZ() + random.nextInt(9) - 4
: origin.getZ() + random.nextInt(length + 6) - 3;
int my = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, mx, mz);
BlockPos mossPos = new BlockPos(mx, my, mz);
if (!canReplace(level.getBlockState(mossPos))) continue;
BlockState below = level.getBlockState(mossPos.below());
if (!below.isFaceSturdy(level, mossPos.below(), Direction.UP)) continue;
level.setBlock(mossPos,
random.nextFloat() < 0.35f
? Blocks.MOSS_BLOCK.defaultBlockState()
: Blocks.MOSS_CARPET.defaultBlockState(),
2);
}
return placed;
}
private static boolean canReplace(BlockState state) {
return state.isAir() || state.canBeReplaced() || (state.getBlock() instanceof LeavesBlock);
}
}
@@ -0,0 +1,190 @@
package com.craisinlord.antarchy.content.worldgen.elythia;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.HugeMushroomBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class FungalMushroomFeature extends Feature<NoneFeatureConfiguration> {
public FungalMushroomFeature(Codec<NoneFeatureConfiguration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
WorldGenLevel level = context.level();
RandomSource random = context.random();
BlockPos origin = context.origin();
boolean isRed = random.nextBoolean();
Block capBlock = isRed ? Blocks.RED_MUSHROOM_BLOCK : Blocks.BROWN_MUSHROOM_BLOCK;
Block smallMushroom = isRed ? Blocks.RED_MUSHROOM : Blocks.BROWN_MUSHROOM;
// 1-in-3 chance of a large mushroom (~3x the small variant)
boolean isLarge = random.nextInt(3) == 0;
int stemSize = isLarge ? (2 + random.nextInt(3)) : (random.nextBoolean() ? 2 : 3);
int stemHeight = isLarge ? (18 + random.nextInt(19)) : (6 + random.nextInt(7)); // large: 18–36, small: 6–12
// Lean: stem drifts in a random horizontal direction over its height
double leanAngle = random.nextDouble() * Math.PI * 2;
double leanDX = Math.cos(leanAngle);
double leanDZ = Math.sin(leanAngle);
double maxLean = isLarge
? (6.0 + random.nextDouble() * 10.0) // large: 6–16 block lean
: (2.0 + random.nextDouble() * 3.5); // small: 2–5.5 block lean
int baseY = origin.getY();
int stemOffset = stemSize == 2 ? 0 : -1; // center 3x3 on origin
// Pore-only stem state (inner faces; sides visible from outside)
BlockState stemPore = Blocks.MUSHROOM_STEM.defaultBlockState()
.setValue(HugeMushroomBlock.NORTH, false)
.setValue(HugeMushroomBlock.SOUTH, false)
.setValue(HugeMushroomBlock.EAST, false)
.setValue(HugeMushroomBlock.WEST, false)
.setValue(HugeMushroomBlock.UP, false)
.setValue(HugeMushroomBlock.DOWN, false);
BlockState stemSide = Blocks.MUSHROOM_STEM.defaultBlockState()
.setValue(HugeMushroomBlock.NORTH, true)
.setValue(HugeMushroomBlock.SOUTH, true)
.setValue(HugeMushroomBlock.EAST, true)
.setValue(HugeMushroomBlock.WEST, true)
.setValue(HugeMushroomBlock.UP, false)
.setValue(HugeMushroomBlock.DOWN, false);
// Place leaning stem
for (int dy = 0; dy < stemHeight; dy++) {
double leanProgress = (double) dy / stemHeight;
int leanX = (int) Math.round(leanDX * maxLean * leanProgress);
int leanZ = (int) Math.round(leanDZ * maxLean * leanProgress);
for (int dx = 0; dx < stemSize; dx++) {
for (int dz = 0; dz < stemSize; dz++) {
BlockPos pos = new BlockPos(
origin.getX() + stemOffset + dx + leanX,
baseY + dy,
origin.getZ() + stemOffset + dz + leanZ);
if (canReplace(level.getBlockState(pos))) {
// Outer ring shows bark, interior is pores
boolean isEdge = (dx == 0 || dx == stemSize - 1 || dz == 0 || dz == stemSize - 1);
level.setBlock(pos, isEdge ? stemSide : stemPore, 2);
}
}
}
}
// Cap: cone-shaped, follows the lean, with irregular per-block radius noise
double capCenterX = origin.getX() + (stemSize == 2 ? 0.5 : 0) + leanDX * maxLean;
double capCenterZ = origin.getZ() + (stemSize == 2 ? 0.5 : 0) + leanDZ * maxLean;
int capTopY = baseY + stemHeight;
int baseCapRadius = isLarge
? (stemSize + 7 + random.nextInt(6)) // large: ~11–18 at base
: (stemSize + 2 + random.nextInt(2)); // small: 4–6 at base
// Per-position radius jitter table — sampled before the loop for consistency
// Each (dx, dz) slot gets a random ±1.5 bias baked in
int jitterRange = baseCapRadius + 4;
float[][] jitter = new float[jitterRange * 2 + 1][jitterRange * 2 + 1];
for (float[] row : jitter) {
for (int j = 0; j < row.length; j++) {
row[j] = random.nextFloat() * 3.0f - 1.5f; // ±1.5 blocks
}
}
int capLayers = baseCapRadius + 2;
for (int cl = 0; cl < capLayers; cl++) {
int capY = capTopY + cl;
double nomRadius = baseCapRadius - cl;
if (nomRadius < 0) break;
// The cap center also shifts slightly with lean for a drooping overhang feel
double layerCapX = capCenterX + leanDX * cl * 0.3;
double layerCapZ = capCenterZ + leanDZ * cl * 0.3;
for (int dx = -(jitterRange); dx <= jitterRange; dx++) {
for (int dz = -(jitterRange); dz <= jitterRange; dz++) {
double dist = Math.sqrt(
(origin.getX() + dx - layerCapX) * (origin.getX() + dx - layerCapX)
+ (origin.getZ() + dz - layerCapZ) * (origin.getZ() + dz - layerCapZ));
float j = jitter[dx + jitterRange][dz + jitterRange];
double effectiveRadius = nomRadius + j;
if (dist > effectiveRadius + 0.5) continue;
if (effectiveRadius < 0) continue;
BlockPos capPos = new BlockPos(origin.getX() + dx, capY, origin.getZ() + dz);
if (!canReplace(level.getBlockState(capPos))) continue;
boolean isOuter = dist >= effectiveRadius - 0.7;
boolean isTop = cl == capLayers - 1;
BlockState capState = capBlock.defaultBlockState()
.setValue(HugeMushroomBlock.UP, isTop || isOuter)
.setValue(HugeMushroomBlock.NORTH, isOuter)
.setValue(HugeMushroomBlock.SOUTH, isOuter)
.setValue(HugeMushroomBlock.EAST, isOuter)
.setValue(HugeMushroomBlock.WEST, isOuter)
.setValue(HugeMushroomBlock.DOWN, false);
level.setBlock(capPos, capState, 2);
}
}
}
// Mycelium patches around base
int myceliumCount = isLarge ? (25 + random.nextInt(25)) : (12 + random.nextInt(12));
for (int i = 0; i < myceliumCount; i++) {
int radius = isLarge ? (stemSize + 8 + random.nextInt(8)) : (stemSize + 3 + random.nextInt(3));
int mx = origin.getX() + random.nextInt(radius * 2 + 1) - radius;
int mz = origin.getZ() + random.nextInt(radius * 2 + 1) - radius;
int my = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, mx, mz) - 1;
BlockPos myceliumPos = new BlockPos(mx, my, mz);
BlockState existing = level.getBlockState(myceliumPos);
if (existing.is(Blocks.GRASS_BLOCK) || existing.is(Blocks.DIRT)
|| existing.is(Blocks.MOSS_BLOCK) || existing.is(Blocks.ROOTED_DIRT)) {
level.setBlock(myceliumPos, Blocks.MYCELIUM.defaultBlockState(), 2);
}
}
// Small mushrooms scattered around
int smallCount = isLarge ? (10 + random.nextInt(15)) : (5 + random.nextInt(8));
for (int i = 0; i < smallCount; i++) {
int radius = isLarge ? (stemSize + 10 + random.nextInt(10)) : (stemSize + 4 + random.nextInt(4));
int sx = origin.getX() + random.nextInt(radius * 2 + 1) - radius;
int sz = origin.getZ() + random.nextInt(radius * 2 + 1) - radius;
int sy = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, sx, sz);
BlockPos smallPos = new BlockPos(sx, sy, sz);
if (!canReplace(level.getBlockState(smallPos))) continue;
BlockState below = level.getBlockState(smallPos.below());
if (!below.isFaceSturdy(level, smallPos.below(), Direction.UP)) continue;
Block plant = random.nextBoolean() ? smallMushroom
: (isRed ? Blocks.BROWN_MUSHROOM : Blocks.RED_MUSHROOM);
BlockState plantState = plant.defaultBlockState();
if (plantState.canSurvive(level, smallPos)) {
level.setBlock(smallPos, plantState, 2);
}
}
return true;
}
private static boolean canReplace(BlockState state) {
return state.isAir() || state.canBeReplaced()
|| (state.getBlock() instanceof net.minecraft.world.level.block.LeavesBlock);
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "antarchy:block/bile_vein"
}
}
}
@@ -27,6 +27,7 @@
"block.antarchy.amber_moss_block": "Amber Moss Block",
"block.antarchy.amber_moss_carpet": "Amber Moss Carpet",
"block.antarchy.amber_lichen": "Amber Lichen",
"block.antarchy.bile_vein": "Bile Vein",
"block.antarchy.duplicator_sapling": "Duplicator Sapling",
"block.antarchy.creepvine": "Creepvine",
"block.antarchy.duct_tape": "Duct Tape",
@@ -272,6 +273,7 @@
"item.antarchy.amber_moss_block": "Amber Moss Block",
"item.antarchy.amber_moss_carpet": "Amber Moss Carpet",
"item.antarchy.amber_lichen": "Amber Lichen",
"item.antarchy.bile_vein": "Bile Vein",
"item.antarchy.creepvine": "Creepvine",
"item.antarchy.chiten": "Chiten",
"item.antarchy.chiten_block": "Chiten Block",
@@ -416,6 +418,7 @@
"message.antarchy.big_bertha.mode.nightmare": "Nightmare",
"message.antarchy.big_bertha.mode.kraken": "Kraken",
"message.antarchy.big_bertha.mode.molevore": "Molevore",
"message.antarchy.big_bertha.mode.toreterror": "Toreterror",
"message.antarchy.ultimate_tool.mode_3x3": "Switched to 3x3 Mining",
"message.antarchy.ultimate_tool.mode_default": "Switched to Default Mining",
"advancements.antarchy.hey_listen.title": "Hey Listen",
@@ -442,6 +445,7 @@
"tooltip.antarchy.big_bertha.mode.nightmare": "Players suffer Dread; hits inflict weakness.",
"tooltip.antarchy.big_bertha.mode.kraken": "Hits slam targets back and call lightning.",
"tooltip.antarchy.big_bertha.mode.molevore": "Right-click to spin forward and drill through Molevore blocks.",
"tooltip.antarchy.big_bertha.mode.toreterror": "Right-click to launch into the air and crash down with an AOE shockwave.",
"tooltip.antarchy.ultimate_tools_3x3": "Shift-right-click to toggle 3x3 Mining.",
"tooltip.antarchy.moggles.reveal": "Gives night vision and points to nearby caves.",
"tooltip.antarchy.moggles.underground": "Works only while you have no sky access.",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "antarchy:block/bile/bile_vein"
}
}
@@ -0,0 +1,3 @@
{
"parent": "antarchy:block/bile_vein"
}
@@ -0,0 +1,5 @@
{
"textures": [
"antarchy:stinky_fly"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

@@ -0,0 +1,16 @@
{
"animation": {
"frametime": 16,
"interpolate": true,
"frames": [
0,
1,
0,
2,
0,
1,
2,
1
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

@@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "antarchy:bile_vein"
}
],
"rolls": 1.0
}
],
"random_sequence": "antarchy:blocks/bile_vein"
}
@@ -37,11 +37,10 @@
[],
[],
[
"antarchy:cavaryn_bile_pools",
"antarchy:cavaryn_amber_moss_patch",
"antarchy:cavaryn_bile_veins",
"antarchy:cavaryn_bile_cysts",
"antarchy:cavaryn_wall_amber_moss",
"antarchy:cavaryn_creepvine",
"minecraft:glow_lichen",
"antarchy:cavaryn_chiten_spikes",
"antarchy:cavaryn_terror_egg_patch"
],
@@ -63,15 +62,16 @@
"maxCount": 5
}
],
"creature": [],
"ambient": [
"creature": [
{
"type": "minecraft:bat",
"type": "antarchy:stink_bug",
"weight": 10,
"minCount": 4,
"maxCount": 8
"minCount": 1,
"maxCount": 3
}
],
"ambient": [
],
"axolotls": [],
"underground_water_creature": [],
"water_creature": [],
@@ -0,0 +1,102 @@
{
"has_precipitation": false,
"temperature": 0.78,
"downfall": 0.95,
"effects": {
"fog_color": 8084735,
"water_color": 5021432,
"water_fog_color": 2502722,
"sky_color": 8084735,
"foliage_color": 2867501,
"grass_color": 4304168,
"grass_color_modifier": "none",
"particle": {
"probability": 0.009,
"options": {
"type": "minecraft:spore_blossom_air"
}
},
"mood_sound": {
"sound": "minecraft:ambient.crimson_forest.mood",
"tick_delay": 6000,
"block_search_extent": 8,
"offset": 2.0
}
},
"spawn_costs": {},
"carvers": {
"air": [],
"liquid": []
},
"features": [
[],
[],
[],
[],
[],
[],
[
"minecraft:ore_coal_upper",
"minecraft:ore_coal_lower",
"minecraft:ore_iron_upper",
"minecraft:ore_iron_middle",
"minecraft:ore_iron_small",
"minecraft:ore_gold",
"minecraft:ore_gold_lower",
"minecraft:ore_redstone",
"minecraft:ore_redstone_lower",
"minecraft:ore_diamond",
"minecraft:ore_diamond_medium",
"minecraft:ore_diamond_large",
"minecraft:ore_diamond_buried",
"minecraft:ore_lapis",
"minecraft:ore_lapis_buried",
"minecraft:ore_copper"
],
[
"antarchy:elythia_underground",
"minecraft:large_dripstone",
"minecraft:pointed_dripstone"
],
[],
[
"antarchy:ouranwood_trees_sparse",
"antarchy:elythia_forest_flora",
"antarchy:elythia_brown_ant_nests",
"antarchy:fallen_ouranwood_tree",
"antarchy:fungal_mushroom"
],
[]
],
"creature_spawn_probability": 0.07,
"spawners": {
"monster": [],
"creature": [
{
"type": "antarchy:caterpillar",
"weight": 5,
"minCount": 1,
"maxCount": 2
},
{
"type": "antarchy:flying_squirrel",
"weight": 2,
"minCount": 1,
"maxCount": 2
}
],
"ambient": [
{
"type": "antarchy:butterfly",
"weight": 7,
"minCount": 1,
"maxCount": 2
}
],
"axolotls": [],
"underground_water_creature": [],
"water_creature": [],
"water_ambient": [],
"misc": []
}
}
@@ -0,0 +1,4 @@
{
"type": "antarchy:cavaryn_bile_cysts",
"config": {}
}
@@ -1,4 +0,0 @@
{
"type": "antarchy:cavaryn_bile_pools",
"config": {}
}
@@ -0,0 +1,4 @@
{
"type": "antarchy:cavaryn_bile_veins",
"config": {}
}
@@ -0,0 +1,4 @@
{
"type": "antarchy:fallen_ouranwood_tree",
"config": {}
}
@@ -0,0 +1,4 @@
{
"type": "antarchy:fungal_mushroom",
"config": {}
}
@@ -2,7 +2,7 @@
"sea_level": 32,
"disable_mob_generation": false,
"aquifers_enabled": true,
"ore_veins_enabled": true,
"ore_veins_enabled": false,
"legacy_random_source": false,
"default_block": {
"Name": "antarchy:myrmite"
@@ -99,73 +99,9 @@
}
}
},
"vein_toggle": {
"type": "minecraft:interpolated",
"argument": {
"type": "minecraft:range_choice",
"input": "minecraft:y",
"min_inclusive": 0,
"max_exclusive": 208,
"when_in_range": {
"type": "minecraft:noise",
"noise": "minecraft:ore_veininess",
"xz_scale": 1.5,
"y_scale": 1.5
},
"when_out_of_range": 0
}
},
"vein_ridged": {
"type": "minecraft:add",
"argument1": -0.07999999821186066,
"argument2": {
"type": "minecraft:max",
"argument1": {
"type": "minecraft:abs",
"argument": {
"type": "minecraft:interpolated",
"argument": {
"type": "minecraft:range_choice",
"input": "minecraft:y",
"min_inclusive": 0,
"max_exclusive": 208,
"when_in_range": {
"type": "minecraft:noise",
"noise": "minecraft:ore_vein_a",
"xz_scale": 4,
"y_scale": 4
},
"when_out_of_range": 0
}
}
},
"argument2": {
"type": "minecraft:abs",
"argument": {
"type": "minecraft:interpolated",
"argument": {
"type": "minecraft:range_choice",
"input": "minecraft:y",
"min_inclusive": 0,
"max_exclusive": 208,
"when_in_range": {
"type": "minecraft:noise",
"noise": "minecraft:ore_vein_b",
"xz_scale": 4,
"y_scale": 4
},
"when_out_of_range": 0
}
}
}
}
},
"vein_gap": {
"type": "minecraft:noise",
"noise": "minecraft:ore_gap",
"xz_scale": 1,
"y_scale": 1
}
"vein_toggle": 0,
"vein_ridged": 0,
"vein_gap": 0
},
"spawn_target": [
{
@@ -430,7 +430,7 @@
},
"then_run": {
"type": "minecraft:block",
"result_state": { "Name": "minecraft:gravel" }
"result_state": { "Name": "minecraft:sand" }
}
}
},
@@ -511,7 +511,7 @@
},
"then_run": {
"type": "minecraft:block",
"result_state": { "Name": "minecraft:gravel" }
"result_state": { "Name": "minecraft:sand" }
}
},
{
@@ -1,5 +1,5 @@
{
"feature": "antarchy:cavaryn_bile_pools",
"feature": "antarchy:cavaryn_bile_cysts",
"placement": [
{
"type": "minecraft:count",
@@ -0,0 +1,27 @@
{
"feature": "antarchy:cavaryn_bile_veins",
"placement": [
{
"type": "minecraft:count",
"count": 5
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:height_range",
"height": {
"type": "minecraft:uniform",
"min_inclusive": {
"above_bottom": 8
},
"max_inclusive": {
"below_top": 16
}
}
},
{
"type": "minecraft:biome"
}
]
}
@@ -3,7 +3,7 @@
"placement": [
{
"type": "minecraft:count",
"count": 2
"count": 1
},
{
"type": "minecraft:in_square"
@@ -0,0 +1,9 @@
{
"feature": "antarchy:fallen_ouranwood_tree",
"placement": [
{ "type": "minecraft:rarity_filter", "chance": 5 },
{ "type": "minecraft:in_square" },
{ "type": "minecraft:heightmap", "heightmap": "WORLD_SURFACE_WG" },
{ "type": "minecraft:biome" }
]
}
@@ -0,0 +1,9 @@
{
"feature": "antarchy:fungal_mushroom",
"placement": [
{ "type": "minecraft:rarity_filter", "chance": 4 },
{ "type": "minecraft:in_square" },
{ "type": "minecraft:heightmap", "heightmap": "WORLD_SURFACE_WG" },
{ "type": "minecraft:biome" }
]
}
@@ -37,6 +37,7 @@
"antarchy:nyxite_brick_slab",
"antarchy:nyxite_brick_wall",
"antarchy:myrmite",
"antarchy:bile_vein",
"antarchy:chiten_block",
"antarchy:chiten_spike",
"antarchy:shellstone",
@@ -19,6 +19,7 @@
"antarchy:shellstone_brick_stairs",
"antarchy:shellstone_brick_slab",
"antarchy:shellstone_brick_wall",
"antarchy:chiten_block"
"antarchy:chiten_block",
"antarchy:bile_vein"
]
}
@@ -19,7 +19,8 @@ import com.craisinlord.antarchy.content.worldgen.ants.BrownAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.RainbowAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.RedAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.TermiteNestFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBilePoolFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBileCystFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBileVeinFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynCreepvineFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynWallAmberMossFeature;
import com.craisinlord.antarchy.content.worldgen.thoraxis.NyxiteSpikeConfiguration;
@@ -612,13 +613,17 @@ public final class AntarchyFabricContent {
public static final DeferredBlock<UmbralMossCarpetBlock> AMBER_MOSS_CARPET = BLOCKS.register("amber_moss_carpet",
() -> new UmbralMossCarpetBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.MOSS_CARPET).noOcclusion()));
public static final DeferredBlock<GlowLichenBlock> AMBER_LICHEN = BLOCKS.register("amber_lichen",
() -> new GlowLichenBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.GLOW_LICHEN).lightLevel(state -> 0)));
() -> new GlowLichenBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.GLOW_LICHEN).lightLevel(state -> 1)));
public static final DeferredBlock<Block> BILE_VEIN = BLOCKS.register("bile_vein",
() -> new Block(BlockBehaviour.Properties.ofFullCopy(Blocks.NETHERRACK)));
public static final DeferredBlock<VineBlock> CREEPVINE = BLOCKS.register("creepvine",
() -> new VineBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.VINE)));
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> DREAM_FIRE_FLAME = PARTICLE_TYPES.register("dream_fire_flame",
() -> simpleParticleType());
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> STINKY_GAS = PARTICLE_TYPES.register("stinky_gas",
() -> simpleParticleType());
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> STINKY_FLY = PARTICLE_TYPES.register("stinky_fly",
() -> simpleParticleType());
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> HYPNOTIC_GAS = PARTICLE_TYPES.register("hypnotic_gas",
() -> simpleParticleType());
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> HYPNOTIC_GAS_CLOUD = PARTICLE_TYPES.register("hypnotic_gas_cloud",
@@ -1060,8 +1065,10 @@ public final class AntarchyFabricContent {
() -> new NyxiteSpikeFeature(NyxiteSpikeConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, ChitenSpikeFeature> CAVARYN_CHITEN_SPIKES = FEATURES.register("cavaryn_chiten_spikes",
() -> new ChitenSpikeFeature(ChitenSpikeConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynBilePoolFeature> CAVARYN_BILE_POOLS = FEATURES.register("cavaryn_bile_pools",
() -> new CavarynBilePoolFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynBileVeinFeature> CAVARYN_BILE_VEINS = FEATURES.register("cavaryn_bile_veins",
() -> new CavarynBileVeinFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynBileCystFeature> CAVARYN_BILE_CYSTS = FEATURES.register("cavaryn_bile_cysts",
() -> new CavarynBileCystFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynCreepvineFeature> CAVARYN_CREEPVINE = FEATURES.register("cavaryn_creepvine",
() -> new CavarynCreepvineFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynWallAmberMossFeature> CAVARYN_WALL_AMBER_MOSS = FEATURES.register("cavaryn_wall_amber_moss",
@@ -1226,6 +1233,7 @@ public final class AntarchyFabricContent {
public static final DeferredItem<net.minecraft.world.item.BlockItem> AMBER_MOSS_BLOCK_ITEM = ITEMS.registerSimpleBlockItem(AMBER_MOSS_BLOCK);
public static final DeferredItem<net.minecraft.world.item.BlockItem> AMBER_MOSS_CARPET_ITEM = ITEMS.registerSimpleBlockItem(AMBER_MOSS_CARPET);
public static final DeferredItem<net.minecraft.world.item.BlockItem> AMBER_LICHEN_ITEM = ITEMS.registerSimpleBlockItem(AMBER_LICHEN);
public static final DeferredItem<net.minecraft.world.item.BlockItem> BILE_VEIN_ITEM = ITEMS.registerSimpleBlockItem(BILE_VEIN);
public static final DeferredItem<net.minecraft.world.item.BlockItem> CREEPVINE_ITEM = ITEMS.registerSimpleBlockItem(CREEPVINE);
public static final DeferredItem<StandingAndWallBlockItem> DREAM_TORCH_ITEM = ITEMS.register("dream_torch",
() -> new StandingAndWallBlockItem(DREAM_TORCH.get(), DREAM_WALL_TORCH.get(), new Item.Properties(), Direction.UP));
@@ -1994,6 +2002,7 @@ public final class AntarchyFabricContent {
"chiseled_titanium", "uranium_bulb", "titanium_bulb",
"uranium_door", "titanium_door", "uranium_trapdoor", "titanium_trapdoor",
"uranium_bars", "titanium_bars" -> 8;
case "bile_vein" -> 9;
case "infested_rooted_dirt", "infested_coarse_dirt", "triffid_goo_block",
"cloud_block", "creeping_horror_egg", "lurking_terror_egg" -> 9;
case "dream_torch", "dream_lantern", "dream_campfire", "dream_fire", "dream_fire_ceiling" -> 10;
@@ -2493,6 +2502,7 @@ public final class AntarchyFabricContent {
() -> WASP_NEST_BLOCK_ENTITY.get(),
() -> HUSHWEED_BLOCK_ENTITY.get(),
() -> STINKY_GAS.get(),
() -> STINKY_FLY.get(),
() -> attributeHolder(DOUBLE_DAMAGE_CHANCE),
() -> attributeHolder(BLOODGLASS_MAX_HEARTS),
() -> mobEffectHolder(BLOODGLASS_WARD)
@@ -181,6 +181,7 @@ public final class AntarchyFabricClientBootstrap {
ParticleFactoryRegistry registry = ParticleFactoryRegistry.getInstance();
registry.register(AntarchyFabricContent.DREAM_FIRE_FLAME.get(), DreamFlameParticle.Provider::new);
registry.register(AntarchyFabricContent.STINKY_GAS.get(), HypnoticGasParticle.Provider::new);
registry.register(AntarchyFabricContent.STINKY_FLY.get(), FireflyParticle.Provider::new);
registry.register(AntarchyFabricContent.HYPNOTIC_GAS.get(), HypnoticGasParticle.Provider::new);
registry.register(AntarchyFabricContent.HYPNOTIC_GAS_DOWN.get(), sprites -> new HypnoticGasParticle.Provider(sprites, true));
registry.register(AntarchyFabricContent.HYPNOTIC_GAS_CLOUD.get(), new HypnoticGasCloudParticle.Provider());
@@ -209,6 +210,7 @@ public final class AntarchyFabricClientBootstrap {
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricContent.UMBRAL_MOSS_CARPET.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricContent.AMBER_MOSS_CARPET.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricContent.AMBER_LICHEN.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricContent.BILE_VEIN.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricContent.CREEPVINE.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricContent.NYXITE_SPIKE.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricContent.CHITEN_SPIKE.get(), RenderType.cutout());
@@ -77,7 +77,7 @@ public abstract class AntimetalScaffoldingMixin {
BlockState below = level.getBlockState(cursor);
int distance = 7;
if (below.is((ScaffoldingBlock) (Object) this)) {
distance = below.getValue(ScaffoldingBlock.DISTANCE);
distance = below.getValue(ScaffoldingBlock.DISTANCE) + 1;
} else if (below.isFaceSturdy(level, cursor, Direction.UP)) {
return 0;
}
@@ -1,6 +1,7 @@
package com.craisinlord.antarchy.fabric.mixin.client;
import com.craisinlord.antarchy.content.entity.ToreterrorEntity;
import com.craisinlord.antarchy.content.item.BigBerthaItem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.minecraft.client.Minecraft;
@@ -17,6 +18,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GameRenderer.class)
public abstract class ToreterrorCameraShakeMixin {
private static final double MAX_SHAKE_RANGE = 48.0D;
private static final int TORETERROR_SHAKE_TICKS = 25;
@Shadow @Final private Minecraft minecraft;
@@ -37,6 +39,10 @@ public abstract class ToreterrorCameraShakeMixin {
shakeStrength += (float) ((1.0D - distance / MAX_SHAKE_RANGE) * 2.0F);
}
if (BigBerthaItem.clientShakeTicks > 0) {
shakeStrength += (float) BigBerthaItem.clientShakeTicks / TORETERROR_SHAKE_TICKS * 2.0F;
}
if (shakeStrength <= 0.0F) return;
float time = (float) (minecraft.player.tickCount + partialTick);
@@ -250,6 +250,7 @@ public class AntarchyNeoforge {
() -> AntarchyNeoforgeBlocks.WASP_NEST_BLOCK_ENTITY.get(),
() -> AntarchyNeoforgeBlocks.HUSHWEED_BLOCK_ENTITY.get(),
() -> AntarchyNeoforgeMisc.STINKY_GAS.get(),
() -> AntarchyNeoforgeMisc.STINKY_FLY.get(),
() -> AntarchyNeoforgeMisc.DOUBLE_DAMAGE_CHANCE,
() -> AntarchyNeoforgeMisc.BLOODGLASS_MAX_HEARTS,
() -> AntarchyNeoforgeMisc.BLOODGLASS_WARD
@@ -200,6 +200,7 @@ public final class AntarchyNeoForgeClient {
public static void registerParticleProviders(RegisterParticleProvidersEvent event) {
event.registerSpriteSet(AntarchyNeoforgeMisc.DREAM_FIRE_FLAME.get(), DreamFlameParticle.Provider::new);
event.registerSpriteSet(AntarchyNeoforgeMisc.STINKY_GAS.get(), HypnoticGasParticle.Provider::new);
event.registerSpriteSet(AntarchyNeoforgeMisc.STINKY_FLY.get(), FireflyParticle.Provider::new);
event.registerSpriteSet(AntarchyNeoforgeMisc.HYPNOTIC_GAS.get(), HypnoticGasParticle.Provider::new);
event.registerSpriteSet(AntarchyNeoforgeMisc.HYPNOTIC_GAS_DOWN.get(), sprites -> new HypnoticGasParticle.Provider(sprites, true));
event.registerSpecial(AntarchyNeoforgeMisc.HYPNOTIC_GAS_CLOUD.get(), new HypnoticGasCloudParticle.Provider());
@@ -397,6 +398,7 @@ public final class AntarchyNeoForgeClient {
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.UMBRAL_MOSS_CARPET.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.AMBER_MOSS_CARPET.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.AMBER_LICHEN.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.BILE_VEIN.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.CREEPVINE.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.NYXITE_SPIKE.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.CHITEN_SPIKE.get(), RenderType.cutout());
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.neoforge.client;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.entity.ToreterrorEntity;
import com.craisinlord.antarchy.content.item.BigBerthaItem;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
@@ -13,6 +14,7 @@ import net.neoforged.neoforge.client.event.ViewportEvent;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class ToreterrorCameraShakeHandler {
private static final double MAX_SHAKE_RANGE = 48.0D;
private static final int TORETERROR_SHAKE_TICKS = 25;
private ToreterrorCameraShakeHandler() {
}
@@ -35,6 +37,10 @@ public final class ToreterrorCameraShakeHandler {
shakeStrength += (float) ((1.0D - distance / MAX_SHAKE_RANGE) * 2.0D);
}
if (BigBerthaItem.clientShakeTicks > 0) {
shakeStrength += (float) BigBerthaItem.clientShakeTicks / TORETERROR_SHAKE_TICKS * 2.0F;
}
if (shakeStrength <= 0.0F) return;
float time = (float) (mc.player.tickCount + event.getPartialTick());
@@ -194,7 +194,9 @@ public final class AntarchyNeoforgeBlocks {
public static final DeferredBlock<UmbralMossCarpetBlock> AMBER_MOSS_CARPET = BLOCKS.register("amber_moss_carpet",
() -> new UmbralMossCarpetBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.MOSS_CARPET).noOcclusion()));
public static final DeferredBlock<GlowLichenBlock> AMBER_LICHEN = BLOCKS.register("amber_lichen",
() -> new GlowLichenBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.GLOW_LICHEN).lightLevel(state -> 0)));
() -> new GlowLichenBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.GLOW_LICHEN).lightLevel(state -> 1)));
public static final DeferredBlock<Block> BILE_VEIN = BLOCKS.register("bile_vein",
() -> new Block(BlockBehaviour.Properties.ofFullCopy(Blocks.NETHERRACK)));
public static final DeferredBlock<VineBlock> CREEPVINE = BLOCKS.register("creepvine",
() -> new VineBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.VINE)));
public static final DeferredBlock<DreamTorchBlock> DREAM_TORCH = BLOCKS.register("dream_torch",
@@ -245,6 +245,7 @@ public class AntarchyNeoforgeCreativeModeTabs {
event.accept(AntarchyNeoforgeItems.MEDIUM_BLOOD_CRYSTAL_BUD_ITEM.get());
event.accept(AntarchyNeoforgeItems.LARGE_BLOOD_CRYSTAL_BUD_ITEM.get());
event.accept(AntarchyNeoforgeItems.MYRMITE_ITEM.get());
event.accept(AntarchyNeoforgeItems.BILE_VEIN_ITEM.get());
event.accept(AntarchyNeoforgeItems.CHITEN_BLOCK_ITEM.get());
event.accept(AntarchyNeoforgeItems.CHITEN_SPIKE_ITEM.get());
event.accept(AntarchyNeoforgeItems.AMBER_MOSS_BLOCK_ITEM.get());
@@ -388,7 +389,7 @@ public class AntarchyNeoforgeCreativeModeTabs {
case "duplicator_sapling", "ouranwood_acorn" -> 10;
// 11 - Plants and flowers
case "orange_milkweed", "pink_milkweed", "torchflower_bush", "hushweed", "amber_lichen", "creepvine",
case "orange_milkweed", "pink_milkweed", "torchflower_bush", "hushweed", "amber_lichen", "bile_vein", "creepvine",
"triffid_goo_block", "wasp_nest",
"red_ant_nest", "brown_ant_nest", "rainbow_ant_nest", "termite_nest" -> 11;
@@ -272,6 +272,7 @@ public final class AntarchyNeoforgeItems {
public static final DeferredItem<net.minecraft.world.item.BlockItem> AMBER_MOSS_BLOCK_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.AMBER_MOSS_BLOCK);
public static final DeferredItem<net.minecraft.world.item.BlockItem> AMBER_MOSS_CARPET_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.AMBER_MOSS_CARPET);
public static final DeferredItem<net.minecraft.world.item.BlockItem> AMBER_LICHEN_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.AMBER_LICHEN);
public static final DeferredItem<net.minecraft.world.item.BlockItem> BILE_VEIN_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.BILE_VEIN);
public static final DeferredItem<net.minecraft.world.item.BlockItem> CREEPVINE_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.CREEPVINE);
public static final DeferredItem<StandingAndWallBlockItem> DREAM_TORCH_ITEM = ITEMS.register("dream_torch",
() -> new StandingAndWallBlockItem(AntarchyNeoforgeBlocks.DREAM_TORCH.get(), AntarchyNeoforgeBlocks.DREAM_WALL_TORCH.get(), new Item.Properties(), net.minecraft.core.Direction.UP));
@@ -13,7 +13,8 @@ import com.craisinlord.antarchy.content.worldgen.ants.BrownAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.RainbowAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.RedAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.TermiteNestFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBilePoolFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBileCystFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBileVeinFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynCreepvineFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynEggPatchFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynWallAmberMossFeature;
@@ -164,6 +165,8 @@ public final class AntarchyNeoforgeMisc {
() -> new SimpleParticleType(true));
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> STINKY_GAS = PARTICLE_TYPES.register("stinky_gas",
() -> new SimpleParticleType(true));
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> STINKY_FLY = PARTICLE_TYPES.register("stinky_fly",
() -> new SimpleParticleType(true));
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> HYPNOTIC_GAS = PARTICLE_TYPES.register("hypnotic_gas",
() -> new SimpleParticleType(true));
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> HYPNOTIC_GAS_CLOUD = PARTICLE_TYPES.register("hypnotic_gas_cloud",
@@ -250,8 +253,10 @@ public final class AntarchyNeoforgeMisc {
() -> new NyxiteSpikeFeature(NyxiteSpikeConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, ChitenSpikeFeature> CAVARYN_CHITEN_SPIKES = FEATURES.register("cavaryn_chiten_spikes",
() -> new ChitenSpikeFeature(ChitenSpikeConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynBilePoolFeature> CAVARYN_BILE_POOLS = FEATURES.register("cavaryn_bile_pools",
() -> new CavarynBilePoolFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynBileVeinFeature> CAVARYN_BILE_VEINS = FEATURES.register("cavaryn_bile_veins",
() -> new CavarynBileVeinFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynBileCystFeature> CAVARYN_BILE_CYSTS = FEATURES.register("cavaryn_bile_cysts",
() -> new CavarynBileCystFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynCreepvineFeature> CAVARYN_CREEPVINE = FEATURES.register("cavaryn_creepvine",
() -> new CavarynCreepvineFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder<Feature<?>, CavarynWallAmberMossFeature> CAVARYN_WALL_AMBER_MOSS = FEATURES.register("cavaryn_wall_amber_moss",