ruined arena

new ant sacrifice portals
dorrie overhaul
new foliage in overworld biomes
This commit is contained in:
craisinlord committed 2026-07-08 01:35:41 -05:00
1 parent ae76303716
commit 4e67661448
92 files changed
+5802 -2512

No files matched your search

@@ -447,6 +447,10 @@ public final class AntarchySettings {
private static double primordialArmorKnockbackPerPiece = 0.5D;
private static int fallenKingCrownArmorValue = 2;
private static double fallenKingCrownArmorToughness = 0.0D;
private static boolean permanentPortalsEnabled = true;
private static boolean elythiaPortalEnabled = true;
private static boolean thoraxisPortalEnabled = true;
private static boolean cavarynPortalEnabled = true;
private static boolean elythiaFireflyParticlesEnabled = true;
private static int bloodCrystalArmorShieldRechargeTicks = 600;
private static int bloodCrystalAppleShieldCount = 2;
@@ -957,6 +961,22 @@ public final class AntarchySettings {
rainbowAntsLeadToInfinityDimensions = value;
}
public static void setPermanentPortalsEnabled(boolean value) {
permanentPortalsEnabled = value;
}
public static void setElythiaPortalEnabled(boolean value) {
elythiaPortalEnabled = value;
}
public static void setThoraxisPortalEnabled(boolean value) {
thoraxisPortalEnabled = value;
}
public static void setCavarynPortalEnabled(boolean value) {
cavarynPortalEnabled = value;
}
public static void setBrownAntRequiresReagent(boolean value) {
brownAntRequiresReagent = value;
}
@@ -2434,6 +2454,11 @@ public final class AntarchySettings {
public static double fallenKingCrownArmorToughness() { return fallenKingCrownArmorToughness; }
public static void setFallenKingCrownArmorToughness(double value) { fallenKingCrownArmorToughness = value; }
public static boolean permanentPortalsEnabled() { return permanentPortalsEnabled; }
public static boolean elythiaPortalEnabled() { return elythiaPortalEnabled; }
public static boolean thoraxisPortalEnabled() { return thoraxisPortalEnabled; }
public static boolean cavarynPortalEnabled() { return cavarynPortalEnabled; }
public static boolean elythiaFireflyParticlesEnabled() { return elythiaFireflyParticlesEnabled; }
public static void setElythiaFireflyParticlesEnabled(boolean value) { elythiaFireflyParticlesEnabled = value; }
@@ -31,6 +31,9 @@ public final class AntarchyTags {
public static final TagKey<Block> TERMITE_FOODS = TagKey.create(Registries.BLOCK, id("termite_foods"));
public static final TagKey<Block> UMBRAL_MOSS_REPLACEABLE = TagKey.create(Registries.BLOCK, id("umbral_moss_replaceable"));
public static final TagKey<Block> HERCULES_BEETLE_CHARGE_IMMUNE_BLOCKS = TagKey.create(Registries.BLOCK, id("hercules_beetle_charge_immune_blocks"));
public static final TagKey<Block> ELYTHIA_PORTAL_FRAMES = TagKey.create(Registries.BLOCK, id("elythia_portal_frames"));
public static final TagKey<Block> THORAXIS_PORTAL_FRAMES = TagKey.create(Registries.BLOCK, id("thoraxis_portal_frames"));
public static final TagKey<Block> CAVARYN_PORTAL_FRAMES = TagKey.create(Registries.BLOCK, id("cavaryn_portal_frames"));
private Blocks() {
}
@@ -0,0 +1,154 @@
package com.craisinlord.antarchy.content.block;
import com.craisinlord.antarchy.content.portal.PermanentPortalManager;
import com.craisinlord.antarchy.content.portal.PermanentPortalType;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
public final class AntDimensionPortalBlock extends Block {
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.HORIZONTAL_AXIS;
private static final VoxelShape X_SHAPE = Block.box(0.0D, 0.0D, 6.0D, 16.0D, 16.0D, 10.0D);
private static final VoxelShape Z_SHAPE = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 16.0D, 16.0D);
private final PermanentPortalType type;
private final MapCodec<AntDimensionPortalBlock> codec;
public AntDimensionPortalBlock(PermanentPortalType type, BlockBehaviour.Properties properties) {
super(properties);
this.type = type;
this.codec = Block.simpleCodec(ignored -> this);
this.registerDefaultState(this.stateDefinition.any().setValue(AXIS, Direction.Axis.X));
}
@Override
public MapCodec<AntDimensionPortalBlock> codec() {
return this.codec;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(AXIS);
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return state.getValue(AXIS) == Direction.Axis.X ? X_SHAPE : Z_SHAPE;
}
@Override
protected VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return Shapes.empty();
}
@Override
protected VoxelShape getVisualShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return Shapes.empty();
}
@Override
protected VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) {
return Shapes.empty();
}
@Override
protected RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
protected boolean skipRendering(BlockState state, BlockState adjacentBlockState, Direction side) {
return adjacentBlockState.is(this) || super.skipRendering(state, adjacentBlockState, side);
}
@Override
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
if (!level.isClientSide()) {
PermanentPortalManager.handleEntityInsidePortal(entity, this.type);
}
}
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
super.onPlace(state, level, pos, oldState, movedByPiston);
if (!level.isClientSide() && !state.is(oldState.getBlock())) {
level.scheduleTick(pos, this, 1);
}
}
@Override
protected BlockState updateShape(
BlockState state,
Direction direction,
BlockState neighborState,
LevelAccessor level,
BlockPos pos,
BlockPos neighborPos
) {
if (level instanceof ServerLevel serverLevel) {
serverLevel.scheduleTick(pos, this, 1);
}
return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
}
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!PermanentPortalManager.isPortalStillValid(level, pos, this.type, state.getValue(AXIS))) {
level.setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL);
}
}
@Override
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
if (random.nextInt(100) == 0) {
level.playLocalSound(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, SoundEvents.PORTAL_AMBIENT, SoundSource.BLOCKS, 0.35F, 0.9F + random.nextFloat() * 0.2F, false);
}
ParticleOptions particle = switch (this.type) {
case ELYTHIA -> ParticleTypes.SPORE_BLOSSOM_AIR;
case THORAXIS -> ParticleTypes.PORTAL;
case CAVARYN -> ParticleTypes.MYCELIUM;
};
for (int i = 0; i < 4; i++) {
double x = pos.getX() + random.nextDouble();
double y = pos.getY() + random.nextDouble();
double z = pos.getZ() + random.nextDouble();
if (state.getValue(AXIS) == Direction.Axis.X) {
z = pos.getZ() + 0.5D + (random.nextDouble() - 0.5D) * 0.25D;
} else {
x = pos.getX() + 0.5D + (random.nextDouble() - 0.5D) * 0.25D;
}
level.addParticle(
particle,
x,
y,
z,
(random.nextDouble() - 0.5D) * 0.2D,
(random.nextDouble() - 0.5D) * 0.2D,
(random.nextDouble() - 0.5D) * 0.2D
);
}
}
}
@@ -8,6 +8,11 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
@@ -22,6 +27,7 @@ import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
@@ -251,4 +257,35 @@ public class BigBushBlock extends BushBlock implements BonemealableBlock {
}
placeStage(level, target.origin(), target.state());
}
/** Pops a bonus item when bone meal is used on a fully-grown (age 2) bush; shared with {@link BigBushPartBlock}. */
public static boolean grantBonemealBonus(Level level, BlockPos originPos, BlockState originState, Player player, ItemStack stack) {
if (!(originState.getBlock() instanceof BigBushBlock bigBush) || originState.getValue(AGE) != 2) {
return false;
}
if (!level.isClientSide) {
bigBush.popResource(level, originPos, new ItemStack(bigBush, 1));
if (!player.getAbilities().instabuild) {
stack.shrink(1);
}
level.levelEvent(1505, originPos, 15);
}
return true;
}
@Override
protected ItemInteractionResult useItemOn(
ItemStack stack,
BlockState state,
Level level,
BlockPos pos,
Player player,
InteractionHand hand,
BlockHitResult hitResult
) {
if (stack.is(Items.BONE_MEAL) && grantBonemealBonus(level, pos, state, player, stack)) {
return ItemInteractionResult.sidedSuccess(level.isClientSide);
}
return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
}
}
@@ -5,8 +5,11 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
@@ -16,6 +19,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
@@ -119,6 +123,25 @@ public class BigBushPartBlock extends Block {
}
}
@Override
protected ItemInteractionResult useItemOn(
ItemStack stack,
BlockState state,
Level level,
BlockPos pos,
Player player,
InteractionHand hand,
BlockHitResult hitResult
) {
if (stack.is(Items.BONE_MEAL)) {
BlockPos origin = findOrigin(level, pos);
if (origin != null && BigBushBlock.grantBonemealBonus(level, origin, level.getBlockState(origin), player, stack)) {
return ItemInteractionResult.sidedSuccess(level.isClientSide);
}
}
return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
}
@Override
public ItemStack getCloneItemStack(LevelReader level, BlockPos pos, BlockState state) {
BlockPos origin = findOrigin(level, pos);
@@ -0,0 +1,41 @@
package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.WeepingVinesBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
@SuppressWarnings({"rawtypes", "unchecked"})
public class OuranwoodVineBlock extends WeepingVinesBlock {
public static final MapCodec<OuranwoodVineBlock> CODEC = simpleCodec(OuranwoodVineBlock::new);
private static Block bodyBlock;
public OuranwoodVineBlock(BlockBehaviour.Properties properties) {
super(properties);
}
@Override
public MapCodec<WeepingVinesBlock> codec() {
return (MapCodec) CODEC;
}
@Override
protected Block getBodyBlock() {
return bodyBlock;
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return Shapes.block();
}
public static void bindBodyBlock(Block block) {
bodyBlock = block;
}
}
@@ -0,0 +1,42 @@
package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.GrowingPlantHeadBlock;
import net.minecraft.world.level.block.WeepingVinesBlock;
import net.minecraft.world.level.block.WeepingVinesPlantBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
@SuppressWarnings({"rawtypes", "unchecked"})
public class OuranwoodVinePlantBlock extends WeepingVinesPlantBlock {
public static final MapCodec<OuranwoodVinePlantBlock> CODEC = simpleCodec(OuranwoodVinePlantBlock::new);
private static GrowingPlantHeadBlock headBlock;
public OuranwoodVinePlantBlock(BlockBehaviour.Properties properties) {
super(properties);
}
@Override
public MapCodec<WeepingVinesPlantBlock> codec() {
return (MapCodec) CODEC;
}
@Override
protected GrowingPlantHeadBlock getHeadBlock() {
return headBlock;
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return Shapes.block();
}
public static void bindHeadBlock(WeepingVinesBlock block) {
headBlock = block;
}
}
@@ -52,7 +52,10 @@ public class AlphaMantisEntity extends MantisEntity {
}
public static boolean checkAlphaMantisSpawnRules(EntityType<AlphaMantisEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG
|| spawnReason == MobSpawnType.SPAWNER
|| spawnReason == MobSpawnType.TRIAL_SPAWNER
|| spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -73,14 +76,12 @@ public class AlphaMantisEntity extends MantisEntity {
return false;
}
// Only one alpha at a time in the area
if (!level.getLevel().getEntitiesOfClass(AlphaMantisEntity.class, new AABB(pos).inflate(128.0D), Entity::isAlive).isEmpty()) {
return false;
}
boolean ignoreLightLevel = AntarchySettings.mantisIgnoreLightLevel();
// Daytime overworld spawns can't pass the vanilla darkness check, so no light gate here
if (level.getLevel().isDay() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_OVERWORLD_SPAWN_BIOMES)) {
return level.canSeeSky(pos);
}
@@ -181,7 +182,6 @@ public class AlphaMantisEntity extends MantisEntity {
@Override
public void setTarget(@Nullable LivingEntity target) {
super.setTarget(target);
// A boss that despawns mid-fight is no boss — stay loaded once engaged
if (target != null) {
this.setPersistenceRequired();
}
@@ -23,6 +23,7 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.control.MoveControl;
import net.minecraft.world.entity.ai.control.SmoothSwimmingLookControl;
import net.minecraft.world.entity.ai.control.SmoothSwimmingMoveControl;
import net.minecraft.world.entity.ai.goal.BreathAirGoal;
@@ -30,8 +31,10 @@ import net.minecraft.world.entity.ai.goal.FloatGoal;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
import net.minecraft.world.entity.ai.goal.RandomSwimmingGoal;
import net.minecraft.world.entity.ai.goal.TryFindWaterGoal;
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
import net.minecraft.world.entity.ai.navigation.PathNavigation;
import net.minecraft.world.entity.ai.navigation.WaterBoundPathNavigation;
import net.minecraft.world.entity.animal.Animal;
@@ -39,6 +42,7 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.pathfinder.PathType;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import software.bernie.geckolib.animatable.GeoEntity;
@@ -59,18 +63,29 @@ public class DorrieEntity extends Animal implements GeoEntity {
SynchedEntityData.defineId(DorrieEntity.class, EntityDataSerializers.BOOLEAN);
private static final EntityDataAccessor<Integer> JUMP_CHARGE =
SynchedEntityData.defineId(DorrieEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> QUIRK_TICKS =
SynchedEntityData.defineId(DorrieEntity.class, EntityDataSerializers.INT);
private static final int MAX_CHARGE_TICKS = 40;
private static final float WATER_RIDE_SPEED = 1.26F;
private static final float LAND_BEACH_SPEED = 0.04F;
private static final int QUIRK_DURATION_TICKS = 65;
private static final int MIN_QUIRK_COOLDOWN_TICKS = 180;
private static final int MAX_QUIRK_COOLDOWN_TICKS = 320;
private static final double MOVING_ANIM_THRESHOLD_SQ = 0.0025D;
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final RawAnimation IDLE_GROUND_ANIM = RawAnimation.begin().thenLoop("idle_ground");
private static final RawAnimation IDLE_WATER_ANIM = RawAnimation.begin().thenLoop("idle_water");
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
private static final RawAnimation SWIM_ANIM = RawAnimation.begin().thenLoop("swim");
private static final RawAnimation JUMP_START_ANIM = RawAnimation.begin().thenPlay("jump_1");
private static final RawAnimation JUMP_LOOP_ANIM = RawAnimation.begin().thenLoop("jump_2");
private static final RawAnimation JUMP_LAND_ANIM = RawAnimation.begin().thenPlay("jump_3");
private static final RawAnimation JUMP_START_ANIM = RawAnimation.begin().thenPlay("jump_start");
private static final RawAnimation JUMP_LOOP_ANIM = RawAnimation.begin().thenLoop("jump_idle");
private static final RawAnimation JUMP_LAND_ANIM = RawAnimation.begin().thenPlay("jump_end");
private static final RawAnimation QUIRK_ANIM = RawAnimation.begin().thenPlay("quirk");
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
private final MoveControl landMoveControl;
private final MoveControl waterMoveControl;
private static final int RIDES_TO_TAME = 4;
private static final int BUCK_DELAY_TICKS = 60;
@@ -83,11 +98,17 @@ public class DorrieEntity extends Animal implements GeoEntity {
private int rideAttempts = 0;
private int buckTimer = 0;
private int swimForwardTicks = 0;
private int quirkCooldownTicks = MIN_QUIRK_COOLDOWN_TICKS;
private boolean usingLandNavigation = true;
public DorrieEntity(EntityType<? extends DorrieEntity> entityType, Level level) {
super(entityType, level);
this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 1.0F, true);
this.landMoveControl = new MoveControl(this);
this.waterMoveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 1.0F, true);
this.moveControl = this.landMoveControl;
this.lookControl = new SmoothSwimmingLookControl(this, 10);
this.setPathfindingMalus(PathType.WATER, 0.0F);
this.setPathfindingMalus(PathType.WATER_BORDER, 0.0F);
}
@Override
@@ -96,11 +117,12 @@ public class DorrieEntity extends Animal implements GeoEntity {
builder.define(HAS_SADDLE, false);
builder.define(TAMED, false);
builder.define(JUMP_CHARGE, 0);
builder.define(QUIRK_TICKS, 0);
}
@Override
protected PathNavigation createNavigation(Level level) {
return new WaterBoundPathNavigation(this, level);
return this.createLandNavigation(level);
}
@Override
@@ -110,8 +132,9 @@ public class DorrieEntity extends Animal implements GeoEntity {
this.goalSelector.addGoal(2, new TryFindWaterGoal(this));
this.goalSelector.addGoal(3, new HuntCheepGoal(this));
this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0D, 10));
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F));
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.45D, 60));
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
}
public static AttributeSupplier.Builder createAttributes() {
@@ -146,6 +169,14 @@ public class DorrieEntity extends Animal implements GeoEntity {
this.entityData.set(JUMP_CHARGE, charge);
}
public int getQuirkTicks() {
return this.entityData.get(QUIRK_TICKS);
}
private void setQuirkTicks(int ticks) {
this.entityData.set(QUIRK_TICKS, ticks);
}
@Override
public void addAdditionalSaveData(CompoundTag tag) {
super.addAdditionalSaveData(tag);
@@ -173,7 +204,18 @@ public class DorrieEntity extends Animal implements GeoEntity {
return InteractionResult.sidedSuccess(this.level().isClientSide);
}
if (this.hasSaddle() && stack.isEmpty() && !player.isPassengerOfSameVehicle(this)) {
if (this.hasSaddle() && !player.isPassengerOfSameVehicle(this)) {
if (!stack.isEmpty()) {
return super.mobInteract(player, hand);
}
if (!player.isShiftKeyDown()) {
if (!this.level().isClientSide) {
player.startRiding(this);
}
return InteractionResult.sidedSuccess(this.level().isClientSide);
}
if (!this.level().isClientSide) {
this.setSaddle(false);
this.spawnAtLocation(new ItemStack(Items.SADDLE));
@@ -193,13 +235,6 @@ public class DorrieEntity extends Animal implements GeoEntity {
return InteractionResult.sidedSuccess(this.level().isClientSide);
}
if (this.hasSaddle() && !player.isPassengerOfSameVehicle(this)) {
if (!this.level().isClientSide) {
player.startRiding(this);
}
return InteractionResult.sidedSuccess(this.level().isClientSide);
}
return super.mobInteract(player, hand);
}
@@ -234,6 +269,7 @@ public class DorrieEntity extends Animal implements GeoEntity {
@Override
public void tick() {
super.tick();
this.updateNavigationMode();
if (this.getControllingPassenger() instanceof Player player) {
this.setYRot(player.getYRot());
@@ -275,6 +311,10 @@ public class DorrieEntity extends Animal implements GeoEntity {
setJumpCharge((int) ((chargeTicks / (float) MAX_CHARGE_TICKS) * 100));
}
if (!this.level().isClientSide) {
this.tickQuirkAnimation();
}
if (this.isInWater() && !isLeaping) {
Vec3 mov = this.getDeltaMovement();
double push = this.isUnderWater() ? 0.07D : 0.015D;
@@ -384,13 +424,29 @@ public class DorrieEntity extends Animal implements GeoEntity {
}
private PlayState mainAnimController(AnimationState<DorrieEntity> state) {
state.getController().setAnimationSpeed(1.0D);
if (landAnimTicks > 0) {
return state.setAndContinue(JUMP_LAND_ANIM);
}
if (isLeaping) {
return state.setAndContinue(wasInAir ? JUMP_LOOP_ANIM : JUMP_START_ANIM);
}
return state.setAndContinue(state.isMoving() ? SWIM_ANIM : IDLE_ANIM);
if (this.getQuirkTicks() > 0) {
return state.setAndContinue(QUIRK_ANIM);
}
boolean moving = this.isMovingForAnimation(state);
if (this.isInWater() || this.isInLava()) {
return state.setAndContinue(moving ? SWIM_ANIM : IDLE_WATER_ANIM);
}
if (moving) {
state.getController().setAnimationSpeed(0.75D);
return state.setAndContinue(WALK_ANIM);
}
return state.setAndContinue(IDLE_GROUND_ANIM);
}
@Override
@@ -407,6 +463,78 @@ public class DorrieEntity extends Animal implements GeoEntity {
return !stack.isEmpty() && stack.is(BuiltInRegistries.ITEM.getOptional(CHEEP_ITEM_ID).orElse(Items.AIR));
}
private PathNavigation createLandNavigation(Level level) {
GroundPathNavigation navigation = new GroundPathNavigation(this, level);
navigation.setCanFloat(true);
navigation.setCanOpenDoors(false);
navigation.setCanPassDoors(true);
return navigation;
}
private PathNavigation createWaterNavigation(Level level) {
return new WaterBoundPathNavigation(this, level);
}
private void updateNavigationMode() {
boolean shouldUseLandNavigation = !this.isInWater() && !this.isUnderWater() && !this.isInLava();
if (this.navigation == null || this.usingLandNavigation != shouldUseLandNavigation) {
this.usingLandNavigation = shouldUseLandNavigation;
if (this.navigation != null) {
this.navigation.stop();
}
this.navigation = shouldUseLandNavigation
? this.createLandNavigation(this.level())
: this.createWaterNavigation(this.level());
this.moveControl = shouldUseLandNavigation ? this.landMoveControl : this.waterMoveControl;
}
}
private void tickQuirkAnimation() {
if (this.getQuirkTicks() > 0) {
if (this.canUseQuirkAnimation()) {
this.setQuirkTicks(this.getQuirkTicks() - 1);
} else {
this.setQuirkTicks(0);
this.quirkCooldownTicks = this.nextQuirkCooldown();
}
return;
}
if (this.quirkCooldownTicks > 0) {
this.quirkCooldownTicks--;
return;
}
if (this.canUseQuirkAnimation()) {
this.setQuirkTicks(QUIRK_DURATION_TICKS);
this.quirkCooldownTicks = this.nextQuirkCooldown();
}
}
private int nextQuirkCooldown() {
return MIN_QUIRK_COOLDOWN_TICKS + this.random.nextInt(MAX_QUIRK_COOLDOWN_TICKS - MIN_QUIRK_COOLDOWN_TICKS + 1);
}
private boolean canUseQuirkAnimation() {
return this.isInWater()
&& this.getControllingPassenger() == null
&& !this.isLeaping
&& this.landAnimTicks <= 0
&& !this.isCharging
&& !this.isMovingForAnimation(null);
}
private boolean isMovingForAnimation(@Nullable AnimationState<DorrieEntity> state) {
if (state != null && state.isMoving()) {
return true;
}
if (this.getControllingPassenger() instanceof Player player) {
return Math.abs(player.zza) > 0.05F || Math.abs(player.xxa) > 0.05F;
}
return this.getDeltaMovement().horizontalDistanceSqr() > MOVING_ANIM_THRESHOLD_SQ
|| this.getNavigation().isInProgress();
}
private static class HuntCheepGoal extends Goal {
private static final int COOLDOWN_TICKS = 600;
private static final double HUNT_RANGE = 16.0D;
@@ -90,7 +90,10 @@ public class MantisEntity extends Monster implements GeoEntity {
}
public static boolean canSpawn(EntityType<MantisEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG
|| spawnReason == MobSpawnType.SPAWNER
|| spawnReason == MobSpawnType.TRIAL_SPAWNER
|| spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -0,0 +1,129 @@
package com.craisinlord.antarchy.content.portal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
public final class PermanentPortalManager {
private static final int TELEPORT_DELAY_TICKS = 20;
private static final int ACTIVATION_SEARCH_RADIUS = 2;
private static final Map<UUID, PortalWarmup> WARMUPS = new HashMap<>();
private PermanentPortalManager() {
}
public static void handleSacrifice(LivingEntity entity) {
PermanentPortalType type = PermanentPortalType.fromSacrifice(entity);
if (type == null || !(entity.level() instanceof ServerLevel serverLevel)) {
return;
}
PermanentPortalShape shape = findInactiveShape(serverLevel, entity.getBoundingBox(), type);
if (shape == null) {
return;
}
shape.fill(serverLevel);
Vec3 center = shape.center();
serverLevel.playSound(null, center.x, center.y, center.z, SoundEvents.END_PORTAL_SPAWN, SoundSource.BLOCKS, 0.9F, 0.9F);
spawnActivationParticles(serverLevel, type, center);
}
public static void handleEntityInsidePortal(Entity entity, PermanentPortalType type) {
if (!(entity.level() instanceof ServerLevel serverLevel) || !type.isEnabled() || entity.isPassenger() || entity.isVehicle()) {
return;
}
if (entity.isOnPortalCooldown()) {
WARMUPS.remove(entity.getUUID());
return;
}
long gameTime = serverLevel.getGameTime();
PortalWarmup warmup = WARMUPS.computeIfAbsent(entity.getUUID(), ignored -> new PortalWarmup());
if (warmup.type != type || warmup.lastSeenTick < gameTime - 1) {
warmup.ticks = 0;
}
warmup.type = type;
if (warmup.lastSeenTick != gameTime) {
warmup.ticks++;
warmup.lastSeenTick = gameTime;
}
if (warmup.ticks < TELEPORT_DELAY_TICKS) {
return;
}
WARMUPS.remove(entity.getUUID());
PermanentPortalTeleporter.teleport(entity, type);
if (entity.level() instanceof ServerLevel currentLevel) {
currentLevel.playSound(null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.8F, 1.0F);
}
}
public static boolean isPortalStillValid(ServerLevel level, BlockPos pos, PermanentPortalType type, Direction.Axis axis) {
PermanentPortalShape shape = PermanentPortalShape.findActive(level, pos, type, axis);
return shape != null && shape.contains(pos);
}
@Nullable
private static PermanentPortalShape findInactiveShape(ServerLevel level, AABB bounds, PermanentPortalType type) {
int minX = (int) Math.floor(bounds.minX + 0.001D) - ACTIVATION_SEARCH_RADIUS;
int minY = (int) Math.floor(bounds.minY + 0.001D) - ACTIVATION_SEARCH_RADIUS;
int minZ = (int) Math.floor(bounds.minZ + 0.001D) - ACTIVATION_SEARCH_RADIUS;
int maxX = (int) Math.floor(bounds.maxX - 0.001D) + ACTIVATION_SEARCH_RADIUS;
int maxY = (int) Math.floor(bounds.maxY - 0.001D) + ACTIVATION_SEARCH_RADIUS;
int maxZ = (int) Math.floor(bounds.maxZ - 0.001D) + ACTIVATION_SEARCH_RADIUS;
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
BlockPos candidate = new BlockPos(x, y, z);
PermanentPortalShape xShape = PermanentPortalShape.findInactive(level, candidate, type, Direction.Axis.X);
if (xShape != null && xShape.intersects(bounds)) {
return xShape;
}
PermanentPortalShape zShape = PermanentPortalShape.findInactive(level, candidate, type, Direction.Axis.Z);
if (zShape != null && zShape.intersects(bounds)) {
return zShape;
}
}
}
}
return null;
}
private static void spawnActivationParticles(ServerLevel level, PermanentPortalType type, Vec3 center) {
switch (type) {
case ELYTHIA -> {
level.sendParticles(ParticleTypes.SPORE_BLOSSOM_AIR, center.x, center.y, center.z, 24, 0.8D, 1.2D, 0.8D, 0.02D);
level.sendParticles(ParticleTypes.HAPPY_VILLAGER, center.x, center.y, center.z, 12, 0.6D, 1.0D, 0.6D, 0.02D);
}
case THORAXIS -> {
level.sendParticles(ParticleTypes.PORTAL, center.x, center.y, center.z, 32, 0.8D, 1.2D, 0.8D, 0.15D);
level.sendParticles(ParticleTypes.REVERSE_PORTAL, center.x, center.y, center.z, 10, 0.5D, 0.8D, 0.5D, 0.01D);
}
case CAVARYN -> {
level.sendParticles(ParticleTypes.MYCELIUM, center.x, center.y, center.z, 24, 0.8D, 1.2D, 0.8D, 0.01D);
level.sendParticles(ParticleTypes.FALLING_SPORE_BLOSSOM, center.x, center.y, center.z, 16, 0.6D, 1.0D, 0.6D, 0.01D);
}
}
}
private static final class PortalWarmup {
private PermanentPortalType type;
private long lastSeenTick;
private int ticks;
}
}
@@ -0,0 +1,203 @@
package com.craisinlord.antarchy.content.portal;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
public final class PermanentPortalShape {
public static final int MIN_WIDTH = 2;
public static final int MIN_HEIGHT = 3;
public static final int MAX_SIZE = 21;
private final PermanentPortalType type;
private final Direction.Axis axis;
private final BlockPos bottomLeft;
private final int width;
private final int height;
private PermanentPortalShape(PermanentPortalType type, Direction.Axis axis, BlockPos bottomLeft, int width, int height) {
this.type = type;
this.axis = axis;
this.bottomLeft = bottomLeft;
this.width = width;
this.height = height;
}
@Nullable
public static PermanentPortalShape findInactive(BlockGetter level, BlockPos interiorPos, PermanentPortalType type, Direction.Axis axis) {
return find(level, interiorPos, type, axis, state -> state.isAir());
}
@Nullable
public static PermanentPortalShape findActive(BlockGetter level, BlockPos interiorPos, PermanentPortalType type, Direction.Axis axis) {
Block portalBlock = type.portalBlock();
return find(level, interiorPos, type, axis, state -> state.is(portalBlock));
}
@Nullable
private static PermanentPortalShape find(
BlockGetter level,
BlockPos interiorPos,
PermanentPortalType type,
Direction.Axis axis,
Predicate<BlockState> interiorPredicate
) {
if (axis == Direction.Axis.Y || !interiorPredicate.test(level.getBlockState(interiorPos))) {
return null;
}
Direction widthDirection = axis == Direction.Axis.X ? Direction.EAST : Direction.SOUTH;
Direction leftDirection = widthDirection.getOpposite();
BlockPos cursor = interiorPos;
for (int i = 0; i < MAX_SIZE && interiorPredicate.test(level.getBlockState(cursor.below())); i++) {
cursor = cursor.below();
}
for (int i = 0; i < MAX_SIZE && interiorPredicate.test(level.getBlockState(cursor.relative(leftDirection))); i++) {
cursor = cursor.relative(leftDirection);
}
int width = measureWidth(level, cursor, widthDirection, type.frameTag(), interiorPredicate);
if (width < MIN_WIDTH) {
return null;
}
int height = measureHeight(level, cursor, widthDirection, width, type.frameTag(), interiorPredicate);
if (height < MIN_HEIGHT) {
return null;
}
return new PermanentPortalShape(type, axis, cursor.immutable(), width, height);
}
private static int measureWidth(
BlockGetter level,
BlockPos bottomLeft,
Direction widthDirection,
TagKey<Block> frameTag,
Predicate<BlockState> interiorPredicate
) {
if (!level.getBlockState(bottomLeft.relative(widthDirection.getOpposite())).is(frameTag)) {
return 0;
}
int width = 0;
while (width < MAX_SIZE && interiorPredicate.test(level.getBlockState(bottomLeft.relative(widthDirection, width)))) {
if (!level.getBlockState(bottomLeft.relative(widthDirection, width).below()).is(frameTag)) {
return 0;
}
width++;
}
if (width < MIN_WIDTH || width > MAX_SIZE) {
return 0;
}
return level.getBlockState(bottomLeft.relative(widthDirection, width)).is(frameTag) ? width : 0;
}
private static int measureHeight(
BlockGetter level,
BlockPos bottomLeft,
Direction widthDirection,
int width,
TagKey<Block> frameTag,
Predicate<BlockState> interiorPredicate
) {
BlockPos leftFrameBase = bottomLeft.relative(widthDirection.getOpposite());
BlockPos rightFrameBase = bottomLeft.relative(widthDirection, width);
for (int height = 0; height < MAX_SIZE; height++) {
if (!level.getBlockState(leftFrameBase.above(height)).is(frameTag)
|| !level.getBlockState(rightFrameBase.above(height)).is(frameTag)) {
return 0;
}
for (int x = 0; x < width; x++) {
BlockPos interiorPos = bottomLeft.relative(widthDirection, x).above(height);
if (!interiorPredicate.test(level.getBlockState(interiorPos))) {
if (height < MIN_HEIGHT) {
return 0;
}
return hasTopFrame(level, bottomLeft, widthDirection, width, height, frameTag) ? height : 0;
}
}
}
return hasTopFrame(level, bottomLeft, widthDirection, width, MAX_SIZE, frameTag) ? MAX_SIZE : 0;
}
private static boolean hasTopFrame(
BlockGetter level,
BlockPos bottomLeft,
Direction widthDirection,
int width,
int topY,
TagKey<Block> frameTag
) {
for (int x = 0; x < width; x++) {
if (!level.getBlockState(bottomLeft.relative(widthDirection, x).above(topY)).is(frameTag)) {
return false;
}
}
return true;
}
public void fill(ServerLevel level) {
BlockState portalState = this.type.portalBlock().defaultBlockState().setValue(BlockStateProperties.HORIZONTAL_AXIS, this.axis);
this.forEachInterior(pos -> level.setBlock(pos, portalState, Block.UPDATE_ALL));
}
public boolean contains(BlockPos pos) {
if (pos.getY() < this.bottomLeft.getY() || pos.getY() >= this.bottomLeft.getY() + this.height) {
return false;
}
if (this.axis == Direction.Axis.X) {
return pos.getZ() == this.bottomLeft.getZ()
&& pos.getX() >= this.bottomLeft.getX()
&& pos.getX() < this.bottomLeft.getX() + this.width;
}
return pos.getX() == this.bottomLeft.getX()
&& pos.getZ() >= this.bottomLeft.getZ()
&& pos.getZ() < this.bottomLeft.getZ() + this.width;
}
public boolean intersects(AABB box) {
final boolean[] intersects = {false};
this.forEachInterior(pos -> {
if (box.intersects(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1.0D, pos.getY() + 1.0D, pos.getZ() + 1.0D)) {
intersects[0] = true;
}
});
return intersects[0];
}
public void forEachInterior(Consumer<BlockPos> consumer) {
Direction widthDirection = this.axis == Direction.Axis.X ? Direction.EAST : Direction.SOUTH;
for (int y = 0; y < this.height; y++) {
for (int x = 0; x < this.width; x++) {
consumer.accept(this.bottomLeft.relative(widthDirection, x).above(y));
}
}
}
public Vec3 center() {
if (this.axis == Direction.Axis.X) {
return new Vec3(this.bottomLeft.getX() + (this.width / 2.0D), this.bottomLeft.getY() + (this.height / 2.0D), this.bottomLeft.getZ() + 0.5D);
}
return new Vec3(this.bottomLeft.getX() + 0.5D, this.bottomLeft.getY() + (this.height / 2.0D), this.bottomLeft.getZ() + (this.width / 2.0D));
}
}
@@ -0,0 +1,150 @@
package com.craisinlord.antarchy.content.portal;
import java.util.LinkedHashSet;
import java.util.Set;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.vehicle.DismountHelper;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.portal.DimensionTransition;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
public final class PermanentPortalTeleporter {
private static final int SEARCH_RADIUS = 8;
private static final int VERTICAL_SEARCH = 24;
private PermanentPortalTeleporter() {
}
public static void teleport(Entity entity, PermanentPortalType type) {
if (!(entity.level() instanceof ServerLevel sourceLevel) || !entity.isAlive()) {
return;
}
ServerLevel destination = resolveDestination(sourceLevel, type);
if (destination == null) {
return;
}
Vec3 arrival = findArrivalPosition(entity, destination, entity.blockPosition(), type.platformBlock().defaultBlockState());
Entity movedEntity = moveEntity(entity, destination, arrival);
if (movedEntity != null) {
movedEntity.setPortalCooldown();
}
}
@Nullable
private static ServerLevel resolveDestination(ServerLevel sourceLevel, PermanentPortalType type) {
if (sourceLevel.dimension() == type.primaryDimension()) {
return sourceLevel.getServer().overworld();
}
return sourceLevel.getServer().getLevel(type.primaryDimension());
}
private static Vec3 findArrivalPosition(Entity entity, ServerLevel destination, BlockPos preferredPos, BlockState platformState) {
Vec3 safe = findSafeArrivalPosition(entity, destination, preferredPos);
return safe != null ? safe : createFallbackPlatform(destination, preferredPos, platformState);
}
@Nullable
private static Vec3 findSafeArrivalPosition(Entity entity, ServerLevel destination, BlockPos preferredPos) {
Set<BlockPos> candidates = new LinkedHashSet<>();
addCandidate(candidates, preferredPos);
for (int radius = 0; radius <= SEARCH_RADIUS; radius++) {
for (int xOff = -radius; xOff <= radius; xOff++) {
for (int zOff = -radius; zOff <= radius; zOff++) {
if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) {
continue;
}
BlockPos horizontalPos = preferredPos.offset(xOff, 0, zOff);
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, horizontalPos));
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, horizontalPos));
for (int yOff = 0; yOff <= VERTICAL_SEARCH; yOff++) {
addCandidate(candidates, horizontalPos.above(yOff));
if (yOff > 0) {
addCandidate(candidates, horizontalPos.below(yOff));
}
}
}
}
}
for (BlockPos candidate : candidates) {
Vec3 safe = tryFindSafePosition(entity, destination, candidate);
if (safe != null) {
return safe;
}
}
return null;
}
private static void addCandidate(Set<BlockPos> candidates, @Nullable BlockPos pos) {
if (pos == null) {
return;
}
candidates.add(pos);
candidates.add(pos.above());
if (pos.getY() > Integer.MIN_VALUE) {
candidates.add(pos.below());
}
}
@Nullable
private static Vec3 tryFindSafePosition(Entity entity, ServerLevel destination, BlockPos candidate) {
Vec3 safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate, true);
if (safe != null) {
return safe;
}
for (Direction direction : Direction.Plane.HORIZONTAL) {
safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate.relative(direction), true);
if (safe != null) {
return safe;
}
}
return null;
}
private static Vec3 createFallbackPlatform(ServerLevel destination, BlockPos preferredPos, BlockState platformState) {
int minY = destination.getMinBuildHeight() + 2;
int maxY = destination.getMaxBuildHeight() - 4;
BlockPos center = new BlockPos(preferredPos.getX(), Mth.clamp(preferredPos.getY(), minY, maxY), preferredPos.getZ());
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
destination.setBlock(center.offset(dx, -1, dz), platformState, Block.UPDATE_ALL);
destination.removeBlock(center.offset(dx, 0, dz), false);
destination.removeBlock(center.offset(dx, 1, dz), false);
}
}
return Vec3.atBottomCenterOf(center);
}
@Nullable
private static Entity moveEntity(Entity entity, ServerLevel destination, Vec3 destinationPos) {
if (entity instanceof ServerPlayer player) {
player.teleportTo(destination, destinationPos.x, destinationPos.y, destinationPos.z, player.getYRot(), player.getXRot());
return player;
}
if (entity.level() == destination) {
entity.teleportTo(destinationPos.x, destinationPos.y, destinationPos.z);
return entity;
}
return entity.changeDimension(new DimensionTransition(destination, destinationPos, Vec3.ZERO, entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING));
}
}
@@ -0,0 +1,111 @@
package com.craisinlord.antarchy.content.portal;
import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.entity.ant.BrownAntEntity;
import com.craisinlord.antarchy.content.entity.ant.RedAntEntity;
import com.craisinlord.antarchy.content.entity.ant.TermiteEntity;
import java.util.Objects;
import java.util.function.Supplier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.Nullable;
public enum PermanentPortalType {
ELYTHIA("elythia", AntarchySettings::brownAntDestinationDimension, AntarchySettings::elythiaPortalEnabled, AntarchyTags.Blocks.ELYTHIA_PORTAL_FRAMES) {
@Override
boolean matchesSacrifice(LivingEntity entity) {
return entity instanceof BrownAntEntity;
}
},
THORAXIS("thoraxis", AntarchySettings::redAntDestinationDimension, AntarchySettings::thoraxisPortalEnabled, AntarchyTags.Blocks.THORAXIS_PORTAL_FRAMES) {
@Override
boolean matchesSacrifice(LivingEntity entity) {
return entity instanceof RedAntEntity;
}
},
CAVARYN("cavaryn", AntarchySettings::termiteDestinationDimension, AntarchySettings::cavarynPortalEnabled, AntarchyTags.Blocks.CAVARYN_PORTAL_FRAMES) {
@Override
boolean matchesSacrifice(LivingEntity entity) {
return entity instanceof TermiteEntity;
}
};
private final String id;
private final Supplier<ResourceKey<Level>> primaryDimensionSupplier;
private final Supplier<Boolean> enabledSupplier;
private final TagKey<Block> frameTag;
private Supplier<Block> platformBlockSupplier;
private Supplier<Block> portalBlockSupplier;
PermanentPortalType(String id, Supplier<ResourceKey<Level>> primaryDimensionSupplier, Supplier<Boolean> enabledSupplier, TagKey<Block> frameTag) {
this.id = id;
this.primaryDimensionSupplier = primaryDimensionSupplier;
this.enabledSupplier = enabledSupplier;
this.frameTag = frameTag;
}
public static void bindBlocks(
Supplier<Block> elythiaPlatform,
Supplier<Block> elythiaPortal,
Supplier<Block> thoraxisPlatform,
Supplier<Block> thoraxisPortal,
Supplier<Block> cavarynPlatform,
Supplier<Block> cavarynPortal
) {
ELYTHIA.bind(elythiaPlatform, elythiaPortal);
THORAXIS.bind(thoraxisPlatform, thoraxisPortal);
CAVARYN.bind(cavarynPlatform, cavarynPortal);
}
public static boolean portalsEnabled() {
return AntarchySettings.permanentPortalsEnabled();
}
@Nullable
public static PermanentPortalType fromSacrifice(LivingEntity entity) {
if (!portalsEnabled()) {
return null;
}
for (PermanentPortalType type : values()) {
if (type.isEnabled() && type.matchesSacrifice(entity)) {
return type;
}
}
return null;
}
private void bind(Supplier<Block> platformBlockSupplier, Supplier<Block> portalBlockSupplier) {
this.platformBlockSupplier = Objects.requireNonNull(platformBlockSupplier);
this.portalBlockSupplier = Objects.requireNonNull(portalBlockSupplier);
}
public String id() {
return this.id;
}
public boolean isEnabled() {
return portalsEnabled() && this.enabledSupplier.get();
}
public ResourceKey<Level> primaryDimension() {
return this.primaryDimensionSupplier.get();
}
public TagKey<Block> frameTag() {
return this.frameTag;
}
public Block platformBlock() {
return Objects.requireNonNull(this.platformBlockSupplier, "Platform block supplier not bound for " + this.id).get();
}
public Block portalBlock() {
return Objects.requireNonNull(this.portalBlockSupplier, "Portal block supplier not bound for " + this.id).get();
}
abstract boolean matchesSacrifice(LivingEntity entity);
}
@@ -0,0 +1,73 @@
package com.craisinlord.antarchy.content.worldgen;
import com.craisinlord.antarchy.content.block.BigBushBlock;
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.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 java.util.ArrayList;
import java.util.List;
/** Places a {@link BigBushBlock} at a fixed growth stage (age), used for sparse overworld generation. */
public class BigBushWorldgenFeature extends Feature<NoneFeatureConfiguration> {
private final int age;
public BigBushWorldgenFeature(Codec<NoneFeatureConfiguration> codec, int age) {
super(codec);
this.age = age;
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
WorldGenLevel level = context.level();
BlockPos origin = context.origin();
RandomSource random = context.random();
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.fromNamespaceAndPath("antarchy", "big_bush"));
if (!(block instanceof BigBushBlock)) {
return false;
}
List<Direction> facings = new ArrayList<>(Direction.Plane.HORIZONTAL.stream().toList());
for (int i = facings.size() - 1; i > 0; i--) {
Direction swap = facings.set(random.nextInt(i + 1), facings.get(i));
facings.set(i, swap);
}
for (Direction facing : facings) {
BlockState grown = block.defaultBlockState().setValue(BigBushBlock.AGE, age).setValue(BigBushBlock.FACING, facing);
if (canPlace(level, origin, grown)) {
BigBushBlock.placeBushBlocks(level, origin, grown, Block.UPDATE_ALL);
return true;
}
if (age == 0) {
// Facing is irrelevant at age 0 (single block); no need to try every rotation.
break;
}
}
return false;
}
private boolean canPlace(WorldGenLevel level, BlockPos origin, BlockState grown) {
if (!BigBushBlock.hasFullSupport(grown, level, origin)) {
return false;
}
List<BlockPos> positions = new ArrayList<>(BigBushBlock.partPositions(grown, origin));
positions.add(origin);
for (BlockPos pos : positions) {
if (!level.getBlockState(pos).canBeReplaced()) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,35 @@
package com.craisinlord.antarchy.content.worldgen;
import com.craisinlord.antarchy.content.block.VeryTallGrassBlock;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
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;
/** Places a single 3-tall {@link VeryTallGrassBlock} column, used for sparse overworld generation. */
public class VeryTallGrassWorldgenFeature extends Feature<NoneFeatureConfiguration> {
public VeryTallGrassWorldgenFeature(Codec<NoneFeatureConfiguration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
WorldGenLevel level = context.level();
BlockPos pos = context.origin();
if (!level.getBlockState(pos).isAir()
|| !level.getBlockState(pos.above()).isAir()
|| !level.getBlockState(pos.above(2)).isAir()) {
return false;
}
BlockPos below = pos.below();
if (!level.getBlockState(below).isFaceSturdy(level, below, Direction.UP)) {
return false;
}
VeryTallGrassBlock.placeAt(level, pos, Block.UPDATE_ALL);
return true;
}
}
@@ -0,0 +1,53 @@
package com.craisinlord.antarchy.mixins;
import com.craisinlord.antarchy.content.block.TorchflowerBushBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.BoneMealItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.DoublePlantBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(BoneMealItem.class)
public abstract class BoneMealItemTorchflowerBushMixin {
@Inject(method = "useOn", at = @At("HEAD"), cancellable = true)
private void antarchy$growTorchflowerBush(UseOnContext context, CallbackInfoReturnable<InteractionResult> cir) {
Level level = context.getLevel();
BlockPos pos = context.getClickedPos();
BlockState clickedState = level.getBlockState(pos);
if (!clickedState.is(Blocks.TORCHFLOWER)) {
return;
}
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.fromNamespaceAndPath("antarchy", "torchflower_bush"));
if (!(block instanceof TorchflowerBushBlock)) {
return;
}
BlockState lowerState = block.defaultBlockState();
if (!level.getBlockState(pos.above()).canBeReplaced() || !lowerState.canSurvive(level, pos)) {
return;
}
if (!level.isClientSide) {
DoublePlantBlock.placeAt(level, lowerState, pos, Block.UPDATE_ALL);
if (context.getPlayer() == null || !context.getPlayer().getAbilities().instabuild) {
ItemStack stack = context.getItemInHand();
stack.shrink(1);
}
level.levelEvent(1505, pos, 15);
}
cir.setReturnValue(InteractionResult.sidedSuccess(level.isClientSide));
}
}
@@ -6,6 +6,7 @@
"mixins": [
"AccessorRangedAttribute",
"BoneMealItemVeryTallGrassMixin",
"BoneMealItemTorchflowerBushMixin",
"BlockEntityTypeSignMixin",
"BloodglassMixin",
"DreamFireBlockMixin",
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,6 @@
{
"variants": {
"axis=x": { "model": "antarchy:block/cavaryn_portal_x" },
"axis=z": { "model": "antarchy:block/cavaryn_portal_z" }
}
}
@@ -0,0 +1,6 @@
{
"variants": {
"axis=x": { "model": "antarchy:block/elythia_portal_x" },
"axis=z": { "model": "antarchy:block/elythia_portal_z" }
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "antarchy:block/ouranwood_vine"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "antarchy:block/ouranwood_vine_plant"
}
}
}
@@ -0,0 +1,6 @@
{
"variants": {
"axis=x": { "model": "antarchy:block/thoraxis_portal_x" },
"axis=z": { "model": "antarchy:block/thoraxis_portal_z" }
}
}
@@ -4,247 +4,195 @@
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 256,
"texture_height": 256,
"visible_bounds_width": 9,
"texture_width": 128,
"texture_height": 128,
"visible_bounds_width": 7,
"visible_bounds_height": 4.5,
"visible_bounds_offset": [0, 1.75, 0]
},
"bones": [
{
"name": "bone",
"pivot": [0, 8.5, 16.125]
},
{
"name": "waist",
"parent": "bone",
"pivot": [0, 8.5, 16.125],
"cubes": [
{"origin": [-10, 1, 15], "size": [20, 19, 6], "uv": [98, 55]}
]
},
{
"name": "tail",
"parent": "waist",
"pivot": [0, 7.83333, 20.83333],
"cubes": [
{"origin": [-7, 2, 21], "size": [14, 17, 17], "uv": [70, 81]}
]
},
{
"name": "tail2",
"parent": "tail",
"pivot": [0, 6.5, 37.5],
"cubes": [
{"origin": [-5, 2, 38], "size": [10, 11, 17], "uv": [62, 115]}
]
},
{
"name": "tail3",
"parent": "tail2",
"pivot": [0, 5.5, 54.5],
"cubes": [
{"origin": [-3, 2, 55], "size": [6, 7, 7], "uv": [34, 163]}
]
"name": "Dorrie",
"pivot": [0, 0, 0]
},
{
"name": "body",
"parent": "bone",
"pivot": [0, 11.33767, -10.06778],
"cubes": [
{"origin": [-13, 0, -19], "size": [26, 21, 34], "uv": [0, 0]},
{"origin": [-11, 2, -24.6], "size": [22, 21, 13], "pivot": [0, 12.5, -19.6], "rotation": [-12.5, 0, 0], "uv": [0, 81]}
]
"parent": "Dorrie",
"pivot": [0, 8.2, 4.4]
},
{
"name": "neck",
"name": "right_arm",
"parent": "body",
"pivot": [0, 20.33333, -19.1],
"pivot": [-8.5, 7.75, -2],
"cubes": [
{"origin": [-8, 10, -26.6], "size": [16, 16, 15], "uv": [0, 115]}
{"origin": [-25.5, 6, -6], "size": [17, 3, 9], "uv": [7, 88]}
]
},
{
"name": "neck2",
"parent": "neck",
"pivot": [0, 25.5, -19.1],
"name": "right_thumb",
"parent": "right_arm",
"pivot": [-23.5, 7, -6],
"cubes": [
{"origin": [-6, 26, -25.6], "size": [12, 8, 13], "uv": [120, 12]}
{"origin": [-25.5, 7, -10], "size": [4, 0, 4], "uv": [20, 72]}
]
},
{
"name": "neck3",
"parent": "neck2",
"pivot": [0, 34, -19.1],
"name": "right_finger",
"parent": "right_arm",
"pivot": [-25.5, 7, -1.5],
"cubes": [
{"origin": [-5, 34, -24.6], "size": [10, 6, 11], "uv": [0, 146]}
]
},
{
"name": "head",
"parent": "neck3",
"pivot": [0.025, 40.75, -18.1],
"cubes": [
{"origin": [-6.5, 39, -25.6], "size": [13, 12, 13], "pivot": [-0.5, 44.5, -19.1], "rotation": [10, 0, 0], "uv": [116, 115]},
{"origin": [-4.9, 39, -37.6], "size": [10, 3, 16], "uv": [120, 33]},
{"origin": [-5.5, 42, -30.6], "size": [11, 7, 9], "uv": [100, 156]},
{"origin": [-5.5, 42, -37.6], "size": [11, 7, 8], "inflate": 0.2, "uv": [150, 65]}
]
},
{
"name": "googles",
"parent": "head",
"pivot": [0, 47.45804, -21.34628],
"cubes": [
{"origin": [-5.5, 46.7, -27.4], "size": [11, 3, 1], "inflate": 0.1, "pivot": [0, 47.6, -24.6], "rotation": [9, 0, 0], "uv": [162, 151]},
{"origin": [-7, 45.7, -19.3], "size": [14, 3, 7], "pivot": [-0.5, 44.5, -19.1], "rotation": [10, 0, 0], "uv": [140, 156]},
{"origin": [-7.5, 44.7, -26.6], "size": [15, 5, 8], "pivot": [-0.5, 44.5, -19.1], "rotation": [10, 0, 0], "uv": [150, 52]}
]
},
{
"name": "saddle",
"parent": "body",
"pivot": [4.66667, 18.5, 1.16667],
"cubes": [
{"origin": [-13, 21, -10], "size": [26, 3, 23], "uv": [0, 55]},
{"origin": [-9, 24, -10], "size": [18, 5, 3], "uv": [132, 106]},
{"origin": [-13, 24, 9], "size": [26, 4, 4], "uv": [132, 80]},
{"origin": [-14, -1, 7], "size": [28, 10, 2], "uv": [120, 0]},
{"origin": [-15, 9, 6], "size": [2, 14, 4], "uv": [88, 164]},
{"origin": [13, 9, 6], "size": [2, 14, 4], "uv": [88, 164], "mirror": true},
{"origin": [13, 9, -7], "size": [2, 14, 4], "uv": [88, 164], "mirror": true},
{"origin": [-15, 9, -7], "size": [2, 14, 4], "uv": [88, 164]},
{"origin": [-14, -1, -6], "size": [28, 10, 2], "uv": [120, 0]}
]
},
{
"name": "left_leg",
"parent": "body",
"pivot": [-10.875, 0.875, 13.375],
"rotation": [0, 45, 0],
"cubes": [
{"origin": [-14, 0, 9], "size": [5, 3, 9], "uv": [60, 164]}
]
},
{
"name": "left_leg2",
"parent": "left_leg",
"pivot": [-14.66667, 0.66667, 13.33333]
},
{
"name": "left_leg3",
"parent": "left_leg2",
"pivot": [-14.66667, 0.66667, 13.33333],
"cubes": [
{"origin": [-19, 0, 9], "size": [5, 2, 9], "uv": [140, 166]}
]
},
{
"name": "left_leg4",
"parent": "left_leg3",
"pivot": [-19.25, 0.5, 13.25],
"cubes": [
{"origin": [-27, 0, 9], "size": [8, 1, 9], "uv": [0, 163]},
{"origin": [-30, 0, 9], "size": [3, 1, 8], "uv": [168, 114]}
]
},
{
"name": "right_leg",
"parent": "body",
"pivot": [10.875, 0.875, 13.375],
"rotation": [0, -45, 0],
"cubes": [
{"origin": [9, 0, 9], "size": [5, 3, 9], "uv": [60, 164], "mirror": true}
]
},
{
"name": "right_leg2",
"parent": "right_leg",
"pivot": [14.66667, 0.66667, 13.33333]
},
{
"name": "right_leg3",
"parent": "right_leg2",
"pivot": [14.66667, 0.66667, 13.33333],
"cubes": [
{"origin": [14, 0, 9], "size": [5, 2, 9], "uv": [140, 166], "mirror": true}
]
},
{
"name": "right_leg4",
"parent": "right_leg3",
"pivot": [19.25, 0.5, 13.25],
"cubes": [
{"origin": [19, 0, 9], "size": [8, 1, 9], "uv": [0, 163], "mirror": true},
{"origin": [27, 0, 9], "size": [3, 1, 8], "uv": [168, 114], "mirror": true}
{"origin": [-33.5, 7, -6], "size": [8, 0, 9], "uv": [23, 79]}
]
},
{
"name": "left_arm",
"parent": "body",
"pivot": [-12.41667, 1.66667, -9.25],
"pivot": [8.5, 7.75, -2],
"cubes": [
{"origin": [-15, 0, -18], "size": [4, 6, 15], "uv": [62, 143]}
{"origin": [8.5, 6, -6], "size": [17, 3, 9], "uv": [7, 88], "mirror": true}
]
},
{
"name": "left_arm2",
"name": "left_thumb",
"parent": "left_arm",
"pivot": [-14.7, 1.4, -9],
"pivot": [23.5, 7, -6],
"cubes": [
{"origin": [-25, 0, -17], "size": [10, 5, 13], "uv": [132, 88]}
{"origin": [21.5, 7, -10], "size": [4, 0, 4], "uv": [20, 72], "mirror": true}
]
},
{
"name": "left_arm3",
"parent": "left_arm2",
"pivot": [-25.125, 1.125, -8.625],
"name": "left_finger",
"parent": "left_arm",
"pivot": [25.5, 7, -1.5],
"cubes": [
{"origin": [-35, 0, -17], "size": [10, 3, 13], "uv": [116, 140]}
{"origin": [25.5, 7, -6], "size": [8, 0, 9], "uv": [23, 79], "mirror": true}
]
},
{
"name": "left_arm4",
"parent": "left_arm3",
"pivot": [-35.5, 1, -8],
"cubes": [
{"origin": [-45, 0, -17], "size": [10, 2, 9], "uv": [162, 140]},
{"origin": [-42, 0, -7], "size": [2, 2, 3], "uv": [100, 143]},
{"origin": [-40, 0, -8], "size": [5, 2, 4], "uv": [42, 146]}
]
},
{
"name": "right_arm",
"name": "left_leg",
"parent": "body",
"pivot": [12.41667, 1.66667, -9.25],
"pivot": [4.5, 7.75, 18],
"cubes": [
{"origin": [11, 0, -18], "size": [4, 6, 15], "uv": [62, 143], "mirror": true}
{"origin": [4.5, 6, 14], "size": [17, 3, 9], "uv": [7, 88], "mirror": true}
]
},
{
"name": "right_arm2",
"parent": "right_arm",
"pivot": [14.7, 1.4, -9],
"name": "left_toe",
"parent": "left_leg",
"pivot": [19.5, 7, 14],
"cubes": [
{"origin": [15, 0, -17], "size": [10, 5, 13], "uv": [132, 88], "mirror": true}
{"origin": [17.5, 7, 8], "size": [4, 0, 6], "uv": [26, 71], "mirror": true}
]
},
{
"name": "right_arm3",
"parent": "right_arm2",
"pivot": [25.125, 1.125, -8.625],
"name": "left_toe2",
"parent": "left_leg",
"pivot": [21.5, 7, 18.5],
"cubes": [
{"origin": [25, 0, -17], "size": [10, 3, 13], "uv": [116, 140], "mirror": true}
{"origin": [21.5, 7, 14], "size": [10, 0, 9], "uv": [41, 80], "mirror": true}
]
},
{
"name": "right_arm4",
"parent": "right_arm3",
"pivot": [35.5, 1, -8],
"name": "right_leg",
"parent": "body",
"pivot": [-4.5, 7.75, 18],
"cubes": [
{"origin": [35, 0, -17], "size": [10, 2, 9], "uv": [162, 140], "mirror": true},
{"origin": [40, 0, -7], "size": [2, 2, 3], "uv": [100, 143], "mirror": true},
{"origin": [35, 0, -8], "size": [5, 2, 4], "uv": [42, 146], "mirror": true}
{"origin": [-21.5, 6, 14], "size": [17, 3, 9], "uv": [7, 88]}
]
},
{
"name": "right_toe",
"parent": "right_leg",
"pivot": [-19.5, 7, 14],
"cubes": [
{"origin": [-21.5, 7, 8], "size": [4, 0, 6], "uv": [26, 71]}
]
},
{
"name": "right_toe2",
"parent": "right_leg",
"pivot": [-21.5, 7, 18.5],
"cubes": [
{"origin": [-31.5, 7, 14], "size": [10, 0, 9], "uv": [41, 80]}
]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 15, 7],
"cubes": [
{"origin": [-11.5, 6, 3], "size": [23, 13, 13], "inflate": 0.1, "uv": [0, 126]},
{"origin": [-10.5, 0, -10], "size": [21, 18, 30], "inflate": 0.1, "uv": [0, 0]},
{"origin": [-15.75, 9, -5], "size": [5, 9, 14], "uv": [73, 125]}
]
},
{
"name": "tail",
"parent": "torso",
"pivot": [0, 12.5, 20],
"cubes": [
{"origin": [-4, 4, 20], "size": [8, 14, 12], "inflate": 0.05, "uv": [0, 100]}
]
},
{
"name": "tail2",
"parent": "tail",
"pivot": [0, 14, 32],
"cubes": [
{"origin": [-4, 10, 32], "size": [8, 8, 12], "uv": [59, 80]}
]
},
{
"name": "neck",
"parent": "torso",
"pivot": [0, 16, -5.175],
"cubes": [
{"origin": [-6, 12, -10.175], "size": [12, 13, 10], "uv": [66, 57]},
{"origin": [-6, 14, -10.175], "size": [12, 13, 10], "inflate": 0.1, "uv": [72, 0]}
]
},
{
"name": "neck2",
"parent": "neck",
"pivot": [0, 25, -5.175],
"cubes": [
{"origin": [-4, 24, -9.175], "size": [8, 8, 8], "uv": [0, 71]}
]
},
{
"name": "head",
"parent": "neck2",
"pivot": [0, 31, -6.00833],
"cubes": [
{"origin": [-5, 31, -11.175], "size": [10, 13, 10], "inflate": 0.1, "uv": [0, 48]},
{"origin": [-8, 31, -9.175], "size": [3, 6, 7], "uv": [40, 60]},
{"origin": [5, 31, -9.175], "size": [3, 6, 7], "uv": [0, 9]},
{"origin": [-5, 33, -15.175], "size": [10, 5, 4], "uv": [76, 48]},
{"origin": [-6, 33, -21.175], "size": [12, 6, 6], "uv": [40, 48]}
]
},
{
"name": "goggle",
"parent": "head",
"pivot": [0, 41, -6.175],
"cubes": [
{"origin": [-6, 37, -12.175], "size": [12, 8, 12], "inflate": 0.1, "uv": [47, 102]}
]
},
{
"name": "eyes_closed",
"parent": "head",
"pivot": [0, 40.95, -8.75],
"cubes": [
{"origin": [-5, 37.95, -10.25], "size": [10, 6, 3], "inflate": 0.1, "uv": [28, 100]}
]
},
{
"name": "jaw",
"parent": "head",
"pivot": [0, 33, -11.175],
"cubes": [
{"origin": [-4, 31, -18.175], "size": [8, 2, 7], "uv": [0, 0]}
]
}
]
@@ -17,6 +17,7 @@
"block.antarchy.ouranwood_button": "Ouranwood Button",
"block.antarchy.ouranwood_leaves": "Ouranwood Leaves",
"block.antarchy.ouranwood_acorn": "Ouranwood Acorn",
"block.antarchy.ouranwood_vine": "Ouranwood Vine",
"block.antarchy.ouranwood_sign": "Ouranwood Sign",
"block.antarchy.ouranwood_hanging_sign": "Ouranwood Hanging Sign",
"block.antarchy.orange_milkweed": "Orange Milkweed",
@@ -76,10 +77,13 @@
"block.antarchy.nyxite_spike": "Nyxite Spike",
"block.antarchy.potent_nyxite": "Potent Nyxite",
"block.antarchy.triffid_goo_block": "Triffid Goo Block",
"block.antarchy.elythia_portal": "Elythia Portal",
"block.antarchy.cloud_block": "Cloud Block",
"block.antarchy.thoraxis_portal": "Thoraxis Portal",
"block.antarchy.antimetal": "Antimetal",
"block.antarchy.polished_antimetal": "Polished Antimetal",
"block.antarchy.antimetal_scaffolding": "Antimetal Scaffolding",
"block.antarchy.cavaryn_portal": "Cavaryn Portal",
"block.antarchy.cornea_stalk": "Cornea Stalk",
"block.antarchy.dream_torch": "Dream Torch",
"block.antarchy.dream_wall_torch": "Dream Wall Torch",
@@ -272,6 +276,7 @@
"item.antarchy.polished_antimetal": "Polished Antimetal",
"item.antarchy.antimetal_scaffolding": "Antimetal Scaffolding",
"item.antarchy.ouranwood_acorn": "Ouranwood Acorn",
"item.antarchy.ouranwood_vine": "Ouranwood Vine",
"item.antarchy.ouranwood_boat": "Ouranwood Boat",
"item.antarchy.ouranwood_chest_boat": "Ouranwood Chest Boat",
"item.antarchy.big_bush": "Big Bush",
@@ -520,6 +525,10 @@
"advancements.antarchy.water_cannon_craft.description": "Obtain a Water Cannon.",
"advancements.antarchy.kill_toreterror.title": "More like Tore-Terrible Aim!",
"advancements.antarchy.kill_toreterror.description": "Defeat the Toreterror.",
"advancements.antarchy.challenge_games.title": "Challenge Games!",
"advancements.antarchy.challenge_games.description": "Enter the Ruined Arena.",
"advancements.antarchy.bugged_out.title": "Bugged Out",
"advancements.antarchy.bugged_out.description": "Defeat the Alpha Mantis.",
"death.attack.bed_bug_bite": "%1$s got bit by the bed bugs",
"death.attack.bed_bug_bite.player": "%1$s got bit by the bed bugs while fighting %2$s",
"message.antarchy.dread_too_scared_to_sleep": "You are too scared to sleep.",
@@ -0,0 +1,17 @@
{
"parent": "block/block",
"textures": {
"portal": "antarchy:block/cavaryn_portal",
"particle": "antarchy:block/cavaryn_portal"
},
"elements": [
{
"from": [0, 0, 7.5],
"to": [16, 16, 8.5],
"faces": {
"north": { "texture": "#portal" },
"south": { "texture": "#portal" }
}
}
]
}
@@ -0,0 +1,17 @@
{
"parent": "block/block",
"textures": {
"portal": "antarchy:block/cavaryn_portal",
"particle": "antarchy:block/cavaryn_portal"
},
"elements": [
{
"from": [7.5, 0, 0],
"to": [8.5, 16, 16],
"faces": {
"west": { "texture": "#portal" },
"east": { "texture": "#portal" }
}
}
]
}
@@ -0,0 +1,17 @@
{
"parent": "block/block",
"textures": {
"portal": "antarchy:block/elythia_portal",
"particle": "antarchy:block/elythia_portal"
},
"elements": [
{
"from": [0, 0, 7.5],
"to": [16, 16, 8.5],
"faces": {
"north": { "texture": "#portal" },
"south": { "texture": "#portal" }
}
}
]
}
@@ -0,0 +1,17 @@
{
"parent": "block/block",
"textures": {
"portal": "antarchy:block/elythia_portal",
"particle": "antarchy:block/elythia_portal"
},
"elements": [
{
"from": [7.5, 0, 0],
"to": [8.5, 16, 16],
"faces": {
"west": { "texture": "#portal" },
"east": { "texture": "#portal" }
}
}
]
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cross",
"textures": {
"cross": "antarchy:block/ouranwood/ouranwood_vine"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cross",
"textures": {
"cross": "antarchy:block/ouranwood/ouranwood_vine_plant"
}
}
@@ -0,0 +1,17 @@
{
"parent": "block/block",
"textures": {
"portal": "antarchy:block/thoraxis_portal",
"particle": "antarchy:block/thoraxis_portal"
},
"elements": [
{
"from": [0, 0, 7.5],
"to": [16, 16, 8.5],
"faces": {
"north": { "texture": "#portal" },
"south": { "texture": "#portal" }
}
}
]
}
@@ -0,0 +1,17 @@
{
"parent": "block/block",
"textures": {
"portal": "antarchy:block/thoraxis_portal",
"particle": "antarchy:block/thoraxis_portal"
},
"elements": [
{
"from": [7.5, 0, 0],
"to": [8.5, 16, 16],
"faces": {
"west": { "texture": "#portal" },
"east": { "texture": "#portal" }
}
}
]
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "antarchy:block/ouranwood/ouranwood_vine"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

@@ -0,0 +1,3 @@
{
"animation": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -0,0 +1,3 @@
{
"animation": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@@ -0,0 +1,3 @@
{
"animation": {}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,34 @@
{
"parent": "minecraft:adventure/root",
"criteria": {
"kill_alpha_mantis": {
"conditions": {
"entity": {
"type": "antarchy:alpha_mantis"
}
},
"trigger": "minecraft:player_killed_entity"
}
},
"display": {
"announce_to_chat": true,
"description": {
"translate": "advancements.antarchy.bugged_out.description"
},
"frame": "challenge",
"icon": {
"count": 1,
"id": "antarchy:alpha_mantis_spawn_egg"
},
"show_toast": true,
"title": {
"translate": "advancements.antarchy.bugged_out.title"
}
},
"requirements": [
[
"kill_alpha_mantis"
]
],
"sends_telemetry_event": true
}
@@ -0,0 +1,42 @@
{
"parent": "minecraft:adventure/root",
"criteria": {
"discover_ruined_arena": {
"conditions": {
"player": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"location": {
"structures": "antarchy:ruined_arena"
}
}
}
]
},
"trigger": "minecraft:location"
}
},
"display": {
"announce_to_chat": true,
"description": {
"translate": "advancements.antarchy.challenge_games.description"
},
"frame": "challenge",
"icon": {
"count": 1,
"id": "minecraft:stone_bricks"
},
"show_toast": true,
"title": {
"translate": "advancements.antarchy.challenge_games.title"
}
},
"requirements": [
[
"discover_ruined_arena"
]
],
"sends_telemetry_event": true
}
@@ -0,0 +1,25 @@
{
"type": "minecraft:block",
"pools": [
{
"conditions": [
{
"condition": "minecraft:match_tool",
"predicate": {
"items": [
"minecraft:shears"
]
}
}
],
"entries": [
{
"type": "minecraft:item",
"name": "antarchy:ouranwood_vine"
}
],
"rolls": 1.0
}
],
"random_sequence": "antarchy:blocks/ouranwood_vine"
}
@@ -153,7 +153,7 @@
"function": "minecraft:set_components",
"components": {
"minecraft:potion_contents": {
"potion": "antarchy:inverted"
"potion": "minecraft:slow_falling"
}
}
}
@@ -161,7 +161,7 @@
},
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"name": "minecraft:book",
"weight": 5,
"functions": [
{
@@ -198,14 +198,14 @@
{
"type": "minecraft:item",
"name": "antarchy:uranium_nugget",
"weight": 3,
"weight": 40,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 1.0,
"max": 2.0
"min": 2.0,
"max": 5.0
}
}
]
@@ -213,14 +213,14 @@
{
"type": "minecraft:item",
"name": "antarchy:titanium_nugget",
"weight": 3,
"weight": 40,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 1.0,
"max": 2.0
"min": 2.0,
"max": 5.0
}
}
]
@@ -283,7 +283,7 @@
},
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"name": "minecraft:book",
"weight": 6,
"functions": [
{
@@ -65,7 +65,7 @@
},
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"name": "minecraft:book",
"weight": 8,
"functions": [
{
@@ -234,7 +234,7 @@
},
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"name": "minecraft:book",
"weight": 4,
"functions": [
{
@@ -163,7 +163,7 @@
},
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"name": "minecraft:book",
"weight": 10,
"functions": [
{
@@ -200,14 +200,14 @@
{
"type": "minecraft:item",
"name": "antarchy:uranium_nugget",
"weight": 4,
"weight": 56,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 1.0,
"max": 2.0
"min": 4.0,
"max": 9.0
}
}
]
@@ -215,14 +215,14 @@
{
"type": "minecraft:item",
"name": "antarchy:titanium_nugget",
"weight": 4,
"weight": 56,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 1.0,
"max": 2.0
"min": 4.0,
"max": 9.0
}
}
]
@@ -292,7 +292,7 @@
},
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"name": "minecraft:book",
"weight": 10,
"functions": [
{
@@ -51,11 +51,6 @@
}
]
},
{
"type": "minecraft:item",
"name": "antarchy:battle_axe",
"weight": 12
},
{
"type": "minecraft:item",
"name": "minecraft:shield",
@@ -199,14 +194,14 @@
{
"type": "minecraft:item",
"name": "antarchy:uranium_nugget",
"weight": 4,
"weight": 48,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 1.0,
"max": 2.0
"min": 3.0,
"max": 7.0
}
}
]
@@ -214,14 +209,14 @@
{
"type": "minecraft:item",
"name": "antarchy:titanium_nugget",
"weight": 4,
"weight": 48,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 1.0,
"max": 2.0
"min": 3.0,
"max": 7.0
}
}
]
@@ -253,7 +248,7 @@
},
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"name": "minecraft:book",
"weight": 6,
"functions": [
{
@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"antarchy:myrmite"
]
}
@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"antarchy:mossy_ouranwood_wood"
]
}
@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"antarchy:nyxite"
]
}
@@ -0,0 +1,10 @@
{
"replace": false,
"values": [
"minecraft:taiga",
"minecraft:snowy_taiga",
"minecraft:dark_forest",
{ "id": "#c:is_taiga", "required": false },
{ "id": "#c:is_dark_forest", "required": false }
]
}
@@ -0,0 +1,8 @@
{
"replace": false,
"values": [
"minecraft:forest",
"minecraft:birch_forest",
"minecraft:dark_forest"
]
}
@@ -0,0 +1,7 @@
{
"replace": false,
"values": [
"minecraft:old_growth_pine_taiga",
"minecraft:old_growth_spruce_taiga"
]
}
@@ -0,0 +1,19 @@
{
"replace": false,
"values": [
"minecraft:plains",
"minecraft:sunflower_plains",
"minecraft:meadow",
"minecraft:savanna",
"minecraft:forest",
"minecraft:flower_forest",
"minecraft:birch_forest",
"minecraft:dark_forest",
"minecraft:taiga",
"minecraft:snowy_taiga",
{ "id": "#c:is_plains", "required": false },
{ "id": "#c:is_savanna", "required": false },
{ "id": "#c:is_forest", "required": false },
{ "id": "#c:is_taiga", "required": false }
]
}
@@ -0,0 +1,9 @@
{
"replace": false,
"values": [
"minecraft:plains",
"minecraft:savanna",
"minecraft:forest",
{ "id": "#c:is_jungle", "required": false }
]
}
@@ -0,0 +1,25 @@
{
"type": "minecraft:random_patch",
"config": {
"tries": 1,
"xz_spread": 0,
"y_spread": 0,
"feature": {
"feature": {
"type": "minecraft:simple_block",
"config": {
"to_place": {
"type": "minecraft:simple_state_provider",
"state": { "Name": "antarchy:big_bush" }
}
}
},
"placement": [
{
"type": "minecraft:block_predicate_filter",
"predicate": { "type": "minecraft:matching_blocks", "blocks": "minecraft:air" }
}
]
}
}
}
@@ -0,0 +1,4 @@
{
"type": "antarchy:big_bush_2x2",
"config": {}
}
@@ -0,0 +1,4 @@
{
"type": "antarchy:big_bush_3x3",
"config": {}
}
@@ -0,0 +1,25 @@
{
"type": "minecraft:random_patch",
"config": {
"tries": 6,
"xz_spread": 4,
"y_spread": 2,
"feature": {
"feature": {
"type": "minecraft:simple_block",
"config": {
"to_place": {
"type": "minecraft:simple_state_provider",
"state": { "Name": "antarchy:very_short_grass" }
}
}
},
"placement": [
{
"type": "minecraft:block_predicate_filter",
"predicate": { "type": "minecraft:matching_blocks", "blocks": "minecraft:air" }
}
]
}
}
}
@@ -0,0 +1,4 @@
{
"type": "antarchy:very_tall_grass",
"config": {}
}
@@ -0,0 +1,9 @@
{
"feature": "antarchy:big_bush",
"placement": [
{ "type": "minecraft:rarity_filter", "chance": 80 },
{ "type": "minecraft:in_square" },
{ "type": "minecraft:heightmap", "heightmap": "MOTION_BLOCKING" },
{ "type": "minecraft:biome" }
]
}
@@ -0,0 +1,9 @@
{
"feature": "antarchy:big_bush_2x2",
"placement": [
{ "type": "minecraft:rarity_filter", "chance": 80 },
{ "type": "minecraft:in_square" },
{ "type": "minecraft:heightmap", "heightmap": "MOTION_BLOCKING" },
{ "type": "minecraft:biome" }
]
}
@@ -0,0 +1,9 @@
{
"feature": "antarchy:big_bush_3x3",
"placement": [
{ "type": "minecraft:rarity_filter", "chance": 5 },
{ "type": "minecraft:in_square" },
{ "type": "minecraft:heightmap", "heightmap": "MOTION_BLOCKING" },
{ "type": "minecraft:biome" }
]
}
@@ -0,0 +1,9 @@
{
"feature": "antarchy:very_short_grass",
"placement": [
{ "type": "minecraft:rarity_filter", "chance": 1 },
{ "type": "minecraft:in_square" },
{ "type": "minecraft:heightmap", "heightmap": "MOTION_BLOCKING" },
{ "type": "minecraft:biome" }
]
}
@@ -0,0 +1,9 @@
{
"feature": "antarchy:very_tall_grass",
"placement": [
{ "type": "minecraft:rarity_filter", "chance": 30 },
{ "type": "minecraft:in_square" },
{ "type": "minecraft:heightmap", "heightmap": "MOTION_BLOCKING" },
{ "type": "minecraft:biome" }
]
}
@@ -5,7 +5,7 @@
"terrain_height_radius_check": 4,
"allowed_terrain_height_range": 14,
"valid_biome_radius_check": 1,
"biomes": "#antarchy:has_structure/ruined_anrea_biomes",
"biomes": "#antarchy:has_structure/ruined_arena_biomes",
"step": "surface_structures",
"enhanced_terrain_adaptation": {
"type": "integrated_api:none"