blood crystal sounds, fixed variious other sounds. refractored sound folders
This commit is contained in:
1 parent
53f223a86c
commit
ce66f56c87
350 files changed
+6269
-550
No files matched your search
@@ -82,6 +82,9 @@ public final class AntarchySettings {
|
||||
private static int bloodCrystalKatanaAttackDamage = 7;
|
||||
private static double bloodCrystalKatanaLaunchStrength = 1.1D;
|
||||
private static int bloodCrystalKatanaTrailDurationTicks = 12;
|
||||
private static double bloodCrystalKatanaReachBonus = 4.0D;
|
||||
private static int bloodCrystalKatanaInvulnTicks = 8;
|
||||
private static int bloodCrystalKatanaDashCooldownTicks = 4;
|
||||
private static double bigBerthaBasiliskCooldownSeconds = 7.0D;
|
||||
private static double bigBerthaLucidInvertedDurationSeconds = 3.0D;
|
||||
private static double bigBerthaLucidInvertedDamageBonusPercent = 25.0D;
|
||||
@@ -226,6 +229,8 @@ public final class AntarchySettings {
|
||||
private static double diamondMinecartCoastDeceleration = 0.02D;
|
||||
private static boolean diamondMinecartMobDamageEnabled = false;
|
||||
private static double diamondMinecartMaxMobDamage = 4.0D;
|
||||
private static double hoverboardMaxSpeed = 3.0D;
|
||||
private static double hoverboardAcceleration = 0.05D;
|
||||
private static boolean dreadHallucinationSoundsEnabled = true;
|
||||
private static double dreadHallucinationSoundMinInterval = 3.0D;
|
||||
private static double dreadHallucinationSoundMaxInterval = 10.0D;
|
||||
@@ -332,6 +337,21 @@ public final class AntarchySettings {
|
||||
private static double lucidMovementSpeed = 0.22D;
|
||||
private static double lucidFlyingSpeed = 0.35D;
|
||||
private static double lucidKnockbackResistance = 0.5D;
|
||||
private static double vortexHealth = 70.0D;
|
||||
private static double vortexAttackDamage = 4.0D;
|
||||
private static double vortexMovementSpeed = 0.22D;
|
||||
private static double vortexFlyingSpeed = 0.35D;
|
||||
private static int vortexMaxActiveVortexes = 3;
|
||||
private static int windVortexDurationTicks = 140;
|
||||
private static double windVortexPullStrength = 0.32D;
|
||||
private static double windVortexLaunchStrength = 1.0D;
|
||||
private static double vortexLensMinRadius = 1.5D;
|
||||
private static double vortexLensMaxRadius = 10.0D;
|
||||
private static double vortexLensMinHeight = 3.0D;
|
||||
private static double vortexLensMaxHeight = 20.0D;
|
||||
private static double vortexLensPullStrength = 0.42D;
|
||||
private static double vortexLensPushStrength = 0.38D;
|
||||
private static double vortexLensLaunchStrength = 1.15D;
|
||||
private static double missileSquidHealth = 60.0D;
|
||||
private static double missileSquidAttackDamage = 9.0D;
|
||||
private static double missileSquidMovementSpeed = 0.84D;
|
||||
@@ -1861,6 +1881,12 @@ public final class AntarchySettings {
|
||||
public static double diamondMinecartMaxMobDamage() { return diamondMinecartMaxMobDamage; }
|
||||
public static void setDiamondMinecartMaxMobDamage(double v) { diamondMinecartMaxMobDamage = v; }
|
||||
|
||||
public static double hoverboardMaxSpeed() { return hoverboardMaxSpeed; }
|
||||
public static void setHoverboardMaxSpeed(double value) { hoverboardMaxSpeed = value; }
|
||||
|
||||
public static double hoverboardAcceleration() { return hoverboardAcceleration; }
|
||||
public static void setHoverboardAcceleration(double value) { hoverboardAcceleration = value; }
|
||||
|
||||
public static boolean dreadHallucinationSoundsEnabled() {
|
||||
return dreadHallucinationSoundsEnabled;
|
||||
}
|
||||
@@ -2046,6 +2072,15 @@ public final class AntarchySettings {
|
||||
public static int bloodCrystalKatanaTrailDurationTicks() { return bloodCrystalKatanaTrailDurationTicks; }
|
||||
public static void setBloodCrystalKatanaTrailDurationTicks(int value) { bloodCrystalKatanaTrailDurationTicks = value; }
|
||||
|
||||
public static double bloodCrystalKatanaReachBonus() { return bloodCrystalKatanaReachBonus; }
|
||||
public static void setBloodCrystalKatanaReachBonus(double value) { bloodCrystalKatanaReachBonus = value; }
|
||||
|
||||
public static int bloodCrystalKatanaInvulnTicks() { return bloodCrystalKatanaInvulnTicks; }
|
||||
public static void setBloodCrystalKatanaInvulnTicks(int value) { bloodCrystalKatanaInvulnTicks = value; }
|
||||
|
||||
public static int bloodCrystalKatanaDashCooldownTicks() { return bloodCrystalKatanaDashCooldownTicks; }
|
||||
public static void setBloodCrystalKatanaDashCooldownTicks(int value) { bloodCrystalKatanaDashCooldownTicks = value; }
|
||||
|
||||
public static double emperorScorpionAttackDamage() { return emperorScorpionAttackDamage; }
|
||||
public static void setEmperorScorpionAttackDamage(double value) { emperorScorpionAttackDamage = value; }
|
||||
|
||||
@@ -2223,6 +2258,51 @@ public final class AntarchySettings {
|
||||
public static double lucidKnockbackResistance() { return lucidKnockbackResistance; }
|
||||
public static void setLucidKnockbackResistance(double value) { lucidKnockbackResistance = value; }
|
||||
|
||||
public static double vortexHealth() { return vortexHealth; }
|
||||
public static void setVortexHealth(double value) { vortexHealth = value; }
|
||||
|
||||
public static double vortexAttackDamage() { return vortexAttackDamage; }
|
||||
public static void setVortexAttackDamage(double value) { vortexAttackDamage = value; }
|
||||
|
||||
public static double vortexMovementSpeed() { return vortexMovementSpeed; }
|
||||
public static void setVortexMovementSpeed(double value) { vortexMovementSpeed = value; }
|
||||
|
||||
public static double vortexFlyingSpeed() { return vortexFlyingSpeed; }
|
||||
public static void setVortexFlyingSpeed(double value) { vortexFlyingSpeed = value; }
|
||||
|
||||
public static int vortexMaxActiveVortexes() { return vortexMaxActiveVortexes; }
|
||||
public static void setVortexMaxActiveVortexes(int value) { vortexMaxActiveVortexes = value; }
|
||||
|
||||
public static int windVortexDurationTicks() { return windVortexDurationTicks; }
|
||||
public static void setWindVortexDurationTicks(int value) { windVortexDurationTicks = value; }
|
||||
|
||||
public static double windVortexPullStrength() { return windVortexPullStrength; }
|
||||
public static void setWindVortexPullStrength(double value) { windVortexPullStrength = value; }
|
||||
|
||||
public static double windVortexLaunchStrength() { return windVortexLaunchStrength; }
|
||||
public static void setWindVortexLaunchStrength(double value) { windVortexLaunchStrength = value; }
|
||||
|
||||
public static double vortexLensMinRadius() { return vortexLensMinRadius; }
|
||||
public static void setVortexLensMinRadius(double value) { vortexLensMinRadius = value; }
|
||||
|
||||
public static double vortexLensMaxRadius() { return vortexLensMaxRadius; }
|
||||
public static void setVortexLensMaxRadius(double value) { vortexLensMaxRadius = value; }
|
||||
|
||||
public static double vortexLensMinHeight() { return vortexLensMinHeight; }
|
||||
public static void setVortexLensMinHeight(double value) { vortexLensMinHeight = value; }
|
||||
|
||||
public static double vortexLensMaxHeight() { return vortexLensMaxHeight; }
|
||||
public static void setVortexLensMaxHeight(double value) { vortexLensMaxHeight = value; }
|
||||
|
||||
public static double vortexLensPullStrength() { return vortexLensPullStrength; }
|
||||
public static void setVortexLensPullStrength(double value) { vortexLensPullStrength = value; }
|
||||
|
||||
public static double vortexLensPushStrength() { return vortexLensPushStrength; }
|
||||
public static void setVortexLensPushStrength(double value) { vortexLensPushStrength = value; }
|
||||
|
||||
public static double vortexLensLaunchStrength() { return vortexLensLaunchStrength; }
|
||||
public static void setVortexLensLaunchStrength(double value) { vortexLensLaunchStrength = value; }
|
||||
|
||||
public static double missileSquidHealth() { return missileSquidHealth; }
|
||||
public static void setMissileSquidHealth(double value) { missileSquidHealth = value; }
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.craisinlord.antarchy.content.entity.WaspEntity;
|
||||
import com.craisinlord.antarchy.content.entity.brutalfly.BrutalflyEntity;
|
||||
import com.craisinlord.antarchy.content.entity.brutalfly.BrutalflyOrbEntity;
|
||||
import com.craisinlord.antarchy.content.block.entity.HushweedBlockEntity;
|
||||
import com.craisinlord.antarchy.content.block.entity.VortexLensBlockEntity;
|
||||
import com.craisinlord.antarchy.content.entity.flying_squirrel.FlyingSquirrelEntity;
|
||||
import com.craisinlord.antarchy.content.entity.MissileSquidEntity;
|
||||
import com.craisinlord.antarchy.content.entity.OctopusBombEntity;
|
||||
@@ -28,6 +29,9 @@ import com.craisinlord.antarchy.content.entity.MantisEntity;
|
||||
import com.craisinlord.antarchy.content.entity.ReverieEntity;
|
||||
import com.craisinlord.antarchy.content.entity.ScorpionEntity;
|
||||
import com.craisinlord.antarchy.content.entity.lucid.LucidEntity;
|
||||
import com.craisinlord.antarchy.content.entity.vortex.VortexChargeProjectileEntity;
|
||||
import com.craisinlord.antarchy.content.entity.vortex.VortexEntity;
|
||||
import com.craisinlord.antarchy.content.entity.vortex.WindVortexEntity;
|
||||
import com.craisinlord.antarchy.content.entity.nightmare.NightmareEntity;
|
||||
import com.craisinlord.antarchy.content.entity.nightmare.NightmareBiteEntity;
|
||||
import com.craisinlord.antarchy.content.entity.nightmare.NightmarePortalEntity;
|
||||
@@ -81,6 +85,16 @@ public final class AntarchyObjects {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<EntityType<LucidEntity>> LUCID = (Supplier<EntityType<LucidEntity>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<EntityType<VortexEntity>> VORTEX = (Supplier<EntityType<VortexEntity>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<EntityType<WindVortexEntity>> WIND_VORTEX = (Supplier<EntityType<WindVortexEntity>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<EntityType<VortexChargeProjectileEntity>> VORTEX_CHARGE_PROJECTILE = (Supplier<EntityType<VortexChargeProjectileEntity>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<Block> VORTEX_LENS = (Supplier<Block>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<BlockEntityType<VortexLensBlockEntity>> VORTEX_LENS_BLOCK_ENTITY = (Supplier<BlockEntityType<VortexLensBlockEntity>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<EntityType<MolewormEntity>> MOLEWORM = (Supplier<EntityType<MolewormEntity>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<EntityType<MantisEntity>> MANTIS = (Supplier<EntityType<MantisEntity>>) UNBOUND;
|
||||
@@ -611,6 +625,26 @@ public final class AntarchyObjects {
|
||||
LUCID = supplier;
|
||||
}
|
||||
|
||||
public static void setVortex(Supplier<EntityType<VortexEntity>> supplier) {
|
||||
VORTEX = supplier;
|
||||
}
|
||||
|
||||
public static void setWindVortex(Supplier<EntityType<WindVortexEntity>> supplier) {
|
||||
WIND_VORTEX = supplier;
|
||||
}
|
||||
|
||||
public static void setVortexChargeProjectile(Supplier<EntityType<VortexChargeProjectileEntity>> supplier) {
|
||||
VORTEX_CHARGE_PROJECTILE = supplier;
|
||||
}
|
||||
|
||||
public static void setVortexLens(Supplier<Block> supplier) {
|
||||
VORTEX_LENS = supplier;
|
||||
}
|
||||
|
||||
public static void setVortexLensBlockEntity(Supplier<BlockEntityType<VortexLensBlockEntity>> supplier) {
|
||||
VORTEX_LENS_BLOCK_ENTITY = supplier;
|
||||
}
|
||||
|
||||
public static void setLotus(Supplier<Block> supplier) {
|
||||
LOTUS = supplier;
|
||||
}
|
||||
|
||||
+16
-1
@@ -173,6 +173,11 @@ public final class AntarchySoundEvents {
|
||||
public static Supplier<SoundEvent> JERRY_ADULT_HURT = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> JERRY_ADULT_DEATH = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> JERRY_ADULT_ATTACK = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> WORM_HOOK_FLYING = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> BLOOD_CRYSTAL_KATANA_DASH = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> BLOOD_CRYSTAL_ARMOR_EQUIP = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> BLOODGLASS_WARD_HEART_BREAK = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> BLOODGLASS_WARD_HEART_REGEN = (Supplier<SoundEvent>) UNBOUND;
|
||||
|
||||
private AntarchySoundEvents() {
|
||||
}
|
||||
@@ -341,7 +346,12 @@ public final class AntarchySoundEvents {
|
||||
Supplier<SoundEvent> jerryAdultIdle,
|
||||
Supplier<SoundEvent> jerryAdultHurt,
|
||||
Supplier<SoundEvent> jerryAdultDeath,
|
||||
Supplier<SoundEvent> jerryAdultAttack
|
||||
Supplier<SoundEvent> jerryAdultAttack,
|
||||
Supplier<SoundEvent> wormHookFlying,
|
||||
Supplier<SoundEvent> bloodCrystalKatanaDash,
|
||||
Supplier<SoundEvent> bloodCrystalArmorEquip,
|
||||
Supplier<SoundEvent> bloodglassWardHeartBreak,
|
||||
Supplier<SoundEvent> bloodglassWardHeartRegen
|
||||
) {
|
||||
SQUIDZOOKA_FIRE = squidzookaFire;
|
||||
SHRINK_RAY_CHARGE = shrinkRayCharge;
|
||||
@@ -507,5 +517,10 @@ public final class AntarchySoundEvents {
|
||||
JERRY_ADULT_HURT = jerryAdultHurt;
|
||||
JERRY_ADULT_DEATH = jerryAdultDeath;
|
||||
JERRY_ADULT_ATTACK = jerryAdultAttack;
|
||||
WORM_HOOK_FLYING = wormHookFlying;
|
||||
BLOOD_CRYSTAL_KATANA_DASH = bloodCrystalKatanaDash;
|
||||
BLOOD_CRYSTAL_ARMOR_EQUIP = bloodCrystalArmorEquip;
|
||||
BLOODGLASS_WARD_HEART_BREAK = bloodglassWardHeartBreak;
|
||||
BLOODGLASS_WARD_HEART_REGEN = bloodglassWardHeartRegen;
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,7 @@ public final class AntarchyTags {
|
||||
public static final TagKey<EntityType<?>> GRAVITY_GUN_BLACKLIST = TagKey.create(Registries.ENTITY_TYPE, id("gravity_gun_blacklist"));
|
||||
public static final TagKey<EntityType<?>> INVERTED_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("inverted_immune"));
|
||||
public static final TagKey<EntityType<?>> LUCID_BOLT_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("lucid_bolt_immune"));
|
||||
public static final TagKey<EntityType<?>> WIND_VORTEX_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("wind_vortex_immune"));
|
||||
public static final TagKey<EntityType<?>> DUCT_TAPE_STICK_BLACKLIST = TagKey.create(Registries.ENTITY_TYPE, id("duct_tape_stick_blacklist"));
|
||||
public static final TagKey<EntityType<?>> NIGHTMARE_NO_ATTACK = TagKey.create(Registries.ENTITY_TYPE, id("nightmare_no_attack"));
|
||||
public static final TagKey<EntityType<?>> SIZE_CHANGING_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("size_changing_immune"));
|
||||
|
||||
+31
@@ -1,9 +1,14 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.UpwardFallingBlockEntity;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
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.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.FallingBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
@@ -25,4 +30,30 @@ public class DreamSandBlock extends FallingBlock {
|
||||
public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
|
||||
entity.causeFallDamage(fallDistance, 0.0F, level.damageSources().fall());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||
if (!level.isClientSide) {
|
||||
level.scheduleTick(pos, this, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
|
||||
level.scheduleTick(pos, this, 2);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||
if (!level.getBlockState(pos).is(this)) {
|
||||
return;
|
||||
}
|
||||
BlockPos abovePos = pos.above();
|
||||
BlockState above = level.getBlockState(abovePos);
|
||||
boolean passable = above.isAir() || above.getCollisionShape(level, abovePos).isEmpty();
|
||||
if (passable) {
|
||||
UpwardFallingBlockEntity.fallUp(level, pos, state, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.GrowingPlantHeadBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class SpiralingVinesBlock extends GrowingPlantHeadBlock {
|
||||
public static final MapCodec<SpiralingVinesBlock> CODEC = simpleCodec(SpiralingVinesBlock::new);
|
||||
public static final VoxelShape SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 16.0D, 12.0D);
|
||||
public static Supplier<Block> BODY_BLOCK;
|
||||
|
||||
public SpiralingVinesBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties, Direction.UP, SHAPE, false, 0.1D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<SpiralingVinesBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBlocksToGrowWhenBonemealed(RandomSource random) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canGrowInto(BlockState state) {
|
||||
return state.isAir();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Block getBodyBlock() {
|
||||
return BODY_BLOCK.get();
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.GrowingPlantBodyBlock;
|
||||
import net.minecraft.world.level.block.GrowingPlantHeadBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
|
||||
public class SpiralingVinesPlantBlock extends GrowingPlantBodyBlock {
|
||||
public static final MapCodec<SpiralingVinesPlantBlock> CODEC = simpleCodec(SpiralingVinesPlantBlock::new);
|
||||
public static Supplier<GrowingPlantHeadBlock> HEAD_BLOCK;
|
||||
|
||||
public SpiralingVinesPlantBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties, Direction.UP, SpiralingVinesBlock.SHAPE, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<SpiralingVinesPlantBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrowingPlantHeadBlock getHeadBlock() {
|
||||
return HEAD_BLOCK.get();
|
||||
}
|
||||
}
|
||||
+7
@@ -1,6 +1,7 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.advancement.AntarchyAdvancements;
|
||||
import com.craisinlord.antarchy.content.worldgen.truffalo.TruffaloTreeGrowers;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -9,6 +10,7 @@ import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
@@ -22,11 +24,13 @@ import net.minecraft.world.level.block.BushBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class TruffaloSaplingBlock extends BushBlock implements BonemealableBlock {
|
||||
public static final MapCodec<TruffaloSaplingBlock> CODEC = Block.simpleCodec(TruffaloSaplingBlock::new);
|
||||
private static final ResourceLocation LET_IT_GROW_ADVANCEMENT = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "let_it_grow");
|
||||
private static final TagKey<Block> SUPPORTS = TagKey.create(
|
||||
Registries.BLOCK,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "truffalo_sapling_supports")
|
||||
@@ -102,6 +106,9 @@ public class TruffaloSaplingBlock extends BushBlock implements BonemealableBlock
|
||||
|
||||
level.removeBlock(pos, false);
|
||||
if (feature.value().place(level, level.getChunkSource().getGenerator(), random, pos)) {
|
||||
for (ServerPlayer player : level.getEntitiesOfClass(ServerPlayer.class, new AABB(pos).inflate(8.0D))) {
|
||||
AntarchyAdvancements.award(player, LET_IT_GROW_ADVANCEMENT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.UpwardFallingBlockEntity;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
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.entity.item.FallingBlockEntity;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.PointedDripstoneBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.DripstoneThickness;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
public class TyphoniteSpikeBlock extends PointedDripstoneBlock {
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static final MapCodec<PointedDripstoneBlock> CODEC = (MapCodec) Block.simpleCodec(TyphoniteSpikeBlock::new);
|
||||
|
||||
public TyphoniteSpikeBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<PointedDripstoneBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
LevelAccessor level = context.getLevel();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
Direction direction = calculateTipDirection(level, pos, context.getNearestLookingVerticalDirection().getOpposite());
|
||||
if (direction == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean mergeTips = !context.isSecondaryUseActive();
|
||||
DripstoneThickness thickness = calculateDripstoneThickness(level, pos, direction, mergeTips);
|
||||
if (thickness == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.defaultBlockState()
|
||||
.setValue(TIP_DIRECTION, direction)
|
||||
.setValue(THICKNESS, thickness)
|
||||
.setValue(WATERLOGGED, level.getFluidState(pos).getType() == Fluids.WATER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState updateShape(
|
||||
BlockState state,
|
||||
Direction direction,
|
||||
BlockState neighborState,
|
||||
LevelAccessor level,
|
||||
BlockPos pos,
|
||||
BlockPos neighborPos
|
||||
) {
|
||||
if (state.getValue(WATERLOGGED)) {
|
||||
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
|
||||
}
|
||||
|
||||
if (direction != Direction.UP && direction != Direction.DOWN) {
|
||||
return state;
|
||||
}
|
||||
|
||||
Direction tipDirection = state.getValue(TIP_DIRECTION);
|
||||
if (tipDirection == Direction.DOWN && level.getBlockTicks().hasScheduledTick(pos, this)) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (direction == tipDirection.getOpposite() && !this.canSurvive(state, level, pos)) {
|
||||
if (tipDirection == Direction.DOWN) {
|
||||
level.scheduleTick(pos, this, 2);
|
||||
} else {
|
||||
level.scheduleTick(pos, this, 1);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
boolean mergeTips = state.getValue(THICKNESS) == DripstoneThickness.TIP_MERGE;
|
||||
return state.setValue(THICKNESS, calculateDripstoneThickness(level, pos, tipDirection, mergeTips));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
|
||||
return isValidPointedDripstonePlacement(level, pos, state.getValue(TIP_DIRECTION));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||
if (this.canSurvive(state, level, pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.getValue(TIP_DIRECTION) == Direction.DOWN) {
|
||||
BlockPos.MutableBlockPos root = pos.mutable();
|
||||
while (isTyphoniteSpikeWithDirection(level.getBlockState(root.above()), Direction.DOWN)) {
|
||||
root.move(Direction.UP);
|
||||
}
|
||||
|
||||
BlockPos.MutableBlockPos cursor = root.mutable();
|
||||
while (isTyphoniteSpikeWithDirection(level.getBlockState(cursor), Direction.DOWN)) {
|
||||
BlockState fallingState = level.getBlockState(cursor);
|
||||
if (isTyphoniteSpikeWithDirection(fallingState, Direction.DOWN)) {
|
||||
FallingBlockEntity.fall(level, cursor, fallingState);
|
||||
}
|
||||
cursor.move(Direction.DOWN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos.MutableBlockPos cursor = pos.mutable();
|
||||
while (isTyphoniteSpikeWithDirection(level.getBlockState(cursor), Direction.UP)) {
|
||||
BlockState spikeState = level.getBlockState(cursor);
|
||||
UpwardFallingBlockEntity.fallUp(level, cursor, spikeState);
|
||||
cursor.move(Direction.UP);
|
||||
}
|
||||
}
|
||||
|
||||
private static Direction calculateTipDirection(LevelReader level, BlockPos pos, Direction preferredDirection) {
|
||||
if (isValidPointedDripstonePlacement(level, pos, preferredDirection)) {
|
||||
return preferredDirection;
|
||||
}
|
||||
|
||||
Direction opposite = preferredDirection.getOpposite();
|
||||
return isValidPointedDripstonePlacement(level, pos, opposite) ? opposite : null;
|
||||
}
|
||||
|
||||
private static DripstoneThickness calculateDripstoneThickness(LevelReader level, BlockPos pos, Direction direction, boolean mergeTips) {
|
||||
Direction opposite = direction.getOpposite();
|
||||
BlockState forwardState = level.getBlockState(pos.relative(direction));
|
||||
if (isTyphoniteSpikeWithDirection(forwardState, opposite)) {
|
||||
return !mergeTips && forwardState.getValue(THICKNESS) != DripstoneThickness.TIP_MERGE
|
||||
? DripstoneThickness.TIP
|
||||
: DripstoneThickness.TIP_MERGE;
|
||||
}
|
||||
|
||||
if (!isTyphoniteSpikeWithDirection(forwardState, direction)) {
|
||||
return DripstoneThickness.TIP;
|
||||
}
|
||||
|
||||
DripstoneThickness forwardThickness = forwardState.getValue(THICKNESS);
|
||||
if (forwardThickness != DripstoneThickness.TIP && forwardThickness != DripstoneThickness.TIP_MERGE) {
|
||||
BlockState backState = level.getBlockState(pos.relative(opposite));
|
||||
return !isTyphoniteSpikeWithDirection(backState, direction) ? DripstoneThickness.BASE : DripstoneThickness.MIDDLE;
|
||||
}
|
||||
|
||||
return DripstoneThickness.FRUSTUM;
|
||||
}
|
||||
|
||||
private static boolean isValidPointedDripstonePlacement(LevelReader level, BlockPos pos, Direction direction) {
|
||||
BlockPos supportPos = pos.relative(direction.getOpposite());
|
||||
BlockState supportState = level.getBlockState(supportPos);
|
||||
return supportState.isFaceSturdy(level, supportPos, direction) || isTyphoniteSpikeWithDirection(supportState, direction);
|
||||
}
|
||||
|
||||
private static boolean isTyphoniteSpikeWithDirection(BlockState state, Direction direction) {
|
||||
return state.getBlock() instanceof TyphoniteSpikeBlock && state.getValue(TIP_DIRECTION) == direction;
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.craisinlord.antarchy.content.block.entity.VortexLensBlockEntity;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
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.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class VortexLensBlock extends BaseEntityBlock {
|
||||
public static final DirectionProperty FACING = BlockStateProperties.FACING;
|
||||
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||||
|
||||
private final Supplier<? extends BlockEntityType<VortexLensBlockEntity>> blockEntityTypeSupplier;
|
||||
private final MapCodec<VortexLensBlock> codec;
|
||||
|
||||
public VortexLensBlock(Supplier<? extends BlockEntityType<VortexLensBlockEntity>> blockEntityTypeSupplier,
|
||||
BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
this.blockEntityTypeSupplier = blockEntityTypeSupplier;
|
||||
this.codec = Block.simpleCodec(ignored -> this);
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.UP).setValue(POWERED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return this.codec;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING, POWERED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState()
|
||||
.setValue(FACING, context.getClickedFace())
|
||||
.setValue(POWERED, hasAnySignal(context.getLevel(), context.getClickedPos()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos,
|
||||
boolean movedByPiston) {
|
||||
if (!level.isClientSide && level.getBlockEntity(pos) instanceof VortexLensBlockEntity lens) {
|
||||
lens.refreshImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RenderShape getRenderShape(BlockState state) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new VortexLensBlockEntity(pos, state, this.blockEntityTypeSupplier);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state,
|
||||
BlockEntityType<T> blockEntityType) {
|
||||
if (level.isClientSide) {
|
||||
return null;
|
||||
}
|
||||
return createTickerHelper(blockEntityType, this.blockEntityTypeSupplier.get(), (tickLevel, tickPos, tickState, blockEntity) -> {
|
||||
if (tickLevel instanceof net.minecraft.server.level.ServerLevel serverLevel) {
|
||||
VortexLensBlockEntity.serverTick(serverLevel, tickPos, tickState, blockEntity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
if (!state.is(newState.getBlock()) && level.getBlockEntity(pos) instanceof VortexLensBlockEntity lens) {
|
||||
lens.removeActiveVortex();
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||
return state.rotate(mirror.getRotation(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
private static boolean hasAnySignal(Level level, BlockPos pos) {
|
||||
return level.getBestNeighborSignal(pos) > 0 || BluestoneSignalHelper.getBestNeighborSignal(level, pos) > 0;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.BushBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class WhirlflowerBlock extends BushBlock {
|
||||
public static final MapCodec<WhirlflowerBlock> CODEC = Block.simpleCodec(WhirlflowerBlock::new);
|
||||
private static final VoxelShape SHAPE = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 13.0D, 13.0D);
|
||||
private static final ResourceLocation VEINED_TYPHONITE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "veined_typhonite");
|
||||
|
||||
public WhirlflowerBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<WhirlflowerBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
|
||||
return SHAPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) {
|
||||
return BuiltInRegistries.BLOCK.getKey(state.getBlock()).equals(VEINED_TYPHONITE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
|
||||
return this.mayPlaceOn(level.getBlockState(pos.below()), level, pos.below());
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
package com.craisinlord.antarchy.content.block.entity;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.block.BluestoneSignalHelper;
|
||||
import com.craisinlord.antarchy.content.block.VortexLensBlock;
|
||||
import com.craisinlord.antarchy.content.entity.vortex.WindVortexEntity;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class VortexLensBlockEntity extends BlockEntity {
|
||||
private static final String ACTIVE_VORTEX_KEY = "ActiveVortex";
|
||||
private static final int LENS_VORTEX_REFRESH_DURATION = 40;
|
||||
|
||||
@Nullable
|
||||
private UUID activeVortexUuid;
|
||||
private boolean refreshNow = true;
|
||||
|
||||
public VortexLensBlockEntity(BlockPos pos, BlockState state,
|
||||
Supplier<? extends BlockEntityType<VortexLensBlockEntity>> typeSupplier) {
|
||||
super(typeSupplier.get(), pos, state);
|
||||
}
|
||||
|
||||
public static void serverTick(ServerLevel level, BlockPos pos, BlockState state, VortexLensBlockEntity blockEntity) {
|
||||
blockEntity.tickLens(level, pos, state);
|
||||
}
|
||||
|
||||
public void refreshImmediately() {
|
||||
this.refreshNow = true;
|
||||
}
|
||||
|
||||
public void removeActiveVortex() {
|
||||
if (this.level instanceof ServerLevel serverLevel) {
|
||||
WindVortexEntity vortex = this.getActiveVortex(serverLevel);
|
||||
if (vortex != null) {
|
||||
vortex.removeFromLens();
|
||||
}
|
||||
}
|
||||
this.activeVortexUuid = null;
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
private void tickLens(ServerLevel level, BlockPos pos, BlockState state) {
|
||||
if (!this.refreshNow && (level.getGameTime() & 1L) == 1L) {
|
||||
return;
|
||||
}
|
||||
this.refreshNow = false;
|
||||
|
||||
int bluestoneSignal = BluestoneSignalHelper.getBestNeighborSignal(level, pos);
|
||||
int redstoneSignal = level.getBestNeighborSignal(pos);
|
||||
boolean pushMode = bluestoneSignal > 0;
|
||||
int signal = pushMode ? bluestoneSignal : redstoneSignal;
|
||||
|
||||
if (signal <= 0) {
|
||||
this.removeActiveVortex();
|
||||
this.updatePoweredState(level, pos, state, false);
|
||||
return;
|
||||
}
|
||||
|
||||
WindVortexEntity vortex = this.getOrCreateVortex(level, pos, state);
|
||||
if (vortex == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Direction facing = state.getValue(VortexLensBlock.FACING);
|
||||
double signalScale = Mth.clamp(signal / 15.0D, 0.0D, 1.0D);
|
||||
double radius = Mth.lerp(signalScale, AntarchySettings.vortexLensMinRadius(), AntarchySettings.vortexLensMaxRadius());
|
||||
double height = Mth.lerp(signalScale, AntarchySettings.vortexLensMinHeight(), AntarchySettings.vortexLensMaxHeight());
|
||||
Vec3 axis = Vec3.atLowerCornerOf(facing.getNormal());
|
||||
Vec3 origin = Vec3.atCenterOf(pos).add(axis.scale(0.65D));
|
||||
WindVortexEntity.VortexMode mode = pushMode ? WindVortexEntity.VortexMode.LENS_PUSH : WindVortexEntity.VortexMode.LENS_PULL;
|
||||
double strength = pushMode ? AntarchySettings.vortexLensPushStrength() : AntarchySettings.vortexLensPullStrength();
|
||||
|
||||
vortex.setPos(origin.x, origin.y, origin.z);
|
||||
vortex.setDeltaMovement(Vec3.ZERO);
|
||||
vortex.setAxis(facing);
|
||||
vortex.setMode(mode);
|
||||
vortex.setVortexSize((float) height, (float) radius);
|
||||
vortex.setVortexDurationTicks(LENS_VORTEX_REFRESH_DURATION);
|
||||
vortex.resetVortexAge();
|
||||
vortex.setVortexStrengths(strength, AntarchySettings.vortexLensLaunchStrength());
|
||||
vortex.setDamaging(false);
|
||||
this.updatePoweredState(level, pos, state, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private WindVortexEntity getOrCreateVortex(ServerLevel level, BlockPos pos, BlockState state) {
|
||||
WindVortexEntity vortex = this.getActiveVortex(level);
|
||||
if (vortex != null) {
|
||||
return vortex;
|
||||
}
|
||||
|
||||
Direction facing = state.getValue(VortexLensBlock.FACING);
|
||||
Vec3 axis = Vec3.atLowerCornerOf(facing.getNormal());
|
||||
Vec3 origin = Vec3.atCenterOf(pos).add(axis.scale(0.65D));
|
||||
vortex = WindVortexEntity.create(level, AntarchyObjects.WIND_VORTEX.get(), origin, Vec3.ZERO, null, false);
|
||||
vortex.setAxis(facing);
|
||||
vortex.setMode(WindVortexEntity.VortexMode.LENS_PULL);
|
||||
vortex.setVortexDurationTicks(LENS_VORTEX_REFRESH_DURATION);
|
||||
vortex.resetVortexAge();
|
||||
level.addFreshEntity(vortex);
|
||||
this.activeVortexUuid = vortex.getUUID();
|
||||
this.setChanged();
|
||||
return vortex;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private WindVortexEntity getActiveVortex(ServerLevel level) {
|
||||
if (this.activeVortexUuid == null) {
|
||||
return null;
|
||||
}
|
||||
Entity entity = level.getEntity(this.activeVortexUuid);
|
||||
if (entity instanceof WindVortexEntity vortex && vortex.isAlive()) {
|
||||
return vortex;
|
||||
}
|
||||
this.activeVortexUuid = null;
|
||||
this.setChanged();
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updatePoweredState(ServerLevel level, BlockPos pos, BlockState state, boolean powered) {
|
||||
if (state.getBlock() instanceof VortexLensBlock && state.getValue(VortexLensBlock.POWERED) != powered) {
|
||||
level.setBlock(pos, state.setValue(VortexLensBlock.POWERED, powered), Block.UPDATE_CLIENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
if (this.activeVortexUuid != null) {
|
||||
tag.putUUID(ACTIVE_VORTEX_KEY, this.activeVortexUuid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
this.activeVortexUuid = tag.hasUUID(ACTIVE_VORTEX_KEY) ? tag.getUUID(ACTIVE_VORTEX_KEY) : null;
|
||||
}
|
||||
}
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
package com.craisinlord.antarchy.content.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.HoverboardEntity;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferUploader;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.MeshData;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class HoverboardTrailSystem {
|
||||
private static final int MAX_TRAIL_POINTS = 18;
|
||||
private static final int TRAIL_LIFETIME_TICKS = 12;
|
||||
private static final float CORE_HALF_WIDTH = 0.0225f;
|
||||
private static final float GLOW_HALF_WIDTH = 0.055f;
|
||||
private static final double MIN_DISTANCE_BETWEEN_POINTS = 0.04D;
|
||||
private static final double LATERAL_OFFSET = 0.34D;
|
||||
private static final double REAR_OFFSET = 0.52D;
|
||||
private static final double HEIGHT_OFFSET = 0.14D;
|
||||
private static final float[] DEFAULT_COLOR = rgb(0xC9A0FF);
|
||||
|
||||
private static final Map<Integer, BoardTrails> TRAILS = new HashMap<>();
|
||||
|
||||
private HoverboardTrailSystem() {
|
||||
}
|
||||
|
||||
private static final class TrailPoint {
|
||||
final Vec3 pos;
|
||||
int age;
|
||||
|
||||
TrailPoint(Vec3 pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
float progress() {
|
||||
return (float) this.age / (float) TRAIL_LIFETIME_TICKS;
|
||||
}
|
||||
|
||||
boolean expired() {
|
||||
return this.age >= TRAIL_LIFETIME_TICKS;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class BoardTrails {
|
||||
final ArrayDeque<TrailPoint> left = new ArrayDeque<>();
|
||||
final ArrayDeque<TrailPoint> right = new ArrayDeque<>();
|
||||
float[] color = DEFAULT_COLOR;
|
||||
}
|
||||
|
||||
public static void tick() {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.level == null) {
|
||||
TRAILS.clear();
|
||||
return;
|
||||
}
|
||||
if (mc.isPaused()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<Integer> activeIds = new HashSet<>();
|
||||
for (Entity entity : mc.level.entitiesForRendering()) {
|
||||
if (!(entity instanceof HoverboardEntity hoverboard)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int id = hoverboard.getId();
|
||||
activeIds.add(id);
|
||||
BoardTrails boardTrails = TRAILS.computeIfAbsent(id, ignored -> new BoardTrails());
|
||||
boardTrails.color = colorFor(hoverboard.getColor());
|
||||
|
||||
if (hoverboard.isVehicle() && hoverboard.isTrailActive()) {
|
||||
TrailAnchors anchors = trailAnchors(hoverboard);
|
||||
addPoint(boardTrails.left, anchors.left());
|
||||
addPoint(boardTrails.right, anchors.right());
|
||||
}
|
||||
|
||||
age(boardTrails.left);
|
||||
age(boardTrails.right);
|
||||
if (boardTrails.left.isEmpty() && boardTrails.right.isEmpty() && !hoverboard.isTrailActive()) {
|
||||
TRAILS.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
TRAILS.keySet().removeIf(id -> !activeIds.contains(id));
|
||||
}
|
||||
|
||||
public static void render(Camera camera, Matrix4f mat) {
|
||||
if (TRAILS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.level == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 camPos = camera.getPosition();
|
||||
List<TrailSnapshot> snapshots = new ArrayList<>(TRAILS.size() * 2);
|
||||
for (BoardTrails boardTrails : TRAILS.values()) {
|
||||
if (boardTrails.left.size() >= 2) {
|
||||
snapshots.add(new TrailSnapshot(new ArrayList<>(boardTrails.left), boardTrails.color));
|
||||
}
|
||||
if (boardTrails.right.size() >= 2) {
|
||||
snapshots.add(new TrailSnapshot(new ArrayList<>(boardTrails.right), boardTrails.color));
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshots.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.depthMask(false);
|
||||
RenderSystem.disableCull();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
|
||||
Tesselator tesselator = Tesselator.getInstance();
|
||||
|
||||
BufferBuilder glowBuf = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
for (TrailSnapshot snapshot : snapshots) {
|
||||
buildPass(glowBuf, mat, snapshot.points(), snapshot.color(), camPos, true);
|
||||
}
|
||||
MeshData glowMesh = glowBuf.build();
|
||||
if (glowMesh != null) {
|
||||
BufferUploader.drawWithShader(glowMesh);
|
||||
}
|
||||
|
||||
BufferBuilder coreBuf = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
for (TrailSnapshot snapshot : snapshots) {
|
||||
buildPass(coreBuf, mat, snapshot.points(), snapshot.color(), camPos, false);
|
||||
}
|
||||
MeshData coreMesh = coreBuf.build();
|
||||
if (coreMesh != null) {
|
||||
BufferUploader.drawWithShader(coreMesh);
|
||||
}
|
||||
|
||||
RenderSystem.enableCull();
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
private static void addPoint(ArrayDeque<TrailPoint> points, Vec3 pos) {
|
||||
if (points.isEmpty()) {
|
||||
points.addFirst(new TrailPoint(pos));
|
||||
return;
|
||||
}
|
||||
if (points.peekFirst().pos.distanceToSqr(pos) < MIN_DISTANCE_BETWEEN_POINTS * MIN_DISTANCE_BETWEEN_POINTS) {
|
||||
return;
|
||||
}
|
||||
points.addFirst(new TrailPoint(pos));
|
||||
while (points.size() > MAX_TRAIL_POINTS) {
|
||||
points.pollLast();
|
||||
}
|
||||
}
|
||||
|
||||
private static void age(ArrayDeque<TrailPoint> points) {
|
||||
Iterator<TrailPoint> iterator = points.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
TrailPoint point = iterator.next();
|
||||
point.age++;
|
||||
if (point.expired()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TrailAnchors trailAnchors(HoverboardEntity hoverboard) {
|
||||
float yawRad = hoverboard.getYRot() * Mth.DEG_TO_RAD;
|
||||
Vec3 forward = new Vec3(-Mth.sin(yawRad), 0.0D, Mth.cos(yawRad));
|
||||
if (forward.lengthSqr() < 1.0E-6D) {
|
||||
forward = new Vec3(0.0D, 0.0D, 1.0D);
|
||||
}
|
||||
forward = forward.normalize();
|
||||
Vec3 right = new Vec3(forward.z, 0.0D, -forward.x);
|
||||
Vec3 center = hoverboard.position().add(0.0D, HEIGHT_OFFSET, 0.0D).subtract(forward.scale(REAR_OFFSET));
|
||||
return new TrailAnchors(center.subtract(right.scale(LATERAL_OFFSET)), center.add(right.scale(LATERAL_OFFSET)));
|
||||
}
|
||||
|
||||
private static void buildPass(BufferBuilder buf, Matrix4f mat, List<TrailPoint> points, float[] color, Vec3 camPos, boolean glow) {
|
||||
int n = points.size();
|
||||
for (int i = 0; i < n - 1; i++) {
|
||||
TrailPoint newer = points.get(i);
|
||||
TrailPoint older = points.get(i + 1);
|
||||
|
||||
float alphaNearer = (glow ? 0.34f : 0.78f) * indexAlpha(i, n) * (1.0f - newer.progress());
|
||||
float alphaFarther = (glow ? 0.34f : 0.78f) * indexAlpha(i + 1, n) * (1.0f - older.progress());
|
||||
if (alphaNearer < 0.005f && alphaFarther < 0.005f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vec3 right = cameraFacingRight(newer.pos, older.pos, camPos);
|
||||
if (right == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
right = right.scale(glow ? GLOW_HALF_WIDTH : CORE_HALF_WIDTH);
|
||||
Vec3 na = newer.pos.subtract(camPos);
|
||||
Vec3 nb = older.pos.subtract(camPos);
|
||||
|
||||
buf.addVertex(mat, (float) (na.x + right.x), (float) (na.y + right.y), (float) (na.z + right.z)).setColor(color[0], color[1], color[2], alphaNearer);
|
||||
buf.addVertex(mat, (float) (na.x - right.x), (float) (na.y - right.y), (float) (na.z - right.z)).setColor(color[0], color[1], color[2], alphaNearer);
|
||||
buf.addVertex(mat, (float) (nb.x - right.x), (float) (nb.y - right.y), (float) (nb.z - right.z)).setColor(color[0], color[1], color[2], alphaFarther);
|
||||
buf.addVertex(mat, (float) (nb.x + right.x), (float) (nb.y + right.y), (float) (nb.z + right.z)).setColor(color[0], color[1], color[2], alphaFarther);
|
||||
}
|
||||
}
|
||||
|
||||
private static Vec3 cameraFacingRight(Vec3 a, Vec3 b, Vec3 camPos) {
|
||||
Vec3 segDir = b.subtract(a);
|
||||
if (segDir.lengthSqr() < 1.0E-12D) {
|
||||
return null;
|
||||
}
|
||||
segDir = segDir.normalize();
|
||||
Vec3 mid = a.add(b).scale(0.5D);
|
||||
Vec3 toCamera = camPos.subtract(mid);
|
||||
if (toCamera.lengthSqr() < 1.0E-12D) {
|
||||
return null;
|
||||
}
|
||||
toCamera = toCamera.normalize();
|
||||
Vec3 right = segDir.cross(toCamera);
|
||||
if (right.lengthSqr() < 1.0E-10D) {
|
||||
right = segDir.cross(new Vec3(0.0D, 1.0D, 0.0D));
|
||||
if (right.lengthSqr() < 1.0E-10D) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return right.normalize();
|
||||
}
|
||||
|
||||
private static float indexAlpha(int i, int n) {
|
||||
if (n <= 1) {
|
||||
return 1.0f;
|
||||
}
|
||||
return 1.0f - (float) i / (float) (n - 1);
|
||||
}
|
||||
|
||||
private static float[] colorFor(DyeColor color) {
|
||||
if (color == null) {
|
||||
return DEFAULT_COLOR;
|
||||
}
|
||||
return rgb(color.getTextureDiffuseColor());
|
||||
}
|
||||
|
||||
private static float[] rgb(int color) {
|
||||
return new float[] {
|
||||
((color >> 16) & 255) / 255.0f,
|
||||
((color >> 8) & 255) / 255.0f,
|
||||
(color & 255) / 255.0f
|
||||
};
|
||||
}
|
||||
|
||||
private record TrailAnchors(Vec3 left, Vec3 right) {
|
||||
}
|
||||
|
||||
private record TrailSnapshot(List<TrailPoint> points, float[] color) {
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.craisinlord.antarchy.content.client.model;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.entity.vortex.VortexEntity;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
public class VortexModel extends GeoModel<VortexEntity> {
|
||||
@Override
|
||||
public ResourceLocation getModelResource(VortexEntity animatable) {
|
||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/vortex.geo.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureResource(VortexEntity animatable) {
|
||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/vortex.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAnimationResource(VortexEntity animatable) {
|
||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/vortex.animation.json");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -60,7 +60,7 @@ public final class ThoraxisUndersideSkyRenderer {
|
||||
VertexBuffer skyBuffer
|
||||
) {
|
||||
setupFog.run();
|
||||
if (isFoggy || minecraft.options.hideLightningFlash().get() || minecraft.gameRenderer.getMainCamera() != camera) {
|
||||
if (minecraft.options.hideLightningFlash().get() || minecraft.gameRenderer.getMainCamera() != camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.model.VortexModel;
|
||||
import com.craisinlord.antarchy.content.entity.vortex.VortexEntity;
|
||||
import software.bernie.geckolib.renderer.GeoEntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
|
||||
public class VortexRenderer extends GeoEntityRenderer<VortexEntity> {
|
||||
public VortexRenderer(EntityRendererProvider.Context context) {
|
||||
super(context, new VortexModel());
|
||||
this.shadowRadius = 0.5F;
|
||||
this.withScale(0.9F);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDeathMaxRotation(VortexEntity animatable) {
|
||||
return 0.0F;
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.vortex.WindVortexEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
public class WindVortexRenderer extends EntityRenderer<WindVortexEntity> {
|
||||
private static final int RINGS = 8;
|
||||
private static final int SEGMENTS_PER_RING = 9;
|
||||
private static final int ARC_STEPS = 4;
|
||||
private static final float BASE_RADIUS = 0.35F;
|
||||
|
||||
public WindVortexRenderer(EntityRendererProvider.Context context) {
|
||||
super(context);
|
||||
this.shadowRadius = 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(WindVortexEntity entity, float entityYaw, float partialTick, PoseStack poseStack,
|
||||
MultiBufferSource bufferSource, int packedLight) {
|
||||
VertexConsumer consumer = bufferSource.getBuffer(RenderType.lightning());
|
||||
Matrix4f pose = poseStack.last().pose();
|
||||
float height = entity.getVortexHeight();
|
||||
float topRadius = entity.getTopRadius();
|
||||
float age = entity.tickCount + partialTick;
|
||||
WindVortexEntity.Basis basis = entity.basis();
|
||||
boolean pull = entity.getMode() == WindVortexEntity.VortexMode.LENS_PULL;
|
||||
boolean push = entity.getMode() == WindVortexEntity.VortexMode.LENS_PUSH;
|
||||
float spinDirection = pull ? -1.0F : 1.0F;
|
||||
|
||||
for (int ring = 0; ring < RINGS; ring++) {
|
||||
float progress = (ring + 0.25F) / RINGS;
|
||||
float axisDistance = progress * height;
|
||||
float shapeProgress = pull ? 1.0F - progress : progress;
|
||||
float radius = Mth.lerp(shapeProgress, BASE_RADIUS, topRadius);
|
||||
float ringSpin = spinDirection * age * (0.13F + progress * 0.045F) + ring * 0.47F;
|
||||
float alpha = 1.0F;
|
||||
float thickness = 0.025F + radius * 0.012F;
|
||||
float arcLength = 0.34F + progress * 0.08F;
|
||||
int red = push ? 70 : 64;
|
||||
int green = push ? 220 : 255;
|
||||
int blue = push ? 255 : 56;
|
||||
|
||||
for (int segment = 0; segment < SEGMENTS_PER_RING; segment++) {
|
||||
float baseAngle = ringSpin + segment * Mth.TWO_PI / SEGMENTS_PER_RING;
|
||||
float start = baseAngle - arcLength * 0.5F;
|
||||
float end = baseAngle + arcLength * 0.5F;
|
||||
drawArc(consumer, pose, basis, radius, axisDistance, thickness, start, end, alpha, red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
super.render(entity, entityYaw, partialTick, poseStack, bufferSource, packedLight);
|
||||
}
|
||||
|
||||
private static void drawArc(VertexConsumer consumer, Matrix4f pose, WindVortexEntity.Basis basis, float radius,
|
||||
float axisDistance, float thickness, float start, float end, float alpha, int red, int green, int blue) {
|
||||
float previousAngle = start;
|
||||
for (int step = 1; step <= ARC_STEPS; step++) {
|
||||
float angle = Mth.lerp(step / (float) ARC_STEPS, start, end);
|
||||
addLineQuad(consumer, pose, basis, radius, axisDistance, thickness, previousAngle, angle, alpha, red, green, blue);
|
||||
previousAngle = angle;
|
||||
}
|
||||
}
|
||||
|
||||
private static void addLineQuad(VertexConsumer consumer, Matrix4f pose, WindVortexEntity.Basis basis, float radius,
|
||||
float axisDistance, float thickness, float startAngle, float endAngle, float alpha, int red, int green, int blue) {
|
||||
org.joml.Vector3f start = point(basis, radius, axisDistance, startAngle);
|
||||
org.joml.Vector3f end = point(basis, radius, axisDistance, endAngle);
|
||||
org.joml.Vector3f axisOffset = new org.joml.Vector3f((float) basis.axis.x, (float) basis.axis.y, (float) basis.axis.z).mul(thickness);
|
||||
float middleAngle = (startAngle + endAngle) * 0.5F;
|
||||
org.joml.Vector3f radialOffset = new org.joml.Vector3f(
|
||||
(float) (basis.sideA.x * Mth.cos(middleAngle) + basis.sideB.x * Mth.sin(middleAngle)),
|
||||
(float) (basis.sideA.y * Mth.cos(middleAngle) + basis.sideB.y * Mth.sin(middleAngle)),
|
||||
(float) (basis.sideA.z * Mth.cos(middleAngle) + basis.sideB.z * Mth.sin(middleAngle))
|
||||
).mul(thickness);
|
||||
int a = Mth.clamp((int) (alpha * 255.0F), 0, 255);
|
||||
|
||||
addQuad(consumer, pose, start, end, axisOffset, red, green, blue, a);
|
||||
addQuad(consumer, pose, start, end, radialOffset, red, green, blue, a);
|
||||
}
|
||||
|
||||
private static void addQuad(VertexConsumer consumer, Matrix4f pose, org.joml.Vector3f start,
|
||||
org.joml.Vector3f end, org.joml.Vector3f offset, int red, int green, int blue, int alpha) {
|
||||
addVertex(consumer, pose, start.x - offset.x, start.y - offset.y, start.z - offset.z, red, green, blue, alpha);
|
||||
addVertex(consumer, pose, end.x - offset.x, end.y - offset.y, end.z - offset.z, red, green, blue, alpha);
|
||||
addVertex(consumer, pose, end.x + offset.x, end.y + offset.y, end.z + offset.z, red, green, blue, alpha);
|
||||
addVertex(consumer, pose, start.x + offset.x, start.y + offset.y, start.z + offset.z, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
private static org.joml.Vector3f point(WindVortexEntity.Basis basis, float radius, float axisDistance, float angle) {
|
||||
double radialA = Mth.cos(angle) * radius;
|
||||
double radialB = Mth.sin(angle) * radius;
|
||||
double x = basis.axis.x * axisDistance + basis.sideA.x * radialA + basis.sideB.x * radialB;
|
||||
double y = basis.axis.y * axisDistance + basis.sideA.y * radialA + basis.sideB.y * radialB;
|
||||
double z = basis.axis.z * axisDistance + basis.sideA.z * radialA + basis.sideB.z * radialB;
|
||||
return new org.joml.Vector3f((float) x, (float) y, (float) z);
|
||||
}
|
||||
|
||||
private static void addVertex(VertexConsumer consumer, Matrix4f pose, float x, float y, float z,
|
||||
int red, int green, int blue, int alpha) {
|
||||
consumer.addVertex(pose, x, y, z).setColor(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(WindVortexEntity entity) {
|
||||
return ResourceLocation.withDefaultNamespace("textures/misc/unknown_pack.png");
|
||||
}
|
||||
}
|
||||
+20
-1
@@ -197,6 +197,23 @@ public final class CreativeTabContents {
|
||||
entry("smooth_dream_sandstone_stairs", "building_blocks"),
|
||||
entry("smooth_dream_sandstone_slab", "building_blocks"),
|
||||
entry("cut_dream_sandstone_slab", "building_blocks"),
|
||||
entry("typhonite", "building_blocks"),
|
||||
entry("typhonite_bricks", "building_blocks"),
|
||||
entry("chiseled_typhonite", "building_blocks"),
|
||||
entry("polished_typhonite", "building_blocks"),
|
||||
entry("veined_typhonite", "building_blocks"),
|
||||
entry("typhonite_spike", "building_blocks"),
|
||||
entry("typhonite_stairs", "building_blocks"),
|
||||
entry("typhonite_slab", "building_blocks"),
|
||||
entry("typhonite_wall", "building_blocks"),
|
||||
entry("typhonite_brick_stairs", "building_blocks"),
|
||||
entry("typhonite_brick_slab", "building_blocks"),
|
||||
entry("typhonite_brick_wall", "building_blocks"),
|
||||
entry("polished_typhonite_stairs", "building_blocks"),
|
||||
entry("polished_typhonite_slab", "building_blocks"),
|
||||
entry("polished_typhonite_wall", "building_blocks"),
|
||||
entry("spiraling_vines", "natural_blocks"),
|
||||
entry("whirlflower", "natural_blocks"),
|
||||
entry("antigravel", "natural_blocks"),
|
||||
entry("budding_blood_crystal", "building_blocks"),
|
||||
entry("blood_crystal_block", "building_blocks"),
|
||||
@@ -270,6 +287,7 @@ public final class CreativeTabContents {
|
||||
entry("uranium_bars", "building_blocks"),
|
||||
entry("uranium_bulb", "building_blocks"),
|
||||
entry("bluestone_block", "redstone_blocks"),
|
||||
entry("vortex_lens", "redstone_blocks"),
|
||||
entry("bluestone_repeater", "redstone_blocks"),
|
||||
entry("bluestone_comparator", "redstone_blocks"),
|
||||
entry("bluestone_torch", "redstone_blocks"),
|
||||
@@ -447,7 +465,7 @@ public final class CreativeTabContents {
|
||||
entry("brutalfly_wing", "ingredients"),
|
||||
entry("primordial_scute", "ingredients"),
|
||||
entry("triffid_goo", "ingredients"),
|
||||
entry("vortex_eye", "ingredients"),
|
||||
entry("vortex_charge", "ingredients"),
|
||||
entry("emperor_scorpion_stinger", "ingredients"),
|
||||
entry("kraken_tooth", "ingredients"),
|
||||
entry("kraken_tentacle", "ingredients"),
|
||||
@@ -524,6 +542,7 @@ public final class CreativeTabContents {
|
||||
entry("nightmare_spawn_egg", "spawn_eggs"),
|
||||
entry("bed_bug_spawn_egg", "spawn_eggs"),
|
||||
entry("lucid_spawn_egg", "spawn_eggs"),
|
||||
entry("vortex_spawn_egg", "spawn_eggs"),
|
||||
entry("scorpion_spawn_egg", "spawn_eggs"),
|
||||
entry("basilisk_spawn_egg", "spawn_eggs"),
|
||||
entry("emperor_scorpion_spawn_egg", "spawn_eggs"),
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.craisinlord.antarchy.content.dispenser;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.vortex.VortexChargeProjectileEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.dispenser.BlockSource;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import net.minecraft.world.level.block.entity.DispenserBlockEntity;
|
||||
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
|
||||
|
||||
public class VortexChargeDispenseBehavior extends DefaultDispenseItemBehavior {
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource source, ItemStack stack) {
|
||||
if (VortexChargeProjectileEntity.defaultItemSupplier == null) {
|
||||
return super.execute(source, stack);
|
||||
}
|
||||
|
||||
ServerLevel level = source.level();
|
||||
Direction direction = source.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos pos = source.pos().relative(direction);
|
||||
double x = pos.getX() + 0.5D;
|
||||
double y = pos.getY() + 0.5D;
|
||||
double z = pos.getZ() + 0.5D;
|
||||
|
||||
VortexChargeProjectileEntity projectile = new VortexChargeProjectileEntity(level, x, y, z);
|
||||
projectile.shoot(direction.getStepX(), direction.getStepY() + 0.1D, direction.getStepZ(), 1.5F, 1.0F);
|
||||
level.addFreshEntity(projectile);
|
||||
stack.shrink(1);
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playSound(BlockSource source) {
|
||||
source.level().levelEvent(1002, source.pos(), 0);
|
||||
}
|
||||
}
|
||||
+7
@@ -9,6 +9,7 @@ import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
|
||||
import com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
@@ -162,6 +163,9 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
||||
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty,
|
||||
MobSpawnType spawnReason, @Nullable net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.emperorScorpionHealth());
|
||||
if (ThoraxisUndersideManager.shouldSpawnInvertedOnDreamSand(level, this.blockPosition())) {
|
||||
ThoraxisUndersideManager.applyUndersideInversion(this);
|
||||
}
|
||||
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||
}
|
||||
|
||||
@@ -233,6 +237,9 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
||||
if (!level.getLevel().dimension().equals(THORAXIS_KEY)) {
|
||||
return false;
|
||||
}
|
||||
if (ThoraxisUndersideManager.shouldSpawnInvertedOnDreamSand(level, pos)) {
|
||||
return level.getDifficulty() != Difficulty.PEACEFUL;
|
||||
}
|
||||
return level.getDifficulty() != Difficulty.PEACEFUL
|
||||
&& Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
|
||||
}
|
||||
|
||||
+52
-11
@@ -1,6 +1,10 @@
|
||||
package com.craisinlord.antarchy.content.entity;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
|
||||
import com.craisinlord.antarchy.mixins.LivingEntityJumpingAccessor;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -41,13 +45,12 @@ import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
private static final EntityDataAccessor<Integer> COLOR = SynchedEntityData.defineId(HoverboardEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Boolean> TRAIL_ACTIVE = SynchedEntityData.defineId(HoverboardEntity.class, EntityDataSerializers.BOOLEAN);
|
||||
|
||||
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
||||
private static final RawAnimation MOVE_ANIM = RawAnimation.begin().thenLoop("move");
|
||||
|
||||
private static final double MAX_HOVER_HEIGHT = 5.0D;
|
||||
private static final double ACCELERATION = 0.08D;
|
||||
private static final double MAX_SPEED = 1.8D;
|
||||
private static final double ASCEND_SPEED = 0.15D;
|
||||
private static final double SETTLE_DESCEND_SPEED = 0.08D;
|
||||
private static final double DAMPING = 0.955D;
|
||||
@@ -88,6 +91,7 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
builder.define(COLOR, -1);
|
||||
builder.define(TRAIL_ACTIVE, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -100,6 +104,14 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
this.entityData.set(COLOR, color == null ? -1 : color.getId());
|
||||
}
|
||||
|
||||
public boolean isTrailActive() {
|
||||
return this.entityData.get(TRAIL_ACTIVE);
|
||||
}
|
||||
|
||||
private void setTrailActive(boolean active) {
|
||||
this.entityData.set(TRAIL_ACTIVE, active);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag tag) {
|
||||
super.addAdditionalSaveData(tag);
|
||||
@@ -142,7 +154,13 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
if (!this.hasPassenger(passenger)) {
|
||||
return;
|
||||
}
|
||||
moveFunction.accept(passenger, this.getX(), this.getY() + RIDER_Y_OFFSET, this.getZ());
|
||||
Vec3 riderOffset = AntarchyGravityRotationUtil.vecPlayerToWorld(
|
||||
0.0D,
|
||||
RIDER_Y_OFFSET,
|
||||
0.0D,
|
||||
AntarchyGravityApi.getGravityDirection(this)
|
||||
);
|
||||
moveFunction.accept(passenger, this.getX() + riderOffset.x, this.getY() + riderOffset.y, this.getZ() + riderOffset.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,15 +174,18 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
|
||||
Vec3 look = Vec3.directionFromRotation(0.0F, this.getYRot());
|
||||
float forward = rider.zza;
|
||||
this.setTrailActive(forward > 0.0F);
|
||||
boolean holdingJump = ((LivingEntityJumpingAccessor) rider).antarchy$isJumping();
|
||||
double verticalMotion = this.resolveVerticalMotion(holdingJump);
|
||||
double acceleration = AntarchySettings.hoverboardAcceleration();
|
||||
double maxSpeed = AntarchySettings.hoverboardMaxSpeed();
|
||||
|
||||
Vec3 currentHorizontal = new Vec3(this.getDeltaMovement().x, 0.0D, this.getDeltaMovement().z);
|
||||
Vec3 horizontalMotion = currentHorizontal.scale(DAMPING).add(look.scale(forward * ACCELERATION));
|
||||
Vec3 horizontalMotion = currentHorizontal.scale(DAMPING).add(look.scale(forward * acceleration));
|
||||
|
||||
double horizontalSpeed = horizontalMotion.horizontalDistance();
|
||||
if (horizontalSpeed > MAX_SPEED) {
|
||||
double scale = MAX_SPEED / horizontalSpeed;
|
||||
if (horizontalSpeed > maxSpeed) {
|
||||
double scale = maxSpeed / horizontalSpeed;
|
||||
horizontalMotion = new Vec3(horizontalMotion.x * scale, 0.0D, horizontalMotion.z * scale);
|
||||
}
|
||||
|
||||
@@ -173,6 +194,7 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setTrailActive(false);
|
||||
double verticalMotion = this.resolveVerticalMotion(false);
|
||||
Vec3 horizontalMotion = new Vec3(this.getDeltaMovement().x, 0.0D, this.getDeltaMovement().z).scale(DAMPING);
|
||||
this.setDeltaMovement(horizontalMotion.x, verticalMotion, horizontalMotion.z);
|
||||
@@ -180,20 +202,32 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
}
|
||||
|
||||
private double resolveVerticalMotion(boolean holdingJump) {
|
||||
double groundHeight = this.findGroundHeight();
|
||||
double maxY = groundHeight + MAX_HOVER_HEIGHT;
|
||||
|
||||
AntarchyGravityDirection gravityDirection = AntarchyGravityApi.getGravityDirection(this);
|
||||
double supportHeight = this.findSupportHeight(gravityDirection);
|
||||
if (!gravityDirection.isInverted()) {
|
||||
double maxY = supportHeight + MAX_HOVER_HEIGHT;
|
||||
if (this.getY() > maxY) {
|
||||
return -SETTLE_DESCEND_SPEED;
|
||||
}
|
||||
if (holdingJump) {
|
||||
return this.getY() >= maxY ? 0.0D : ASCEND_SPEED;
|
||||
}
|
||||
return this.getY() <= groundHeight ? 0.0D : -SETTLE_DESCEND_SPEED;
|
||||
return this.getY() <= supportHeight ? 0.0D : -SETTLE_DESCEND_SPEED;
|
||||
}
|
||||
|
||||
private double findGroundHeight() {
|
||||
double minY = supportHeight - MAX_HOVER_HEIGHT;
|
||||
if (this.getY() < minY) {
|
||||
return SETTLE_DESCEND_SPEED;
|
||||
}
|
||||
if (holdingJump) {
|
||||
return this.getY() <= minY ? 0.0D : -ASCEND_SPEED;
|
||||
}
|
||||
return this.getY() >= supportHeight ? 0.0D : SETTLE_DESCEND_SPEED;
|
||||
}
|
||||
|
||||
private double findSupportHeight(AntarchyGravityDirection gravityDirection) {
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()));
|
||||
if (!gravityDirection.isInverted()) {
|
||||
int minY = this.level().getMinBuildHeight();
|
||||
while (pos.getY() > minY && this.level().getBlockState(pos).isAir()) {
|
||||
pos.move(Direction.DOWN);
|
||||
@@ -201,6 +235,13 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
|
||||
return pos.getY() + 1.0D;
|
||||
}
|
||||
|
||||
int maxY = this.level().getMaxBuildHeight() - 1;
|
||||
while (pos.getY() < maxY && this.level().getBlockState(pos).isAir()) {
|
||||
pos.move(Direction.UP);
|
||||
}
|
||||
return this.level().getBlockState(pos).isAir() ? this.getY() : pos.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) {
|
||||
return false;
|
||||
|
||||
@@ -36,8 +36,6 @@ import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.level.pathfinder.PathType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import software.bernie.geckolib.animatable.GeoEntity;
|
||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.animation.AnimatableManager;
|
||||
@@ -50,7 +48,6 @@ import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class MantisEntity extends Monster implements GeoEntity {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MantisEntity.class);
|
||||
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
||||
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
|
||||
private static final RawAnimation FLY_ANIM = RawAnimation.begin().thenLoop("fly");
|
||||
@@ -87,7 +84,6 @@ public class MantisEntity extends Monster implements GeoEntity {
|
||||
protected float committedAttackYaw;
|
||||
protected boolean attackDamageApplied;
|
||||
protected boolean attackStartedInFlight;
|
||||
private int debugLogTicks = 0;
|
||||
private int configSyncTicks;
|
||||
|
||||
public MantisEntity(EntityType<? extends MantisEntity> entityType, Level level) {
|
||||
@@ -275,7 +271,6 @@ public class MantisEntity extends Monster implements GeoEntity {
|
||||
|
||||
this.setNoGravity(this.isFlyingNow());
|
||||
this.updateAnimationState();
|
||||
this.tickDebugLog();
|
||||
}
|
||||
|
||||
this.updateFlightRotation();
|
||||
@@ -574,27 +569,6 @@ public class MantisEntity extends Monster implements GeoEntity {
|
||||
this.setHealth(syncedHealth);
|
||||
}
|
||||
|
||||
private void tickDebugLog() {
|
||||
if (++this.debugLogTicks < 100) {
|
||||
return;
|
||||
}
|
||||
this.debugLogTicks = 0;
|
||||
LivingEntity target = this.getTarget();
|
||||
int animState = this.getAnimationState();
|
||||
LOGGER.debug(
|
||||
"[Mantis id={}] pos={},{},{} target={} anim={} attackTicks={} flyBurst={} flyCooldown={} onGround={} navDone={}",
|
||||
this.getId(),
|
||||
(int) this.getX(), (int) this.getY(), (int) this.getZ(),
|
||||
target != null ? target.getName().getString() : "none",
|
||||
animState,
|
||||
this.attackAnimationTicks,
|
||||
this.flyBurstTicks,
|
||||
this.flyCooldownTicks,
|
||||
this.onGround(),
|
||||
this.getNavigation().isDone()
|
||||
);
|
||||
}
|
||||
|
||||
private final class MantisCombatGoal extends Goal {
|
||||
private int repathTicks;
|
||||
|
||||
@@ -656,4 +630,3 @@ public class MantisEntity extends Monster implements GeoEntity {
|
||||
|
||||
|
||||
}
|
||||
|
||||
+17
-12
@@ -37,6 +37,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.goal.BreedGoal;
|
||||
import net.minecraft.world.entity.ai.goal.FloatGoal;
|
||||
import net.minecraft.world.entity.ai.goal.FollowOwnerGoal;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
@@ -160,25 +161,26 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
||||
}
|
||||
});
|
||||
this.goalSelector.addGoal(2, new BowlingAttackGoal());
|
||||
this.goalSelector.addGoal(3, new FertilizeCropGoal());
|
||||
this.goalSelector.addGoal(4, new EatCompostItemGoal());
|
||||
this.goalSelector.addGoal(5, new SnuggleOnBedGoal());
|
||||
this.goalSelector.addGoal(6, new TemptGoal(this, 1.1D, Ingredient.of(AntarchyTags.Items.ROLLY_POLLY_FOOD), false) {
|
||||
this.goalSelector.addGoal(3, new BreedGoal(this, 1.0D));
|
||||
this.goalSelector.addGoal(4, new FertilizeCropGoal());
|
||||
this.goalSelector.addGoal(5, new EatCompostItemGoal());
|
||||
this.goalSelector.addGoal(6, new SnuggleOnBedGoal());
|
||||
this.goalSelector.addGoal(7, new TemptGoal(this, 1.1D, Ingredient.of(AntarchyTags.Items.ROLLY_POLLY_FOOD), false) {
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return !RollyPollyEntity.this.isRolled() && super.canUse();
|
||||
}
|
||||
});
|
||||
this.goalSelector.addGoal(7, new FollowOwnerGoal(this, 1.1D, 10.0F, 2.0F));
|
||||
this.goalSelector.addGoal(8, new RollingStrollGoal());
|
||||
this.goalSelector.addGoal(9, new WaterAvoidingRandomStrollGoal(this, 1.0D) {
|
||||
this.goalSelector.addGoal(8, new FollowOwnerGoal(this, 1.1D, 10.0F, 2.0F));
|
||||
this.goalSelector.addGoal(9, new RollingStrollGoal());
|
||||
this.goalSelector.addGoal(10, new WaterAvoidingRandomStrollGoal(this, 1.0D) {
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return !RollyPollyEntity.this.isRolled() && super.canUse();
|
||||
}
|
||||
});
|
||||
this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
||||
this.goalSelector.addGoal(11, new RandomLookAroundGoal(this));
|
||||
this.goalSelector.addGoal(11, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
||||
this.goalSelector.addGoal(12, new RandomLookAroundGoal(this));
|
||||
this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this));
|
||||
this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this));
|
||||
}
|
||||
@@ -192,7 +194,8 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
||||
public InteractionResult mobInteract(Player player, InteractionHand hand) {
|
||||
ItemStack stack = player.getItemInHand(hand);
|
||||
|
||||
if (this.isFood(stack) && (!this.isTame() || this.getHealth() < this.getMaxHealth())) {
|
||||
if (this.isFood(stack) && (!this.isTame() || this.getHealth() < this.getMaxHealth()
|
||||
|| (this.canFallInLove() && !this.isBaby()))) {
|
||||
if (!this.level().isClientSide) {
|
||||
if (!player.getAbilities().instabuild) {
|
||||
stack.shrink(1);
|
||||
@@ -210,9 +213,11 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
||||
} else {
|
||||
this.level().broadcastEntityEvent(this, (byte) 6);
|
||||
}
|
||||
} else {
|
||||
} else if (this.getHealth() < this.getMaxHealth()) {
|
||||
this.heal(4.0F);
|
||||
this.level().broadcastEntityEvent(this, (byte) 7);
|
||||
} else {
|
||||
this.setInLove(player);
|
||||
}
|
||||
}
|
||||
return InteractionResult.sidedSuccess(this.level().isClientSide);
|
||||
@@ -239,7 +244,7 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
||||
@Override
|
||||
@Nullable
|
||||
public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) {
|
||||
return null;
|
||||
return com.craisinlord.antarchy.content.AntarchyObjects.ROLLY_POLLY.get().create(level);
|
||||
}
|
||||
|
||||
private static boolean isCompostable(ItemStack stack) {
|
||||
|
||||
+7
@@ -5,6 +5,7 @@ import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
|
||||
import com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
@@ -97,6 +98,9 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
||||
|| spawnReason == MobSpawnType.COMMAND) {
|
||||
return true;
|
||||
}
|
||||
if (ThoraxisUndersideManager.shouldSpawnInvertedOnDreamSand(level, pos)) {
|
||||
return level.getDifficulty() != Difficulty.PEACEFUL;
|
||||
}
|
||||
return level.getDifficulty() != Difficulty.PEACEFUL
|
||||
&& Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
|
||||
}
|
||||
@@ -123,6 +127,9 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData spawnGroupData) {
|
||||
this.assignRandomTextureVariant();
|
||||
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.scorpionHealth());
|
||||
if (ThoraxisUndersideManager.shouldSpawnInvertedOnDreamSand(level, this.blockPosition())) {
|
||||
ThoraxisUndersideManager.applyUndersideInversion(this);
|
||||
}
|
||||
return super.finalizeSpawn(level, difficulty, spawnType, spawnGroupData);
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -51,6 +51,10 @@ public class UpwardFallingBlockEntity extends Entity {
|
||||
return this.entityData.get(DATA_BLOCK_STATE);
|
||||
}
|
||||
|
||||
protected double getRiseAccel() {
|
||||
return RISE_ACCEL;
|
||||
}
|
||||
|
||||
public static void fallUp(Level level, BlockPos pos, BlockState state) {
|
||||
fallUp(level, pos, state, true);
|
||||
}
|
||||
@@ -82,7 +86,7 @@ public class UpwardFallingBlockEntity extends Entity {
|
||||
}
|
||||
|
||||
double beforeY = getY();
|
||||
setDeltaMovement(getDeltaMovement().add(0.0, RISE_ACCEL, 0.0));
|
||||
setDeltaMovement(getDeltaMovement().add(0.0, getRiseAccel(), 0.0));
|
||||
move(MoverType.SELF, getDeltaMovement());
|
||||
setDeltaMovement(getDeltaMovement().scale(DRAG));
|
||||
distanceTraveled += Math.max(0.0, getY() - beforeY);
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.craisinlord.antarchy.content.entity.vortex;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class VortexChargeProjectileEntity extends ThrowableItemProjectile {
|
||||
public static Supplier<Item> defaultItemSupplier;
|
||||
public static Supplier<EntityType<VortexChargeProjectileEntity>> projectileTypeSupplier;
|
||||
public static Supplier<EntityType<WindVortexEntity>> windVortexTypeSupplier;
|
||||
|
||||
public VortexChargeProjectileEntity(EntityType<? extends VortexChargeProjectileEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
}
|
||||
|
||||
public VortexChargeProjectileEntity(EntityType<? extends VortexChargeProjectileEntity> entityType,
|
||||
LivingEntity thrower, Level level) {
|
||||
super(entityType, thrower, level);
|
||||
}
|
||||
|
||||
public VortexChargeProjectileEntity(Level level, double x, double y, double z) {
|
||||
super(projectileTypeSupplier.get(), x, y, z, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getDefaultGravity() {
|
||||
return 0.03D;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item getDefaultItem() {
|
||||
return defaultItemSupplier != null ? defaultItemSupplier.get() : Items.WIND_CHARGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHit(HitResult hitResult) {
|
||||
super.onHit(hitResult);
|
||||
|
||||
if (this.level() instanceof ServerLevel serverLevel && windVortexTypeSupplier != null) {
|
||||
Vec3 position = hitResult.getLocation();
|
||||
WindVortexEntity vortex = WindVortexEntity.create(
|
||||
serverLevel,
|
||||
windVortexTypeSupplier.get(),
|
||||
position,
|
||||
this.getDeltaMovement().normalize().scale(0.035D),
|
||||
null,
|
||||
false
|
||||
);
|
||||
serverLevel.addFreshEntity(vortex);
|
||||
serverLevel.playSound(null, position.x, position.y, position.z,
|
||||
SoundEvents.BREEZE_WIND_CHARGE_BURST, SoundSource.PLAYERS, 0.9F, 1.0F);
|
||||
}
|
||||
|
||||
if (!this.level().isClientSide) {
|
||||
this.level().broadcastEntityEvent(this, (byte) 3);
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
+427
@@ -0,0 +1,427 @@
|
||||
package com.craisinlord.antarchy.content.entity.vortex;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.Difficulty;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.MoverType;
|
||||
import net.minecraft.world.entity.SpawnGroupData;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.control.FlyingMoveControl;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
|
||||
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
||||
import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||||
import net.minecraft.world.entity.ai.util.HoverRandomPos;
|
||||
import net.minecraft.world.entity.monster.Monster;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import software.bernie.geckolib.animatable.GeoEntity;
|
||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.animation.AnimationController;
|
||||
import software.bernie.geckolib.animation.AnimationState;
|
||||
import software.bernie.geckolib.animation.PlayState;
|
||||
import software.bernie.geckolib.animation.RawAnimation;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class VortexEntity extends Monster implements GeoEntity {
|
||||
private static final EntityDataAccessor<Integer> ANIMATION_STATE =
|
||||
SynchedEntityData.defineId(VortexEntity.class, EntityDataSerializers.INT);
|
||||
|
||||
private static final int ANIM_IDLE = 0;
|
||||
private static final int ANIM_FLY = 1;
|
||||
private static final int ANIM_ATTACK = 2;
|
||||
private static final int ANIM_DEATH = 3;
|
||||
|
||||
private static final String ATTACK_COOLDOWN_KEY = "AttackCooldown";
|
||||
private static final String ATTACK_TICKS_KEY = "AttackTicks";
|
||||
|
||||
private static final int ATTACK_WINDUP_TICKS = 18;
|
||||
private static final int ATTACK_RECOVERY_TICKS = 12;
|
||||
private static final int ATTACK_COOLDOWN_TICKS = 70;
|
||||
private static final int DEATH_TICKS = 15;
|
||||
private static final double ATTACK_RANGE = 14.0D;
|
||||
|
||||
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
||||
private static final RawAnimation FLY_ANIM = RawAnimation.begin().thenLoop("walk");
|
||||
private static final RawAnimation ATTACK_ANIM = RawAnimation.begin().thenPlay("wind_gust");
|
||||
private static final RawAnimation DEATH_ANIM = RawAnimation.begin().thenPlay("death");
|
||||
|
||||
public static Supplier<EntityType<WindVortexEntity>> windVortexTypeSupplier;
|
||||
|
||||
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||
private int attackCooldown;
|
||||
private int attackTicks;
|
||||
private boolean spawnedAttackVortex;
|
||||
|
||||
public VortexEntity(EntityType<? extends VortexEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
this.moveControl = new FlyingMoveControl(this, 2, true);
|
||||
this.xpReward = 10;
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return Mob.createMobAttributes()
|
||||
.add(Attributes.MAX_HEALTH, AntarchySettings.vortexHealth())
|
||||
.add(Attributes.ATTACK_DAMAGE, AntarchySettings.vortexAttackDamage())
|
||||
.add(Attributes.MOVEMENT_SPEED, AntarchySettings.vortexMovementSpeed())
|
||||
.add(Attributes.FLYING_SPEED, AntarchySettings.vortexFlyingSpeed())
|
||||
.add(Attributes.FOLLOW_RANGE, 40.0D)
|
||||
.add(Attributes.KNOCKBACK_RESISTANCE, 0.45D);
|
||||
}
|
||||
|
||||
public static boolean canSpawn(EntityType<VortexEntity> entityType, ServerLevelAccessor level,
|
||||
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||
return level.getDifficulty() != Difficulty.PEACEFUL
|
||||
&& level.isEmptyBlock(pos)
|
||||
&& level.isEmptyBlock(pos.above())
|
||||
&& level.isEmptyBlock(pos.above(2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||
MobSpawnType spawnReason, SpawnGroupData spawnData) {
|
||||
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.vortexHealth());
|
||||
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
builder.define(ANIMATION_STATE, ANIM_IDLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(1, new VortexPatrolGoal());
|
||||
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
|
||||
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 20, true, false, this::canTargetEntity));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PathNavigation createNavigation(Level level) {
|
||||
FlyingPathNavigation nav = new FlyingPathNavigation(this, level);
|
||||
nav.setCanOpenDoors(false);
|
||||
nav.setCanFloat(true);
|
||||
nav.setCanPassDoors(true);
|
||||
return nav;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||
controllers.add(new AnimationController<>(this, "main_controller", 0, this::mainAnimController)
|
||||
.triggerableAnim("attack", ATTACK_ANIM)
|
||||
.triggerableAnim("death", DEATH_ANIM));
|
||||
}
|
||||
|
||||
private PlayState mainAnimController(AnimationState<VortexEntity> state) {
|
||||
return switch (this.getAnimationState()) {
|
||||
case ANIM_FLY -> state.setAndContinue(FLY_ANIM);
|
||||
case ANIM_ATTACK -> state.setAndContinue(ATTACK_ANIM);
|
||||
case ANIM_DEATH -> state.setAndContinue(DEATH_ANIM);
|
||||
default -> state.setAndContinue(IDLE_ANIM);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.geoCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
this.setNoGravity(true);
|
||||
|
||||
if (this.level().isClientSide) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isDeadOrDying()) {
|
||||
this.updateAnimationState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.attackCooldown > 0) {
|
||||
this.attackCooldown--;
|
||||
}
|
||||
|
||||
LivingEntity target = this.getTarget();
|
||||
if (this.attackTicks > 0) {
|
||||
this.tickAttack(target);
|
||||
this.updateAnimationState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (target != null && this.canTargetEntity(target)) {
|
||||
this.tickCombatMovement(target);
|
||||
}
|
||||
|
||||
this.updateAnimationState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void travel(Vec3 travelVector) {
|
||||
if (this.isEffectiveAi() || this.isNoGravity()) {
|
||||
this.moveRelative(this.getSpeed(), travelVector);
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
this.setDeltaMovement(this.getDeltaMovement().scale(0.91D));
|
||||
return;
|
||||
}
|
||||
super.travel(travelVector);
|
||||
}
|
||||
|
||||
private void tickCombatMovement(LivingEntity target) {
|
||||
this.faceTowards(target.position().add(0.0D, target.getBbHeight() * 0.5D, 0.0D), 12.0F, 8.0F);
|
||||
this.getMoveControl().setWantedPosition(target.getX(), target.getY() + 2.5D, target.getZ(), 0.38D);
|
||||
|
||||
if (this.attackCooldown <= 0
|
||||
&& this.distanceToSqr(target) <= ATTACK_RANGE * ATTACK_RANGE
|
||||
&& this.hasLineOfSight(target)
|
||||
&& this.countOwnedActiveVortexes() < AntarchySettings.vortexMaxActiveVortexes()) {
|
||||
this.startAttack();
|
||||
}
|
||||
}
|
||||
|
||||
private void startAttack() {
|
||||
this.attackTicks = ATTACK_WINDUP_TICKS + ATTACK_RECOVERY_TICKS;
|
||||
this.spawnedAttackVortex = false;
|
||||
this.attackCooldown = ATTACK_COOLDOWN_TICKS;
|
||||
this.getNavigation().stop();
|
||||
}
|
||||
|
||||
private void tickAttack(@Nullable LivingEntity target) {
|
||||
this.getNavigation().stop();
|
||||
this.setDeltaMovement(this.getDeltaMovement().scale(0.84D));
|
||||
|
||||
if (target == null || !this.canTargetEntity(target)) {
|
||||
this.attackTicks = 0;
|
||||
this.spawnedAttackVortex = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.faceTowards(target.getEyePosition(), 16.0F, 10.0F);
|
||||
this.getMoveControl().setWantedPosition(this.getX(), Math.max(this.getY(), target.getY() + 2.5D), this.getZ(), 0.34D);
|
||||
|
||||
int elapsed = ATTACK_WINDUP_TICKS + ATTACK_RECOVERY_TICKS - this.attackTicks;
|
||||
if (!this.spawnedAttackVortex && elapsed >= ATTACK_WINDUP_TICKS) {
|
||||
this.spawnAttackVortex(target);
|
||||
this.spawnedAttackVortex = true;
|
||||
}
|
||||
|
||||
if (--this.attackTicks <= 0) {
|
||||
this.attackTicks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnAttackVortex(LivingEntity target) {
|
||||
if (!(this.level() instanceof ServerLevel serverLevel) || windVortexTypeSupplier == null) {
|
||||
return;
|
||||
}
|
||||
Vec3 targetPos = target.position();
|
||||
Vec3 fromMob = targetPos.subtract(this.position());
|
||||
Vec3 drift = fromMob.lengthSqr() > 1.0E-6D ? fromMob.normalize().scale(0.045D) : this.getViewVector(0.0F).scale(0.045D);
|
||||
Vec3 position = targetPos.add(
|
||||
(this.random.nextDouble() - 0.5D) * 1.6D,
|
||||
0.05D,
|
||||
(this.random.nextDouble() - 0.5D) * 1.6D
|
||||
);
|
||||
WindVortexEntity vortex = WindVortexEntity.create(serverLevel, windVortexTypeSupplier.get(), position, drift, this, true);
|
||||
serverLevel.addFreshEntity(vortex);
|
||||
serverLevel.playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.BREEZE_SHOOT, this.getSoundSource(), 1.0F, 0.9F);
|
||||
}
|
||||
|
||||
private int countOwnedActiveVortexes() {
|
||||
if (!(this.level() instanceof ServerLevel serverLevel) || windVortexTypeSupplier == null) {
|
||||
return 0;
|
||||
}
|
||||
return serverLevel.getEntities(windVortexTypeSupplier.get(), this.getBoundingBox().inflate(32.0D),
|
||||
vortex -> vortex.isAlive() && vortex.isDamaging() && vortex.isOwnedBy(this)).size();
|
||||
}
|
||||
|
||||
private void faceTowards(Vec3 targetPos, float maxYawStep, float maxPitchStep) {
|
||||
Vec3 delta = targetPos.subtract(this.getEyePosition());
|
||||
double horizontal = Math.sqrt(delta.x * delta.x + delta.z * delta.z);
|
||||
if (horizontal < 1.0E-6D && Math.abs(delta.y) < 1.0E-6D) {
|
||||
return;
|
||||
}
|
||||
|
||||
float targetYaw = (float) (Mth.atan2(delta.z, delta.x) * (180.0D / Math.PI)) - 90.0F;
|
||||
float targetPitch = (float) (-(Mth.atan2(delta.y, horizontal) * (180.0D / Math.PI)));
|
||||
float nextYaw = Mth.approachDegrees(this.getYRot(), targetYaw, maxYawStep);
|
||||
float nextPitch = Mth.approachDegrees(this.getXRot(), targetPitch, maxPitchStep);
|
||||
this.setYRot(nextYaw);
|
||||
this.setYHeadRot(nextYaw);
|
||||
this.yBodyRot = nextYaw;
|
||||
this.setXRot(nextPitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void die(DamageSource damageSource) {
|
||||
if (!this.level().isClientSide) {
|
||||
this.setAnimationState(ANIM_DEATH);
|
||||
this.attackTicks = 0;
|
||||
this.spawnedAttackVortex = false;
|
||||
this.getNavigation().stop();
|
||||
}
|
||||
super.die(damageSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tickDeath() {
|
||||
this.deathTime++;
|
||||
if (this.deathTime == 1) {
|
||||
this.setAnimationState(ANIM_DEATH);
|
||||
}
|
||||
if (this.deathTime >= DEATH_TICKS) {
|
||||
this.remove(RemovalReason.KILLED);
|
||||
this.dropExperience(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getHurtSound(DamageSource damageSource) {
|
||||
return SoundEvents.BREEZE_HURT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getDeathSound() {
|
||||
return SoundEvents.BREEZE_DEATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag tag) {
|
||||
super.addAdditionalSaveData(tag);
|
||||
tag.putInt(ATTACK_COOLDOWN_KEY, this.attackCooldown);
|
||||
tag.putInt(ATTACK_TICKS_KEY, this.attackTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag tag) {
|
||||
super.readAdditionalSaveData(tag);
|
||||
this.attackCooldown = tag.getInt(ATTACK_COOLDOWN_KEY);
|
||||
this.attackTicks = 0;
|
||||
this.spawnedAttackVortex = false;
|
||||
}
|
||||
|
||||
public int getAnimationState() {
|
||||
return this.entityData.get(ANIMATION_STATE);
|
||||
}
|
||||
|
||||
private void setAnimationState(int state) {
|
||||
if (this.entityData.get(ANIMATION_STATE) != state) {
|
||||
this.entityData.set(ANIMATION_STATE, state);
|
||||
String trigger = switch (state) {
|
||||
case ANIM_ATTACK -> "wind_gust";
|
||||
case ANIM_DEATH -> "death";
|
||||
default -> null;
|
||||
};
|
||||
if (trigger != null) {
|
||||
this.triggerAnim("main_controller", trigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAnimationState() {
|
||||
if (this.isDeadOrDying()) {
|
||||
this.setAnimationState(ANIM_DEATH);
|
||||
} else if (this.attackTicks > 0) {
|
||||
this.setAnimationState(ANIM_ATTACK);
|
||||
} else if (this.getTarget() != null && this.canTargetEntity(this.getTarget())) {
|
||||
this.setAnimationState(ANIM_FLY);
|
||||
} else {
|
||||
this.setAnimationState(ANIM_IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canTargetEntity(@Nullable LivingEntity entity) {
|
||||
if (entity == null || !entity.isAlive() || entity == this || entity.getType() == this.getType()) {
|
||||
return false;
|
||||
}
|
||||
if (entity instanceof Player player) {
|
||||
return !player.isCreative() && !player.isSpectator()
|
||||
&& this.level().getDifficulty() != Difficulty.PEACEFUL;
|
||||
}
|
||||
return entity.isAttackable();
|
||||
}
|
||||
|
||||
private final class VortexPatrolGoal extends Goal {
|
||||
private int retargetDelay;
|
||||
|
||||
private VortexPatrolGoal() {
|
||||
this.setFlags(EnumSet.of(Flag.MOVE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return VortexEntity.this.getTarget() == null
|
||||
&& VortexEntity.this.attackTicks <= 0
|
||||
&& VortexEntity.this.getNavigation().isDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return VortexEntity.this.getTarget() == null
|
||||
&& VortexEntity.this.attackTicks <= 0
|
||||
&& VortexEntity.this.getNavigation().isInProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.retargetDelay = Mth.nextInt(VortexEntity.this.random, 40, 80);
|
||||
this.moveToNewTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (VortexEntity.this.getTarget() != null || VortexEntity.this.attackTicks > 0) {
|
||||
VortexEntity.this.getNavigation().stop();
|
||||
return;
|
||||
}
|
||||
if (VortexEntity.this.getNavigation().isDone() && this.retargetDelay-- <= 0) {
|
||||
this.retargetDelay = Mth.nextInt(VortexEntity.this.random, 40, 80);
|
||||
this.moveToNewTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToNewTarget() {
|
||||
Vec3 bias = VortexEntity.this.getViewVector(0.0F);
|
||||
Vec3 hover = HoverRandomPos.getPos(VortexEntity.this, 10, 5, bias.x, bias.z, (float) Math.PI / 2.0F, 3, 1);
|
||||
if (hover != null) {
|
||||
VortexEntity.this.getNavigation().moveTo(hover.x, hover.y, hover.z, 0.18D);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+469
@@ -0,0 +1,469 @@
|
||||
package com.craisinlord.antarchy.content.entity.vortex;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.AntarchyTags;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class WindVortexEntity extends Entity {
|
||||
private static final EntityDataAccessor<Float> HEIGHT =
|
||||
SynchedEntityData.defineId(WindVortexEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Float> TOP_RADIUS =
|
||||
SynchedEntityData.defineId(WindVortexEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Boolean> DAMAGING =
|
||||
SynchedEntityData.defineId(WindVortexEntity.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final EntityDataAccessor<Integer> MODE =
|
||||
SynchedEntityData.defineId(WindVortexEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Float> AXIS_X =
|
||||
SynchedEntityData.defineId(WindVortexEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Float> AXIS_Y =
|
||||
SynchedEntityData.defineId(WindVortexEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Float> AXIS_Z =
|
||||
SynchedEntityData.defineId(WindVortexEntity.class, EntityDataSerializers.FLOAT);
|
||||
|
||||
private static final String AGE_KEY = "Age";
|
||||
private static final String DURATION_KEY = "Duration";
|
||||
private static final String HEIGHT_KEY = "Height";
|
||||
private static final String TOP_RADIUS_KEY = "TopRadius";
|
||||
private static final String PULL_STRENGTH_KEY = "PullStrength";
|
||||
private static final String LAUNCH_STRENGTH_KEY = "LaunchStrength";
|
||||
private static final String DAMAGING_KEY = "Damaging";
|
||||
private static final String OWNER_KEY = "Owner";
|
||||
private static final String MODE_KEY = "Mode";
|
||||
private static final String AXIS_X_KEY = "AxisX";
|
||||
private static final String AXIS_Y_KEY = "AxisY";
|
||||
private static final String AXIS_Z_KEY = "AxisZ";
|
||||
|
||||
private static final double BASE_RADIUS = 0.35D;
|
||||
private static final double DRIFT_FRICTION = 0.96D;
|
||||
|
||||
public enum VortexMode {
|
||||
UPWARD,
|
||||
LENS_PULL,
|
||||
LENS_PUSH
|
||||
}
|
||||
|
||||
private int age;
|
||||
private int durationTicks = 140;
|
||||
private double pullStrength = 0.32D;
|
||||
private double launchStrength = 1.0D;
|
||||
private final Map<UUID, Double> carriedProgress = new HashMap<>();
|
||||
@Nullable
|
||||
private UUID ownerUuid;
|
||||
|
||||
public WindVortexEntity(EntityType<? extends WindVortexEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
this.noCulling = true;
|
||||
}
|
||||
|
||||
public static WindVortexEntity create(Level level, EntityType<? extends WindVortexEntity> type, Vec3 position,
|
||||
Vec3 drift, @Nullable LivingEntity owner, boolean damaging) {
|
||||
WindVortexEntity vortex = new WindVortexEntity(type, level);
|
||||
vortex.setPos(position.x, position.y, position.z);
|
||||
vortex.setDeltaMovement(drift);
|
||||
vortex.setVortexSize(5.0F, 1.5F);
|
||||
vortex.setAxis(Direction.UP);
|
||||
vortex.setMode(VortexMode.UPWARD);
|
||||
vortex.durationTicks = Math.max(1, AntarchySettings.windVortexDurationTicks());
|
||||
vortex.pullStrength = AntarchySettings.windVortexPullStrength();
|
||||
vortex.launchStrength = AntarchySettings.windVortexLaunchStrength();
|
||||
vortex.setDamaging(damaging);
|
||||
if (owner != null) {
|
||||
vortex.ownerUuid = owner.getUUID();
|
||||
}
|
||||
return vortex;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
builder.define(HEIGHT, 5.0F);
|
||||
builder.define(TOP_RADIUS, 1.5F);
|
||||
builder.define(DAMAGING, false);
|
||||
builder.define(MODE, VortexMode.UPWARD.ordinal());
|
||||
builder.define(AXIS_X, 0.0F);
|
||||
builder.define(AXIS_Y, 1.0F);
|
||||
builder.define(AXIS_Z, 0.0F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
boolean lensVortex = this.getMode() != VortexMode.UPWARD;
|
||||
if (!lensVortex && (this.isInLava() || this.isInsideSolidBlock())) {
|
||||
this.fadeOut();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.level().isClientSide) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.age++;
|
||||
if (!lensVortex && this.age >= this.durationTicks) {
|
||||
this.fadeOut();
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 drift = this.getDeltaMovement().multiply(DRIFT_FRICTION, DRIFT_FRICTION, DRIFT_FRICTION);
|
||||
this.setDeltaMovement(drift);
|
||||
this.move(net.minecraft.world.entity.MoverType.SELF, drift);
|
||||
|
||||
if ((this.tickCount & 1) == 0) {
|
||||
this.applyVortexForces();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInsideSolidBlock() {
|
||||
BlockPos pos = this.blockPosition();
|
||||
BlockState state = this.level().getBlockState(pos);
|
||||
return !state.getCollisionShape(this.level(), pos).isEmpty();
|
||||
}
|
||||
|
||||
private void fadeOut() {
|
||||
if (!this.level().isClientSide) {
|
||||
this.level().broadcastEntityEvent(this, (byte) 60);
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEntityEvent(byte id) {
|
||||
if (id == 60) {
|
||||
return;
|
||||
}
|
||||
super.handleEntityEvent(id);
|
||||
}
|
||||
|
||||
private void applyVortexForces() {
|
||||
double height = this.getVortexHeight();
|
||||
double maxRadius = this.getTopRadius();
|
||||
AABB area = this.getBoundingBox().inflate(maxRadius + height + 1.0D);
|
||||
Basis basis = this.basis();
|
||||
VortexMode mode = this.getMode();
|
||||
|
||||
for (Entity entity : this.level().getEntities(this, area, this::canAffectEntity)) {
|
||||
Vec3 relative = entity.position().subtract(this.position());
|
||||
double axisDistance = relative.dot(basis.axis);
|
||||
if (axisDistance < -0.25D || axisDistance > height + 0.75D) {
|
||||
continue;
|
||||
}
|
||||
double along = Mth.clamp(axisDistance, 0.0D, height);
|
||||
double currentProgress = height <= 0.0D ? 1.0D : along / height;
|
||||
double captureProgress = mode == VortexMode.LENS_PULL ? 1.0D - currentProgress : currentProgress;
|
||||
double shapeProgress = mode == VortexMode.LENS_PULL ? 1.0D - currentProgress : currentProgress;
|
||||
double radius = this.radiusAt(shapeProgress);
|
||||
Vec3 axisPoint = basis.axis.scale(axisDistance);
|
||||
Vec3 radialVector = relative.subtract(axisPoint);
|
||||
double captureRadius = radius + (entity instanceof Player ? 1.0D : 0.35D);
|
||||
|
||||
if (radialVector.lengthSqr() > captureRadius * captureRadius || !this.hasClearPathTo(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.carriedProgress.putIfAbsent(entity.getUUID(), captureProgress);
|
||||
}
|
||||
|
||||
if (!(this.level() instanceof ServerLevel serverLevel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Iterator<Map.Entry<UUID, Double>> iterator = this.carriedProgress.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<UUID, Double> entry = iterator.next();
|
||||
Entity entity = serverLevel.getEntity(entry.getKey());
|
||||
if (entity == null || !this.canAffectEntity(entity)) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
double progress = entry.getValue();
|
||||
double direction = mode == VortexMode.LENS_PULL ? -1.0D : 1.0D;
|
||||
progress += direction * 0.055D;
|
||||
if (mode == VortexMode.LENS_PULL && progress <= 0.0D) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mode == VortexMode.UPWARD && progress >= 0.92D) {
|
||||
this.launch(entity, this.radialVectorAt(entity, progress, basis), progress, basis);
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mode == VortexMode.LENS_PUSH && progress >= 0.94D) {
|
||||
this.launch(entity, this.radialVectorAt(entity, progress, basis), progress, basis);
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
double shapeProgress = mode == VortexMode.LENS_PULL ? progress : progress;
|
||||
double radius = this.radiusAt(shapeProgress);
|
||||
Vec3 relative = entity.position().subtract(this.position());
|
||||
Vec3 axisPoint = basis.axis.scale(relative.dot(basis.axis));
|
||||
Vec3 radialVector = relative.subtract(axisPoint);
|
||||
this.spin(entity, radialVector, progress, shapeProgress, radius, basis, mode);
|
||||
if (mode == VortexMode.UPWARD) {
|
||||
entity.setOnGround(false);
|
||||
}
|
||||
this.hurtCaughtEntity(entity);
|
||||
entry.setValue(progress);
|
||||
}
|
||||
}
|
||||
|
||||
private Vec3 radialVectorAt(Entity entity, double progress, Basis basis) {
|
||||
Vec3 relative = entity.position().subtract(this.position());
|
||||
Vec3 axisPoint = basis.axis.scale(relative.dot(basis.axis));
|
||||
Vec3 radial = relative.subtract(axisPoint);
|
||||
return radial.lengthSqr() < 1.0E-6D ? basis.sideA.scale(this.radiusAt(progress)) : radial;
|
||||
}
|
||||
|
||||
private boolean canAffectEntity(Entity entity) {
|
||||
if (!entity.isAlive() || entity.isSpectator() || entity.noPhysics || entity.getType().is(AntarchyTags.Entities.WIND_VORTEX_IMMUNE)) {
|
||||
return false;
|
||||
}
|
||||
if (entity instanceof Player player && player.isCreative()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasClearPathTo(Entity entity) {
|
||||
Vec3 from = this.position().add(this.getAxis().scale(Math.min(entity.getBbHeight() * 0.5D, this.getVortexHeight())));
|
||||
Vec3 to = entity.getBoundingBox().getCenter();
|
||||
HitResult result = this.level().clip(new ClipContext(from, to, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this));
|
||||
return result.getType() == HitResult.Type.MISS;
|
||||
}
|
||||
|
||||
private void spin(Entity entity, Vec3 radialVector, double progress, double shapeProgress, double radius, Basis basis, VortexMode mode) {
|
||||
double horizontal = Math.max(0.08D, radialVector.length());
|
||||
Vec3 radial = radialVector.lengthSqr() < 1.0E-6D ? basis.sideA : radialVector.scale(1.0D / horizontal);
|
||||
Vec3 tangent = basis.axis.cross(radial).normalize();
|
||||
double targetRadius = mode == VortexMode.LENS_PULL
|
||||
? Math.max(0.05D, radius * 0.18D)
|
||||
: Mth.lerp(shapeProgress, BASE_RADIUS, radius * 0.82D);
|
||||
double radialError = targetRadius - horizontal;
|
||||
double playerScale = entity instanceof Player ? 1.8D : 1.0D;
|
||||
double pull = this.pullStrength * playerScale * (entity.isShiftKeyDown() ? 0.5D : 1.0D);
|
||||
double massScale = Mth.clamp(1.35D / Math.max(0.35D, entity.getBbWidth() * entity.getBbHeight()), 0.28D, 1.0D);
|
||||
double spin = (0.24D + progress * 0.34D) * massScale * playerScale;
|
||||
double axialSpeed = switch (mode) {
|
||||
case LENS_PULL -> -(0.18D + (1.0D - progress) * 0.18D) * massScale;
|
||||
case LENS_PUSH -> (0.18D + progress * 0.22D) * massScale;
|
||||
case UPWARD -> (0.13D + progress * 0.16D) * massScale;
|
||||
} * playerScale;
|
||||
if (mode == VortexMode.UPWARD && entity instanceof Player && entity.onGround()) {
|
||||
axialSpeed = Math.max(axialSpeed, 0.38D);
|
||||
}
|
||||
|
||||
Vec3 wanted = radial.scale(radialError * pull)
|
||||
.add(tangent.scale(spin))
|
||||
.add(basis.axis.scale(axialSpeed));
|
||||
Vec3 current = entity.getDeltaMovement();
|
||||
Vec3 updatedMovement = new Vec3(
|
||||
Mth.lerp(0.72D, current.x, wanted.x),
|
||||
Mth.lerp(0.58D, current.y, wanted.y),
|
||||
Mth.lerp(0.72D, current.z, wanted.z)
|
||||
);
|
||||
if (mode == VortexMode.UPWARD && entity instanceof Player && entity.onGround()) {
|
||||
updatedMovement = new Vec3(updatedMovement.x, Math.max(updatedMovement.y, 0.38D), updatedMovement.z);
|
||||
entity.setOnGround(false);
|
||||
}
|
||||
entity.setDeltaMovement(updatedMovement);
|
||||
entity.fallDistance = 0.0F;
|
||||
entity.hasImpulse = true;
|
||||
}
|
||||
|
||||
private void launch(Entity entity, Vec3 radialVector, double progress, Basis basis) {
|
||||
double horizontal = Math.max(0.08D, radialVector.length());
|
||||
Vec3 radial = radialVector.lengthSqr() < 1.0E-6D ? basis.sideA : radialVector.scale(1.0D / horizontal);
|
||||
Vec3 tangent = basis.axis.cross(radial).normalize();
|
||||
double scale = this.launchStrength * Mth.clamp(this.getVortexHeight() / 5.0D, 0.5D, 2.5D);
|
||||
entity.setDeltaMovement(tangent.scale(0.72D * scale).add(radial.scale(0.34D * scale)).add(basis.axis.scale((0.78D + progress * 0.28D) * scale)));
|
||||
entity.hasImpulse = true;
|
||||
}
|
||||
|
||||
private void hurtCaughtEntity(Entity entity) {
|
||||
if (!this.isDamaging() || !(entity instanceof LivingEntity living) || living.tickCount % 20 != 0) {
|
||||
return;
|
||||
}
|
||||
if (living.getType().is(AntarchyTags.Entities.WIND_VORTEX_IMMUNE)) {
|
||||
return;
|
||||
}
|
||||
float damage = (float) (2.0D * Mth.clamp(this.getTopRadius() / 1.5D, 0.5D, 3.0D));
|
||||
living.hurt(this.damageSource(), damage);
|
||||
}
|
||||
|
||||
private DamageSource damageSource() {
|
||||
Entity owner = this.getOwnerEntity();
|
||||
if (owner instanceof LivingEntity living) {
|
||||
return this.damageSources().mobAttack(living);
|
||||
}
|
||||
return this.damageSources().magic();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Entity getOwnerEntity() {
|
||||
if (this.ownerUuid == null || !(this.level() instanceof ServerLevel serverLevel)) {
|
||||
return null;
|
||||
}
|
||||
return serverLevel.getEntity(this.ownerUuid);
|
||||
}
|
||||
|
||||
private double radiusAt(double progress) {
|
||||
return Mth.lerp(progress, BASE_RADIUS, this.getTopRadius());
|
||||
}
|
||||
|
||||
public void setVortexSize(float height, float topRadius) {
|
||||
this.entityData.set(HEIGHT, height);
|
||||
this.entityData.set(TOP_RADIUS, topRadius);
|
||||
}
|
||||
|
||||
public float getVortexHeight() {
|
||||
return this.entityData.get(HEIGHT);
|
||||
}
|
||||
|
||||
public float getTopRadius() {
|
||||
return this.entityData.get(TOP_RADIUS);
|
||||
}
|
||||
|
||||
public void setMode(VortexMode mode) {
|
||||
this.entityData.set(MODE, mode.ordinal());
|
||||
}
|
||||
|
||||
public VortexMode getMode() {
|
||||
int ordinal = Mth.clamp(this.entityData.get(MODE), 0, VortexMode.values().length - 1);
|
||||
return VortexMode.values()[ordinal];
|
||||
}
|
||||
|
||||
public void setAxis(Direction direction) {
|
||||
this.setAxis(Vec3.atLowerCornerOf(direction.getNormal()));
|
||||
}
|
||||
|
||||
public void setAxis(Vec3 axis) {
|
||||
Vec3 normalized = axis.lengthSqr() < 1.0E-6D ? new Vec3(0.0D, 1.0D, 0.0D) : axis.normalize();
|
||||
this.entityData.set(AXIS_X, (float) normalized.x);
|
||||
this.entityData.set(AXIS_Y, (float) normalized.y);
|
||||
this.entityData.set(AXIS_Z, (float) normalized.z);
|
||||
}
|
||||
|
||||
public Vec3 getAxis() {
|
||||
Vec3 axis = new Vec3(this.entityData.get(AXIS_X), this.entityData.get(AXIS_Y), this.entityData.get(AXIS_Z));
|
||||
return axis.lengthSqr() < 1.0E-6D ? new Vec3(0.0D, 1.0D, 0.0D) : axis.normalize();
|
||||
}
|
||||
|
||||
public int getVortexAge() {
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public int getVortexDurationTicks() {
|
||||
return this.durationTicks;
|
||||
}
|
||||
|
||||
public void setVortexDurationTicks(int durationTicks) {
|
||||
this.durationTicks = Math.max(1, durationTicks);
|
||||
}
|
||||
|
||||
public void resetVortexAge() {
|
||||
this.age = 0;
|
||||
}
|
||||
|
||||
public void setVortexStrengths(double pullStrength, double launchStrength) {
|
||||
this.pullStrength = Math.max(0.0D, pullStrength);
|
||||
this.launchStrength = Math.max(0.0D, launchStrength);
|
||||
}
|
||||
|
||||
public void removeFromLens() {
|
||||
this.fadeOut();
|
||||
}
|
||||
|
||||
public boolean isDamaging() {
|
||||
return this.entityData.get(DAMAGING);
|
||||
}
|
||||
|
||||
public boolean isOwnedBy(Entity entity) {
|
||||
return entity != null && this.ownerUuid != null && this.ownerUuid.equals(entity.getUUID());
|
||||
}
|
||||
|
||||
public void setDamaging(boolean damaging) {
|
||||
this.entityData.set(DAMAGING, damaging);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag tag) {
|
||||
this.age = tag.getInt(AGE_KEY);
|
||||
this.durationTicks = tag.getInt(DURATION_KEY);
|
||||
this.setVortexSize(tag.getFloat(HEIGHT_KEY), tag.getFloat(TOP_RADIUS_KEY));
|
||||
this.pullStrength = tag.getDouble(PULL_STRENGTH_KEY);
|
||||
this.launchStrength = tag.getDouble(LAUNCH_STRENGTH_KEY);
|
||||
this.setDamaging(tag.getBoolean(DAMAGING_KEY));
|
||||
this.setMode(VortexMode.values()[Mth.clamp(tag.getInt(MODE_KEY), 0, VortexMode.values().length - 1)]);
|
||||
this.setAxis(new Vec3(tag.getFloat(AXIS_X_KEY), tag.getFloat(AXIS_Y_KEY), tag.getFloat(AXIS_Z_KEY)));
|
||||
if (tag.hasUUID(OWNER_KEY)) {
|
||||
this.ownerUuid = tag.getUUID(OWNER_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionalSaveData(CompoundTag tag) {
|
||||
tag.putInt(AGE_KEY, this.age);
|
||||
tag.putInt(DURATION_KEY, this.durationTicks);
|
||||
tag.putFloat(HEIGHT_KEY, this.getVortexHeight());
|
||||
tag.putFloat(TOP_RADIUS_KEY, this.getTopRadius());
|
||||
tag.putDouble(PULL_STRENGTH_KEY, this.pullStrength);
|
||||
tag.putDouble(LAUNCH_STRENGTH_KEY, this.launchStrength);
|
||||
tag.putBoolean(DAMAGING_KEY, this.isDamaging());
|
||||
tag.putInt(MODE_KEY, this.getMode().ordinal());
|
||||
tag.putFloat(AXIS_X_KEY, (float) this.getAxis().x);
|
||||
tag.putFloat(AXIS_Y_KEY, (float) this.getAxis().y);
|
||||
tag.putFloat(AXIS_Z_KEY, (float) this.getAxis().z);
|
||||
if (this.ownerUuid != null) {
|
||||
tag.putUUID(OWNER_KEY, this.ownerUuid);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Basis {
|
||||
public final Vec3 axis;
|
||||
public final Vec3 sideA;
|
||||
public final Vec3 sideB;
|
||||
|
||||
private Basis(Vec3 axis, Vec3 sideA, Vec3 sideB) {
|
||||
this.axis = axis;
|
||||
this.sideA = sideA;
|
||||
this.sideB = sideB;
|
||||
}
|
||||
}
|
||||
|
||||
public Basis basis() {
|
||||
Vec3 axis = this.getAxis();
|
||||
Vec3 reference = Math.abs(axis.y) > 0.9D ? new Vec3(1.0D, 0.0D, 0.0D) : new Vec3(0.0D, 1.0D, 0.0D);
|
||||
Vec3 sideA = reference.cross(axis).normalize();
|
||||
Vec3 sideB = axis.cross(sideA).normalize();
|
||||
return new Basis(axis, sideA, sideB);
|
||||
}
|
||||
}
|
||||
+36
-86
@@ -1,7 +1,5 @@
|
||||
package com.craisinlord.antarchy.content.gravity;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.level.PathNavigationRegion;
|
||||
@@ -11,52 +9,27 @@ import net.minecraft.world.level.pathfinder.PathfindingContext;
|
||||
import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
|
||||
|
||||
public class GravityWalkNodeEvaluator extends WalkNodeEvaluator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Antarchy/Pathfinding");
|
||||
private static final int[] START_Y_SEARCH = {0, 1, -1, 2, -2, 3, -3, 4, -4};
|
||||
private static final int[][] INVERTED_NEIGHBOR_OFFSETS = {
|
||||
private static final int[] START_Y_SEARCH = {0, 1, -1, 2, -2};
|
||||
private static final int[][] INVERTED_CARDINAL_NEIGHBOR_OFFSETS = {
|
||||
{1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{0, 0, 1},
|
||||
{0, 0, -1},
|
||||
{0, 0, -1}
|
||||
};
|
||||
private static final int[][] INVERTED_DIAGONAL_NEIGHBOR_OFFSETS = {
|
||||
{1, 0, 1},
|
||||
{1, 0, -1},
|
||||
{-1, 0, 1},
|
||||
{-1, 0, -1},
|
||||
{0, 1, 0},
|
||||
{0, -1, 0}
|
||||
{-1, 0, -1}
|
||||
};
|
||||
|
||||
private int antarchy$loggedPrepare;
|
||||
private int antarchy$loggedGetStart;
|
||||
private int antarchy$loggedPathType;
|
||||
private int antarchy$loggedNeighbors;
|
||||
|
||||
@Override
|
||||
public void prepare(PathNavigationRegion sourceIn, Mob mob) {
|
||||
super.prepare(sourceIn, mob);
|
||||
this.antarchy$loggedPrepare = 0;
|
||||
this.antarchy$loggedGetStart = 0;
|
||||
this.antarchy$loggedPathType = 0;
|
||||
this.antarchy$loggedNeighbors = 0;
|
||||
|
||||
if (AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
LOGGER.debug(
|
||||
"[Path] prepare inverted mob={} pos=({}, {}, {}) size=({}, {})",
|
||||
mob.getClass().getSimpleName(),
|
||||
Mth.floor(mob.getX()),
|
||||
Mth.floor(mob.getY()),
|
||||
Mth.floor(mob.getZ()),
|
||||
mob.getBbWidth(),
|
||||
mob.getBbHeight()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
if (this.mob != null && AntarchyGravityApi.isGravityInverted(this.mob)) {
|
||||
LOGGER.debug("[Path] done inverted mob={}", this.mob.getClass().getSimpleName());
|
||||
}
|
||||
super.done();
|
||||
}
|
||||
|
||||
@@ -74,19 +47,6 @@ public class GravityWalkNodeEvaluator extends WalkNodeEvaluator {
|
||||
return super.getStart();
|
||||
}
|
||||
|
||||
if (this.antarchy$loggedGetStart < 8) {
|
||||
LOGGER.debug(
|
||||
"[Path] getStart inverted mob={} node=({}, {}, {}) type={} malus={}",
|
||||
this.mob.getClass().getSimpleName(),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
node.type,
|
||||
node.costMalus
|
||||
);
|
||||
this.antarchy$loggedGetStart++;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -154,19 +114,6 @@ public class GravityWalkNodeEvaluator extends WalkNodeEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.antarchy$loggedPathType < 16) {
|
||||
LOGGER.debug(
|
||||
"[Path] type inverted mob={} pos=({}, {}, {}) ceiling={} result={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
ceilingType,
|
||||
result
|
||||
);
|
||||
this.antarchy$loggedPathType++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -177,46 +124,49 @@ public class GravityWalkNodeEvaluator extends WalkNodeEvaluator {
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (int[] offset : INVERTED_NEIGHBOR_OFFSETS) {
|
||||
count += this.antarchy$addNeighbor(neighbors, count, current.x + offset[0], current.y + offset[1], current.z + offset[2]);
|
||||
Node[] cardinalNeighbors = new Node[INVERTED_CARDINAL_NEIGHBOR_OFFSETS.length];
|
||||
for (int i = 0; i < INVERTED_CARDINAL_NEIGHBOR_OFFSETS.length; i++) {
|
||||
int[] offset = INVERTED_CARDINAL_NEIGHBOR_OFFSETS[i];
|
||||
Node neighbor = this.antarchy$getNeighbor(current.x + offset[0], current.y, current.z + offset[2]);
|
||||
cardinalNeighbors[i] = neighbor;
|
||||
if (neighbor != null) {
|
||||
neighbors[count++] = neighbor;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.antarchy$loggedNeighbors < 16) {
|
||||
LOGGER.debug(
|
||||
"[Path] neighbors inverted mob={} node=({}, {}, {}) count={}",
|
||||
this.mob.getClass().getSimpleName(),
|
||||
current.x,
|
||||
current.y,
|
||||
current.z,
|
||||
count
|
||||
);
|
||||
this.antarchy$loggedNeighbors++;
|
||||
for (int i = 0; i < INVERTED_DIAGONAL_NEIGHBOR_OFFSETS.length; i++) {
|
||||
int[] offset = INVERTED_DIAGONAL_NEIGHBOR_OFFSETS[i];
|
||||
if (!this.antarchy$canUseDiagonal(cardinalNeighbors, i)) {
|
||||
continue;
|
||||
}
|
||||
Node neighbor = this.antarchy$getNeighbor(current.x + offset[0], current.y, current.z + offset[2]);
|
||||
if (neighbor != null) {
|
||||
neighbors[count++] = neighbor;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private int antarchy$addNeighbor(Node[] neighbors, int index, int x, int y, int z) {
|
||||
private boolean antarchy$canUseDiagonal(Node[] cardinalNeighbors, int diagonalIndex) {
|
||||
return switch (diagonalIndex) {
|
||||
case 0 -> cardinalNeighbors[0] != null && cardinalNeighbors[2] != null;
|
||||
case 1 -> cardinalNeighbors[0] != null && cardinalNeighbors[3] != null;
|
||||
case 2 -> cardinalNeighbors[1] != null && cardinalNeighbors[2] != null;
|
||||
case 3 -> cardinalNeighbors[1] != null && cardinalNeighbors[3] != null;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private Node antarchy$getNeighbor(int x, int y, int z) {
|
||||
PathType type = this.getPathTypeOfMob(this.currentContext, x, y, z, this.mob);
|
||||
if (this.mob.getPathfindingMalus(type) < 0.0F) {
|
||||
if (this.antarchy$loggedNeighbors < 16) {
|
||||
LOGGER.debug(
|
||||
"[Path] reject mob={} pos=({}, {}, {}) type={} malus={}",
|
||||
this.mob.getClass().getSimpleName(),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
type,
|
||||
this.mob.getPathfindingMalus(type)
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
Node node = this.getNode(x, y, z);
|
||||
node.type = type;
|
||||
node.costMalus = this.mob.getPathfindingMalus(type);
|
||||
neighbors[index] = node;
|
||||
return 1;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
+65
-3
@@ -1,10 +1,22 @@
|
||||
package com.craisinlord.antarchy.content.item;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EquipmentSlotGroup;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.SwordItem;
|
||||
@@ -13,8 +25,16 @@ import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.component.ItemAttributeModifiers;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import com.craisinlord.antarchy.content.client.BloodCrystalKatanaTrailClientState;
|
||||
|
||||
public class BloodCrystalKatanaItem extends SwordItem {
|
||||
private static final ResourceLocation ATTACK_RANGE_MODIFIER_ID =
|
||||
ResourceLocation.fromNamespaceAndPath("antarchy", "blood_crystal_katana_attack_range");
|
||||
private static final float FULL_SWING_THRESHOLD = 0.9F;
|
||||
private static final Map<UUID, Long> LAST_DASH_TICK = new ConcurrentHashMap<>();
|
||||
private static final Map<UUID, Long> DASH_UNTIL_TICK = new ConcurrentHashMap<>();
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TrailCallback {
|
||||
void trigger(ServerPlayer player, int durationTicks);
|
||||
@@ -35,7 +55,12 @@ public class BloodCrystalKatanaItem extends SwordItem {
|
||||
|
||||
@Override
|
||||
public ItemAttributeModifiers getDefaultAttributeModifiers() {
|
||||
return SwordItem.createAttributes(this.tier, this.attackDamage, this.attackSpeed);
|
||||
return SwordItem.createAttributes(this.tier, this.attackDamage, this.attackSpeed)
|
||||
.withModifierAdded(
|
||||
Attributes.ENTITY_INTERACTION_RANGE,
|
||||
new AttributeModifier(ATTACK_RANGE_MODIFIER_ID, AntarchySettings.bloodCrystalKatanaReachBonus(), AttributeModifier.Operation.ADD_VALUE),
|
||||
EquipmentSlotGroup.MAINHAND
|
||||
);
|
||||
}
|
||||
|
||||
public static void setTrailCallback(TrailCallback callback) {
|
||||
@@ -45,10 +70,21 @@ public class BloodCrystalKatanaItem extends SwordItem {
|
||||
@Override
|
||||
public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
|
||||
boolean result = super.hurtEnemy(stack, target, attacker);
|
||||
if (!(attacker instanceof ServerPlayer player)) {
|
||||
if (attacker instanceof ServerPlayer player) {
|
||||
performDash(player, player.getAttackStrengthScale(0.0F) >= FULL_SWING_THRESHOLD);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void performDash(ServerPlayer player, boolean fullSwing) {
|
||||
long now = player.level().getGameTime();
|
||||
Long last = LAST_DASH_TICK.get(player.getUUID());
|
||||
if (last != null && now - last < AntarchySettings.bloodCrystalKatanaDashCooldownTicks()) {
|
||||
return;
|
||||
}
|
||||
LAST_DASH_TICK.put(player.getUUID(), now);
|
||||
DASH_UNTIL_TICK.put(player.getUUID(), now + AntarchySettings.bloodCrystalKatanaTrailDurationTicks());
|
||||
|
||||
Vec3 look = player.getLookAngle();
|
||||
Vec3 horizontal = new Vec3(look.x, 0.0D, look.z);
|
||||
if (horizontal.lengthSqr() < 1.0E-6D) {
|
||||
@@ -60,13 +96,39 @@ public class BloodCrystalKatanaItem extends SwordItem {
|
||||
player.setDeltaMovement(player.getDeltaMovement().add(launch));
|
||||
player.hasImpulse = true;
|
||||
player.hurtMarked = true;
|
||||
|
||||
trailCallback.trigger(player, AntarchySettings.bloodCrystalKatanaTrailDurationTicks());
|
||||
return result;
|
||||
player.level().playSound(null, player.getX(), player.getY(), player.getZ(),
|
||||
AntarchySoundEvents.BLOOD_CRYSTAL_KATANA_DASH.get(), SoundSource.PLAYERS, 1.0F, 1.0F);
|
||||
|
||||
int invulnTicks = AntarchySettings.bloodCrystalKatanaInvulnTicks();
|
||||
if (fullSwing && invulnTicks > 0) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, invulnTicks, 4, false, false, false));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDashing(Entity entity) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
if (entity.level().isClientSide()) {
|
||||
return BloodCrystalKatanaTrailClientState.getRemainingTicks(entity.getId()) > 0;
|
||||
}
|
||||
Long until = DASH_UNTIL_TICK.get(entity.getUUID());
|
||||
if (until == null) {
|
||||
return false;
|
||||
}
|
||||
if (entity.level().getGameTime() >= until) {
|
||||
DASH_UNTIL_TICK.remove(entity.getUUID());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
tooltipComponents.add(Component.translatable("tooltip.antarchy.blood_crystal_katana.launch").withStyle(ChatFormatting.RED));
|
||||
tooltipComponents.add(Component.translatable("tooltip.antarchy.blood_crystal_katana.dash").withStyle(ChatFormatting.RED));
|
||||
tooltipComponents.add(Component.translatable("tooltip.antarchy.blood_crystal_katana.trail").withStyle(ChatFormatting.DARK_RED));
|
||||
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
||||
}
|
||||
|
||||
+4
@@ -1,7 +1,9 @@
|
||||
package com.craisinlord.antarchy.content.item;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import com.craisinlord.antarchy.content.bloodglass.BloodglassAccess;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
@@ -52,6 +54,8 @@ public class BloodCrystalShardItem extends Item {
|
||||
}
|
||||
|
||||
player.getCooldowns().addCooldown(this, COOLDOWN_TICKS);
|
||||
level.playSound(null, player.getX(), player.getY(), player.getZ(),
|
||||
AntarchySoundEvents.BLOODGLASS_WARD_HEART_REGEN.get(), SoundSource.PLAYERS, 1.0F, 1.0F);
|
||||
SYNC_BLOODGLASS.accept((ServerPlayer) player);
|
||||
|
||||
if (!player.getAbilities().instabuild) {
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.craisinlord.antarchy.content.item;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.vortex.VortexChargeProjectileEntity;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class VortexChargeItem extends Item {
|
||||
private final Supplier<? extends EntityType<? extends VortexChargeProjectileEntity>> projectileType;
|
||||
|
||||
public VortexChargeItem(Properties properties,
|
||||
Supplier<? extends EntityType<? extends VortexChargeProjectileEntity>> projectileType) {
|
||||
super(properties);
|
||||
this.projectileType = projectileType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand usedHand) {
|
||||
ItemStack itemStack = player.getItemInHand(usedHand);
|
||||
if (player.getCooldowns().isOnCooldown(this)) {
|
||||
return InteractionResultHolder.fail(itemStack);
|
||||
}
|
||||
|
||||
level.playSound(null, player.getX(), player.getY(), player.getZ(),
|
||||
SoundEvents.WIND_CHARGE_THROW, SoundSource.NEUTRAL, 0.6F,
|
||||
0.8F + level.getRandom().nextFloat() * 0.4F);
|
||||
|
||||
if (!level.isClientSide) {
|
||||
VortexChargeProjectileEntity projectile = new VortexChargeProjectileEntity(projectileType.get(), player, level);
|
||||
projectile.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F);
|
||||
level.addFreshEntity(projectile);
|
||||
if (!player.getAbilities().instabuild) {
|
||||
itemStack.shrink(1);
|
||||
}
|
||||
}
|
||||
|
||||
player.awardStat(Stats.ITEM_USED.get(this));
|
||||
player.getCooldowns().addCooldown(this, 20);
|
||||
return InteractionResultHolder.consume(itemStack);
|
||||
}
|
||||
}
|
||||
+18
@@ -1,5 +1,6 @@
|
||||
package com.craisinlord.antarchy.content.item;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import com.craisinlord.antarchy.content.entity.WormHookProjectileEntity;
|
||||
import com.craisinlord.antarchy.content.util.WormHookRope;
|
||||
import java.util.Map;
|
||||
@@ -29,6 +30,8 @@ public final class WormHookTetherManager {
|
||||
private static final double DEFAULT_BREAK_RANGE = 48.0D;
|
||||
private static final double SNAP_BUFFER = 4.0D;
|
||||
private static final double PULL_CORRECTION = 0.35D;
|
||||
private static final double FLYING_SOUND_MIN_SPEED_SQR = 0.1D * 0.1D;
|
||||
private static final int FLYING_SOUND_INTERVAL_TICKS = 24;
|
||||
|
||||
private static final Map<UUID, TetherState> TETHERS = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -118,6 +121,7 @@ public final class WormHookTetherManager {
|
||||
Vec3 playerEye = player.getEyePosition();
|
||||
|
||||
state.rope.update(hook, anchor, playerEye, state.maxLen);
|
||||
tickFlyingSound(player, state);
|
||||
|
||||
Vec3 pivot = state.rope.getPivot();
|
||||
double consumed = state.rope.getConsumedLength();
|
||||
@@ -168,6 +172,19 @@ public final class WormHookTetherManager {
|
||||
player.fallDistance = 0;
|
||||
}
|
||||
|
||||
private static void tickFlyingSound(ServerPlayer player, TetherState state) {
|
||||
if (state.flyingSoundCooldown > 0) {
|
||||
state.flyingSoundCooldown--;
|
||||
return;
|
||||
}
|
||||
if (player.getDeltaMovement().horizontalDistanceSqr() < FLYING_SOUND_MIN_SPEED_SQR) {
|
||||
return;
|
||||
}
|
||||
state.flyingSoundCooldown = FLYING_SOUND_INTERVAL_TICKS;
|
||||
player.level().playSound(null, player.blockPosition(), AntarchySoundEvents.WORM_HOOK_FLYING.get(),
|
||||
SoundSource.PLAYERS, 0.6F, 1.0F);
|
||||
}
|
||||
|
||||
private static boolean isValid(ServerPlayer player, WormHookProjectileEntity hook, TetherState state) {
|
||||
double breakRange = (state.rope == null ? DEFAULT_BREAK_RANGE : state.maxLen) * BREAK_RANGE_MULTIPLIER;
|
||||
return player.isAlive()
|
||||
@@ -188,6 +205,7 @@ public final class WormHookTetherManager {
|
||||
private final int hookEntityId;
|
||||
private double maxLen;
|
||||
private WormHookRope rope;
|
||||
private int flyingSoundCooldown;
|
||||
|
||||
private TetherState(int hookEntityId) {
|
||||
this.hookEntityId = hookEntityId;
|
||||
|
||||
+68
-36
@@ -16,8 +16,11 @@ import net.minecraft.world.level.WorldGenLevel;
|
||||
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.Column;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
public NadirTreeFeature(Codec<NadirTreeConfiguration> codec) {
|
||||
@@ -27,7 +30,7 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NadirTreeConfiguration> context) {
|
||||
WorldGenLevel level = context.level();
|
||||
BlockPos origin = context.origin();
|
||||
BlockPos origin = findCeilingOrigin(level, context.origin(), 72);
|
||||
BlockPos supportPos = origin.above();
|
||||
if (!level.getBlockState(supportPos).isFaceSturdy(level, supportPos, Direction.DOWN)) {
|
||||
return false;
|
||||
@@ -46,7 +49,7 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
Set<BlockPos> foliage = new LinkedHashSet<>();
|
||||
|
||||
placeTrunk(spine, bottomRadius, logs, random);
|
||||
placeLowerMass(spine, bottomRadius, logs, foliage, random, veilRadius);
|
||||
placeRootWaves(spine, bottomRadius, logs, foliage, random, veilRadius);
|
||||
placeBranches(spine, branchCount, branchLength, logs, foliage, random, veilRadius);
|
||||
placeVeilCurtains(spine, foliage, random, veilRadius);
|
||||
|
||||
@@ -75,6 +78,21 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static BlockPos findCeilingOrigin(WorldGenLevel level, BlockPos origin, int searchRange) {
|
||||
if (level.getBlockState(origin).isAir() && level.getBlockState(origin.above()).isFaceSturdy(level, origin.above(), Direction.DOWN)) {
|
||||
return origin;
|
||||
}
|
||||
Optional<Column> optional = Column.scan(level, origin, searchRange, state -> state.isAir(), state -> !state.isAir());
|
||||
if (optional.isEmpty()) {
|
||||
return origin;
|
||||
}
|
||||
OptionalInt ceiling = optional.get().getCeiling();
|
||||
if (ceiling.isEmpty()) {
|
||||
return origin;
|
||||
}
|
||||
return origin.atY(ceiling.getAsInt() - 1);
|
||||
}
|
||||
|
||||
private List<BlockPos> buildSpine(BlockPos origin, int height, RandomSource random) {
|
||||
List<BlockPos> spine = new ArrayList<>(height);
|
||||
BlockPos current = origin;
|
||||
@@ -100,7 +118,11 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
for (int index = 0; index < spine.size(); index++) {
|
||||
BlockPos center = spine.get(index);
|
||||
float progress = spine.size() == 1 ? 1.0F : index / (float) (spine.size() - 1);
|
||||
int radius = Mth.clamp(Math.round(progress * bottomRadius), 0, bottomRadius);
|
||||
float wave = Mth.sin(progress * Mth.PI * 2.75F) * 0.55F + Mth.sin(progress * Mth.PI * 5.5F) * 0.25F;
|
||||
int radius = Mth.clamp(Math.round((0.45F + progress * 0.3F + wave * 0.22F) * bottomRadius), 0, Math.max(1, bottomRadius - 1));
|
||||
if (index < 2) {
|
||||
radius = Math.max(radius, 1);
|
||||
}
|
||||
fillTrunkLayer(center, radius, logs, random);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +140,7 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
if (dist > radiusSq + 1) {
|
||||
continue;
|
||||
}
|
||||
if (dist > radiusSq - radius && random.nextFloat() < 0.2F) {
|
||||
if (dist > radiusSq - radius && random.nextFloat() < 0.48F) {
|
||||
continue;
|
||||
}
|
||||
putLog(logs, center.offset(dx, 0, dz), Direction.Axis.Y);
|
||||
@@ -126,7 +148,7 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
}
|
||||
}
|
||||
|
||||
private void placeLowerMass(
|
||||
private void placeRootWaves(
|
||||
List<BlockPos> spine,
|
||||
int bottomRadius,
|
||||
Map<BlockPos, Direction.Axis> logs,
|
||||
@@ -134,14 +156,28 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
RandomSource random,
|
||||
int veilRadius
|
||||
) {
|
||||
int start = Math.max(0, spine.size() - Math.max(3, bottomRadius + 2));
|
||||
for (int index = start; index < spine.size(); index++) {
|
||||
int waveCount = Math.max(4, bottomRadius + 3);
|
||||
for (int wave = 0; wave < waveCount; wave++) {
|
||||
int index = Mth.nextInt(random, 0, Math.max(0, spine.size() - 3));
|
||||
BlockPos center = spine.get(index);
|
||||
int extraRadius = Math.max(1, bottomRadius - Math.max(0, spine.size() - 1 - index));
|
||||
for (int dy = 0; dy <= Math.min(2, index - start); dy++) {
|
||||
fillTrunkLayer(center.below(dy), extraRadius, logs, random);
|
||||
Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(random);
|
||||
int length = Mth.nextInt(random, 2, Math.max(3, bottomRadius + 3));
|
||||
BlockPos cursor = center;
|
||||
BlockPos previous = center;
|
||||
for (int step = 0; step < length; step++) {
|
||||
cursor = cursor.relative(direction);
|
||||
if (random.nextFloat() < 0.55F) {
|
||||
cursor = cursor.below();
|
||||
}
|
||||
if (step > 1 && random.nextFloat() < 0.38F) {
|
||||
direction = random.nextBoolean() ? direction.getClockWise() : direction.getCounterClockWise();
|
||||
}
|
||||
putLog(logs, cursor, axisForSegment(previous, cursor));
|
||||
previous = cursor;
|
||||
}
|
||||
if (random.nextFloat() < 0.75F) {
|
||||
placeVeilRibbon(foliage, cursor, direction, Math.max(2, veilRadius + random.nextInt(2)), random);
|
||||
}
|
||||
placeVeilCluster(foliage, center.below(), Math.max(1, veilRadius), random, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +215,7 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
previous = cursor;
|
||||
}
|
||||
|
||||
placeVeilCluster(foliage, cursor, veilRadius + random.nextInt(2), random, true);
|
||||
placeVeilCluster(foliage, cursor.below(1 + random.nextInt(2)), Math.max(1, veilRadius - 1), random, true);
|
||||
placeVeilRibbon(foliage, cursor, direction, Math.max(2, veilRadius + random.nextInt(3)), random);
|
||||
|
||||
if (random.nextFloat() < 0.45F) {
|
||||
BlockPos fork = cursor;
|
||||
@@ -191,44 +226,41 @@ public class NadirTreeFeature extends Feature<NadirTreeConfiguration> {
|
||||
putLog(logs, next, axisForSegment(fork, next));
|
||||
fork = next;
|
||||
}
|
||||
placeVeilCluster(foliage, fork, Math.max(1, veilRadius - 1), random, true);
|
||||
placeVeilRibbon(foliage, fork, forkDirection, Math.max(2, veilRadius), random);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void placeVeilCurtains(List<BlockPos> spine, Set<BlockPos> foliage, RandomSource random, int veilRadius) {
|
||||
for (int index = 1; index < spine.size(); index++) {
|
||||
if (random.nextFloat() > 0.33F) {
|
||||
if (random.nextFloat() > 0.24F) {
|
||||
continue;
|
||||
}
|
||||
BlockPos anchor = spine.get(index);
|
||||
Direction side = Direction.Plane.HORIZONTAL.getRandomDirection(random);
|
||||
BlockPos start = anchor.relative(side);
|
||||
int length = 2 + random.nextInt(Math.max(2, veilRadius + 1));
|
||||
for (int i = 0; i < length; i++) {
|
||||
BlockPos pos = start.below(i);
|
||||
foliage.add(pos);
|
||||
if (random.nextFloat() < 0.22F) {
|
||||
foliage.add(pos.relative(side.getClockWise()));
|
||||
}
|
||||
}
|
||||
placeVeilRibbon(foliage, anchor.relative(side), side, Math.max(2, veilRadius + random.nextInt(3)), random);
|
||||
}
|
||||
}
|
||||
|
||||
private void placeVeilCluster(Set<BlockPos> foliage, BlockPos center, int radius, RandomSource random, boolean stretchDown) {
|
||||
int radiusSq = radius * radius;
|
||||
for (int dx = -radius; dx <= radius; dx++) {
|
||||
for (int dz = -radius; dz <= radius; dz++) {
|
||||
for (int dy = -radius; dy <= 1; dy++) {
|
||||
int adjustedDy = stretchDown ? Math.max(0, -dy) : Math.abs(dy);
|
||||
int dist = dx * dx + dz * dz + adjustedDy * adjustedDy;
|
||||
if (dist > radiusSq + 1) {
|
||||
continue;
|
||||
private void placeVeilRibbon(Set<BlockPos> foliage, BlockPos start, Direction flow, int length, RandomSource random) {
|
||||
Direction side = random.nextBoolean() ? flow.getClockWise() : flow.getCounterClockWise();
|
||||
BlockPos cursor = start;
|
||||
for (int step = 0; step < length; step++) {
|
||||
foliage.add(cursor);
|
||||
if (random.nextFloat() < 0.34F) {
|
||||
foliage.add(cursor.relative(side));
|
||||
}
|
||||
if (dist > radiusSq - radius && random.nextFloat() < 0.28F) {
|
||||
continue;
|
||||
if (random.nextFloat() < 0.18F) {
|
||||
foliage.add(cursor.relative(side.getOpposite()));
|
||||
}
|
||||
foliage.add(center.offset(dx, dy, dz));
|
||||
cursor = cursor.below();
|
||||
if (step > 0 && random.nextFloat() < 0.4F) {
|
||||
cursor = cursor.relative(random.nextBoolean() ? side : side.getOpposite());
|
||||
}
|
||||
if (random.nextFloat() < 0.18F) {
|
||||
BlockPos drift = cursor.relative(flow);
|
||||
if (random.nextBoolean()) {
|
||||
foliage.add(drift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+40
-14
@@ -23,6 +23,8 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
private static final int VERTICAL_NOISE_SCALE = 8;
|
||||
private static final double DUNES_SELECTOR_CUTOFF = 0.38D;
|
||||
private static final double HILLS_SELECTOR_CUTOFF = 0.24D;
|
||||
private static final double NADIR_FOREST_SELECTOR_MIN = 0.42D;
|
||||
private static final double NADIR_FOREST_SELECTOR_MAX = 0.66D;
|
||||
private static final ResourceKey<Biome> NIGHTMARE_WASTES = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "nightmare_wastes")
|
||||
@@ -31,6 +33,10 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
Registries.BIOME,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dream_dunes")
|
||||
);
|
||||
private static final ResourceKey<Biome> VORTEX_EXPANSE = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "vortex_expanse")
|
||||
);
|
||||
private static final ResourceKey<Biome> UMBRAL_HILLS = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "umbral_hills")
|
||||
@@ -39,16 +45,17 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
Registries.BIOME,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "lucid_pools")
|
||||
);
|
||||
private static final ResourceKey<Biome> UNDERSIDE = ResourceKey.create(
|
||||
private static final ResourceKey<Biome> NADIR_FOREST = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "thoraxis_underside")
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "nadir_forest")
|
||||
);
|
||||
|
||||
public static final MapCodec<ThoraxisBiomeSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||
MultiNoiseBiomeSource.DIRECT_CODEC.forGetter(ThoraxisBiomeSource::parameters),
|
||||
Codec.INT.optionalFieldOf("dream_dunes_max_y", 96).forGetter(ThoraxisBiomeSource::dreamDunesMaxY),
|
||||
Codec.INT.optionalFieldOf("umbral_hills_max_y", 100).forGetter(ThoraxisBiomeSource::umbralHillsMaxY),
|
||||
Codec.INT.optionalFieldOf("lucid_pools_min_y", 116).forGetter(ThoraxisBiomeSource::lucidPoolsMinY)
|
||||
Codec.INT.optionalFieldOf("lucid_pools_min_y", 116).forGetter(ThoraxisBiomeSource::lucidPoolsMinY),
|
||||
Codec.INT.optionalFieldOf("nadir_forest_min_y", 128).forGetter(ThoraxisBiomeSource::nadirForestMinY)
|
||||
).apply(instance, ThoraxisBiomeSource::new));
|
||||
|
||||
private final Climate.ParameterList<Holder<Biome>> parameters;
|
||||
@@ -56,30 +63,35 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
private final int dreamDunesMaxY;
|
||||
private final int umbralHillsMaxY;
|
||||
private final int lucidPoolsMinY;
|
||||
private final int nadirForestMinY;
|
||||
private final int dreamDunesMaxQuartY;
|
||||
private final int umbralHillsMaxQuartY;
|
||||
private final int lucidPoolsMinQuartY;
|
||||
private final int nadirForestMinQuartY;
|
||||
private volatile boolean biomesResolved;
|
||||
private Holder<Biome> nightmareWastesBiome;
|
||||
private Holder<Biome> dreamDunesBiome;
|
||||
private Holder<Biome> vortexExpanseBiome;
|
||||
private Holder<Biome> umbralHillsBiome;
|
||||
private Holder<Biome> lucidPoolsBiome;
|
||||
private Holder<Biome> undersideBiome;
|
||||
private Holder<Biome> nadirForestBiome;
|
||||
|
||||
private static final ThreadLocal<Long2DoubleOpenHashMap> REGION_CACHE =
|
||||
ThreadLocal.withInitial(() -> new Long2DoubleOpenHashMap(512));
|
||||
private static final ThreadLocal<Long2DoubleOpenHashMap> VERTICAL_CACHE =
|
||||
ThreadLocal.withInitial(() -> new Long2DoubleOpenHashMap(64));
|
||||
|
||||
public ThoraxisBiomeSource(Climate.ParameterList<Holder<Biome>> parameters, int dreamDunesMaxY, int umbralHillsMaxY, int lucidPoolsMinY) {
|
||||
public ThoraxisBiomeSource(Climate.ParameterList<Holder<Biome>> parameters, int dreamDunesMaxY, int umbralHillsMaxY, int lucidPoolsMinY, int nadirForestMinY) {
|
||||
this.parameters = parameters;
|
||||
this.delegate = MultiNoiseBiomeSource.createFromList(parameters);
|
||||
this.dreamDunesMaxY = dreamDunesMaxY;
|
||||
this.umbralHillsMaxY = umbralHillsMaxY;
|
||||
this.lucidPoolsMinY = lucidPoolsMinY;
|
||||
this.nadirForestMinY = nadirForestMinY;
|
||||
this.dreamDunesMaxQuartY = QuartPos.fromBlock(dreamDunesMaxY);
|
||||
this.umbralHillsMaxQuartY = QuartPos.fromBlock(umbralHillsMaxY);
|
||||
this.lucidPoolsMinQuartY = QuartPos.fromBlock(lucidPoolsMinY);
|
||||
this.nadirForestMinQuartY = QuartPos.fromBlock(nadirForestMinY);
|
||||
}
|
||||
|
||||
private void resolveBiomesIfNeeded() {
|
||||
@@ -92,9 +104,10 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
}
|
||||
this.nightmareWastesBiome = this.findBiome(NIGHTMARE_WASTES);
|
||||
this.dreamDunesBiome = this.findBiome(DREAM_DUNES);
|
||||
this.vortexExpanseBiome = this.findBiome(VORTEX_EXPANSE);
|
||||
this.umbralHillsBiome = this.findBiome(UMBRAL_HILLS);
|
||||
this.lucidPoolsBiome = this.findBiome(LUCID_POOLS);
|
||||
this.undersideBiome = this.findBiome(UNDERSIDE);
|
||||
this.nadirForestBiome = this.findBiome(NADIR_FOREST);
|
||||
this.biomesResolved = true;
|
||||
}
|
||||
}
|
||||
@@ -107,6 +120,10 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
return this.lucidPoolsMinY;
|
||||
}
|
||||
|
||||
private int nadirForestMinY() {
|
||||
return this.nadirForestMinY;
|
||||
}
|
||||
|
||||
private int dreamDunesMaxY() {
|
||||
return this.dreamDunesMaxY;
|
||||
}
|
||||
@@ -128,21 +145,29 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
@Override
|
||||
public Holder<Biome> getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) {
|
||||
this.resolveBiomesIfNeeded();
|
||||
if (y < 0 && this.undersideBiome != null) {
|
||||
return this.undersideBiome;
|
||||
}
|
||||
|
||||
if (y >= this.lucidPoolsMinQuartY && this.lucidPoolsBiome != null) {
|
||||
return this.lucidPoolsBiome;
|
||||
if (y < 0 && this.dreamDunesBiome != null) {
|
||||
return this.dreamDunesBiome;
|
||||
}
|
||||
|
||||
double region = cachedRegionNoise(x, z);
|
||||
double vertical = cachedVerticalNoise(y);
|
||||
double dreamDunesSelector = region * 0.65D + (1.0D - vertical) * 0.35D;
|
||||
double umbralHillsSelector = region * 0.55D + vertical * 0.45D;
|
||||
double nadirForestSelector = region * 0.78D + vertical * 0.22D;
|
||||
|
||||
if (this.dreamDunesBiome != null && y <= this.dreamDunesMaxQuartY && dreamDunesSelector <= DUNES_SELECTOR_CUTOFF) {
|
||||
return this.dreamDunesBiome;
|
||||
if (this.nadirForestBiome != null
|
||||
&& y >= this.nadirForestMinQuartY
|
||||
&& nadirForestSelector >= NADIR_FOREST_SELECTOR_MIN
|
||||
&& nadirForestSelector <= NADIR_FOREST_SELECTOR_MAX) {
|
||||
return this.nadirForestBiome;
|
||||
}
|
||||
|
||||
if (y >= this.lucidPoolsMinQuartY && this.lucidPoolsBiome != null) {
|
||||
return this.lucidPoolsBiome;
|
||||
}
|
||||
|
||||
if (this.vortexExpanseBiome != null && y <= this.dreamDunesMaxQuartY && dreamDunesSelector <= DUNES_SELECTOR_CUTOFF) {
|
||||
return this.vortexExpanseBiome;
|
||||
}
|
||||
|
||||
if (this.umbralHillsBiome != null && y <= this.umbralHillsMaxQuartY && umbralHillsSelector <= HILLS_SELECTOR_CUTOFF) {
|
||||
@@ -158,6 +183,7 @@ public final class ThoraxisBiomeSource extends BiomeSource {
|
||||
this.delegate.addDebugInfo(debug, pos, sampler);
|
||||
debug.add("Thoraxis selector: mixed vertical/region noise");
|
||||
debug.add("Thoraxis Lucid Pools: y>=" + this.lucidPoolsMinY);
|
||||
debug.add("Thoraxis Nadir Forest: y>=" + this.nadirForestMinY);
|
||||
}
|
||||
|
||||
private Holder<Biome> findBiome(ResourceKey<Biome> key) {
|
||||
|
||||
+38
-4
@@ -2,19 +2,24 @@ package com.craisinlord.antarchy.content.worldgen.thoraxis;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.block.DreamSandBlock;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityTransition;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public final class ThoraxisUndersideManager {
|
||||
public static final int GRAVITY_FLIP_Y = 0;
|
||||
@@ -43,10 +48,7 @@ public final class ThoraxisUndersideManager {
|
||||
if (entity instanceof LivingEntity living) {
|
||||
UUID uuid = entity.getUUID();
|
||||
if (inUnderside) {
|
||||
if (!living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
|
||||
living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), EFFECT_DURATION_TICKS, 0, true, false, false));
|
||||
UNDERSIDE_APPLIED_EFFECT.add(uuid);
|
||||
}
|
||||
applyUndersideInversion(living);
|
||||
} else if (UNDERSIDE_APPLIED_EFFECT.remove(uuid)) {
|
||||
if (living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
|
||||
living.removeEffect(AntarchyObjects.INVERTED_EFFECT.get());
|
||||
@@ -84,6 +86,38 @@ public final class ThoraxisUndersideManager {
|
||||
UNDERSIDE_FORCED_GRAVITY.retainAll(activeThisTick);
|
||||
}
|
||||
|
||||
public static void applyUndersideInversion(LivingEntity living) {
|
||||
UNDERSIDE_APPLIED_EFFECT.add(living.getUUID());
|
||||
if (!living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
|
||||
living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), EFFECT_DURATION_TICKS, 0, true, false, false));
|
||||
}
|
||||
if (AntarchyGravityApi.getGravityDirection(living) != AntarchyGravityDirection.UP
|
||||
|| !AntarchyGravityApi.isGravityForced(living)) {
|
||||
AntarchyGravityApi.setForcedGravityDirection(living, AntarchyGravityDirection.UP, TRANSITION);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shouldSpawnInvertedOnDreamSand(ServerLevelAccessor level, BlockPos pos) {
|
||||
if (!isThoraxis(level.getLevel()) || pos.getY() >= GRAVITY_FLIP_Y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockState bodyState = level.getBlockState(pos);
|
||||
if (!bodyState.isAir() && !bodyState.getCollisionShape(level, pos).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockPos supportPos = pos.above();
|
||||
BlockState supportState = level.getBlockState(supportPos);
|
||||
if (!(supportState.getBlock() instanceof DreamSandBlock)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return supportState.isFaceSturdy(level, supportPos, Direction.DOWN)
|
||||
&& level.getFluidState(pos).isEmpty()
|
||||
&& level.isEmptyBlock(pos.below());
|
||||
}
|
||||
|
||||
public static boolean isThoraxis(Level level) {
|
||||
return level.dimension().location().equals(THORAXIS_DIMENSION);
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.craisinlord.antarchy.content.worldgen.thoraxis;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
||||
public record TyphoniteSpikeConfiguration(
|
||||
int floorToCeilingSearchRange,
|
||||
int radius,
|
||||
int maxColumnHeight,
|
||||
int heightDeviation,
|
||||
float chanceOfColumnAtMaxDistanceFromCenter,
|
||||
int maxDistanceFromCenterAffectingChanceOfColumn,
|
||||
int maxDistanceFromCenterAffectingHeightBias,
|
||||
int maxHeightDifference
|
||||
) implements FeatureConfiguration {
|
||||
public static final Codec<TyphoniteSpikeConfiguration> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Codec.intRange(1, 128).fieldOf("floor_to_ceiling_search_range").forGetter(TyphoniteSpikeConfiguration::floorToCeilingSearchRange),
|
||||
Codec.intRange(1, 32).fieldOf("radius").forGetter(TyphoniteSpikeConfiguration::radius),
|
||||
Codec.intRange(1, 32).fieldOf("max_column_height").forGetter(TyphoniteSpikeConfiguration::maxColumnHeight),
|
||||
Codec.intRange(1, 16).fieldOf("height_deviation").forGetter(TyphoniteSpikeConfiguration::heightDeviation),
|
||||
Codec.floatRange(0.0F, 1.0F).fieldOf("chance_of_column_at_max_distance_from_center").forGetter(TyphoniteSpikeConfiguration::chanceOfColumnAtMaxDistanceFromCenter),
|
||||
Codec.intRange(1, 64).fieldOf("max_distance_from_center_affecting_chance_of_column").forGetter(TyphoniteSpikeConfiguration::maxDistanceFromCenterAffectingChanceOfColumn),
|
||||
Codec.intRange(1, 64).fieldOf("max_distance_from_center_affecting_height_bias").forGetter(TyphoniteSpikeConfiguration::maxDistanceFromCenterAffectingHeightBias),
|
||||
Codec.intRange(0, 32).fieldOf("max_height_difference").forGetter(TyphoniteSpikeConfiguration::maxHeightDifference)
|
||||
).apply(instance, TyphoniteSpikeConfiguration::new));
|
||||
}
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
package com.craisinlord.antarchy.content.worldgen.thoraxis;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.mojang.serialization.Codec;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
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.PointedDripstoneBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.DripstoneThickness;
|
||||
import net.minecraft.world.level.levelgen.Column;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
public class TyphoniteSpikeFeature extends Feature<TyphoniteSpikeConfiguration> {
|
||||
private static final ResourceLocation TYPHONITE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "typhonite");
|
||||
private static final ResourceLocation TYPHONITE_SPIKE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "typhonite_spike");
|
||||
|
||||
public TyphoniteSpikeFeature(Codec<TyphoniteSpikeConfiguration> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<TyphoniteSpikeConfiguration> context) {
|
||||
WorldGenLevel level = context.level();
|
||||
BlockPos origin = context.origin();
|
||||
TyphoniteSpikeConfiguration config = context.config();
|
||||
RandomSource random = context.random();
|
||||
if (!level.getBlockState(origin).isAir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean placedAny = false;
|
||||
int radius = config.radius();
|
||||
for (int dx = -radius; dx <= radius; dx++) {
|
||||
for (int dz = -radius; dz <= radius; dz++) {
|
||||
double chance = this.getChanceOfColumn(radius, dx, dz, config);
|
||||
if (chance <= 0.0D) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.placeColumn(level, random, origin.offset(dx, 0, dz), dx, dz, chance, config)) {
|
||||
placedAny = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return placedAny;
|
||||
}
|
||||
|
||||
private boolean placeColumn(
|
||||
WorldGenLevel level,
|
||||
RandomSource random,
|
||||
BlockPos pos,
|
||||
int dx,
|
||||
int dz,
|
||||
double chance,
|
||||
TyphoniteSpikeConfiguration config
|
||||
) {
|
||||
Optional<Column> optional = Column.scan(level, pos, config.floorToCeilingSearchRange(), state -> state.isAir(), state -> !state.isAir());
|
||||
if (optional.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Column column = optional.get();
|
||||
OptionalInt ceiling = column.getCeiling();
|
||||
OptionalInt floor = column.getFloor();
|
||||
boolean canGrowDown = ceiling.isPresent() && isTyphonite(level.getBlockState(pos.atY(ceiling.getAsInt())));
|
||||
boolean canGrowUp = floor.isPresent() && isTyphonite(level.getBlockState(pos.atY(floor.getAsInt())));
|
||||
if (!canGrowDown && !canGrowUp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int downLength = 0;
|
||||
int upLength = 0;
|
||||
if (canGrowDown) {
|
||||
int maxLength = this.getMaxLength(config, ceiling, floor);
|
||||
downLength = this.getSpikeHeight(random, dx, dz, chance, maxLength, config);
|
||||
}
|
||||
if (canGrowUp) {
|
||||
int maxLength = this.getMaxLength(config, ceiling, floor);
|
||||
if (downLength > 0) {
|
||||
upLength = Mth.clamp(
|
||||
downLength + Mth.randomBetweenInclusive(random, -config.maxHeightDifference(), config.maxHeightDifference()),
|
||||
0,
|
||||
maxLength
|
||||
);
|
||||
} else {
|
||||
upLength = this.getSpikeHeight(random, dx, dz, chance, maxLength, config);
|
||||
}
|
||||
}
|
||||
|
||||
if (ceiling.isPresent() && floor.isPresent() && downLength > 0 && upLength > 0 && ceiling.getAsInt() - downLength <= floor.getAsInt() + upLength) {
|
||||
int floorY = floor.getAsInt();
|
||||
int ceilingY = ceiling.getAsInt();
|
||||
int minSplit = Math.max(ceilingY - downLength, floorY + 1);
|
||||
int maxSplit = Math.min(floorY + upLength, ceilingY - 1);
|
||||
int split = Mth.randomBetweenInclusive(random, minSplit, maxSplit + 1);
|
||||
int tipBelowCeiling = split - 1;
|
||||
downLength = ceilingY - split;
|
||||
upLength = tipBelowCeiling - floorY;
|
||||
}
|
||||
|
||||
boolean placedAny = false;
|
||||
if (downLength > 0 && ceiling.isPresent()) {
|
||||
placedAny |= this.growPointedTyphonite(level, pos.atY(ceiling.getAsInt() - 1), Direction.DOWN, downLength);
|
||||
}
|
||||
if (upLength > 0 && floor.isPresent()) {
|
||||
placedAny |= this.growPointedTyphonite(level, pos.atY(floor.getAsInt() + 1), Direction.UP, upLength);
|
||||
}
|
||||
return placedAny;
|
||||
}
|
||||
|
||||
private int getMaxLength(TyphoniteSpikeConfiguration config, OptionalInt ceiling, OptionalInt floor) {
|
||||
if (ceiling.isPresent() && floor.isPresent()) {
|
||||
return Math.min(config.maxColumnHeight(), ceiling.getAsInt() - floor.getAsInt() - 1);
|
||||
}
|
||||
return config.maxColumnHeight();
|
||||
}
|
||||
|
||||
private boolean growPointedTyphonite(WorldGenLevel level, BlockPos rootStart, Direction direction, int length) {
|
||||
Block typhoniteSpike = BuiltInRegistries.BLOCK.get(TYPHONITE_SPIKE_ID);
|
||||
boolean placedAny = false;
|
||||
for (int offset = 0; offset < length; offset++) {
|
||||
BlockPos spikePos = rootStart.relative(direction, offset);
|
||||
if (spikePos.getY() < level.getMinBuildHeight() || spikePos.getY() >= level.getMaxBuildHeight()) {
|
||||
break;
|
||||
}
|
||||
if (!level.getBlockState(spikePos).isAir()) {
|
||||
break;
|
||||
}
|
||||
|
||||
BlockState spikeState = typhoniteSpike.defaultBlockState()
|
||||
.setValue(PointedDripstoneBlock.TIP_DIRECTION, direction)
|
||||
.setValue(PointedDripstoneBlock.THICKNESS, getThicknessForRootOffset(offset, length))
|
||||
.setValue(PointedDripstoneBlock.WATERLOGGED, false);
|
||||
if (!spikeState.canSurvive(level, spikePos)) {
|
||||
break;
|
||||
}
|
||||
|
||||
level.setBlock(spikePos, spikeState, 3);
|
||||
placedAny = true;
|
||||
}
|
||||
return placedAny;
|
||||
}
|
||||
|
||||
private static DripstoneThickness getThicknessForRootOffset(int offsetFromRoot, int length) {
|
||||
if (length <= 1) {
|
||||
return DripstoneThickness.TIP;
|
||||
}
|
||||
if (offsetFromRoot == length - 1) {
|
||||
return DripstoneThickness.TIP;
|
||||
}
|
||||
if (offsetFromRoot == length - 2) {
|
||||
return DripstoneThickness.FRUSTUM;
|
||||
}
|
||||
if (offsetFromRoot == 0) {
|
||||
return DripstoneThickness.BASE;
|
||||
}
|
||||
return DripstoneThickness.MIDDLE;
|
||||
}
|
||||
|
||||
private int getSpikeHeight(RandomSource random, int dx, int dz, double chance, int maxHeight, TyphoniteSpikeConfiguration config) {
|
||||
if (maxHeight <= 0 || random.nextDouble() > chance) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int distance = Math.abs(dx) + Math.abs(dz);
|
||||
float mean = (float) Mth.clampedMap(
|
||||
(double) distance,
|
||||
0.0D,
|
||||
(double) config.maxDistanceFromCenterAffectingHeightBias(),
|
||||
(double) maxHeight,
|
||||
1.0D
|
||||
);
|
||||
int sampled = Math.round((float) (mean + random.nextGaussian() * config.heightDeviation()));
|
||||
return Mth.clamp(sampled, 1, maxHeight);
|
||||
}
|
||||
|
||||
private double getChanceOfColumn(int radius, int dx, int dz, TyphoniteSpikeConfiguration config) {
|
||||
int remainingX = radius - Math.abs(dx);
|
||||
int remainingZ = radius - Math.abs(dz);
|
||||
int edgeDistance = Math.min(remainingX, remainingZ);
|
||||
return Mth.clampedMap(
|
||||
(double) edgeDistance,
|
||||
0.0D,
|
||||
(double) config.maxDistanceFromCenterAffectingChanceOfColumn(),
|
||||
(double) config.chanceOfColumnAtMaxDistanceFromCenter(),
|
||||
1.0D
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean isTyphonite(BlockState state) {
|
||||
return BuiltInRegistries.BLOCK.getKey(state.getBlock()).equals(TYPHONITE_ID);
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import com.craisinlord.antarchy.content.item.BloodCrystalKatanaItem;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
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.CallbackInfo;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class BloodCrystalKatanaDashPhaseMixin {
|
||||
|
||||
@Inject(method = "push(Lnet/minecraft/world/entity/Entity;)V", at = @At("HEAD"), cancellable = true)
|
||||
private void antarchy$katanaDashPassThrough(Entity entity, CallbackInfo ci) {
|
||||
Entity self = (Entity) (Object) this;
|
||||
if (BloodCrystalKatanaItem.isDashing(self) || BloodCrystalKatanaItem.isDashing(entity)) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -2,9 +2,9 @@ package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.entity.UpwardFallingBlockEntity;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -12,14 +12,14 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(FallingBlockEntity.class)
|
||||
@Mixin(UpwardFallingBlockEntity.class)
|
||||
public abstract class DreamSandFallingSpeedMixin {
|
||||
private static final ResourceLocation DREAM_SAND_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dream_sand");
|
||||
|
||||
@Shadow public abstract BlockState getBlockState();
|
||||
|
||||
@Inject(method = "getDefaultGravity", at = @At("RETURN"), cancellable = true)
|
||||
private void antarchy$slowDreamSandFall(CallbackInfoReturnable<Double> cir) {
|
||||
@Inject(method = "getRiseAccel", at = @At("RETURN"), cancellable = true, remap = false)
|
||||
private void antarchy$slowDreamSandRise(CallbackInfoReturnable<Double> cir) {
|
||||
if (BuiltInRegistries.BLOCK.getKey(this.getBlockState().getBlock()).equals(DREAM_SAND_ID)) {
|
||||
cir.setReturnValue(cir.getReturnValue() * AntarchySettings.dreamSandFallingBlockGravityMultiplier());
|
||||
}
|
||||
|
||||
+87
-3
@@ -1,14 +1,23 @@
|
||||
package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.block.DreamSandBlock;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
|
||||
import com.craisinlord.antarchy.content.movement.DreamSandLowGravityAccess;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
/*
|
||||
* Stores per-entity dream sand low-grav state.
|
||||
*/
|
||||
public abstract class DreamSandLowGravityMixin implements DreamSandLowGravityAccess {
|
||||
@Unique
|
||||
private boolean antarchy$dreamSandLowGravityActive;
|
||||
@@ -46,4 +55,79 @@ public abstract class DreamSandLowGravityMixin implements DreamSandLowGravityAcc
|
||||
public void antarchy$setDreamSandLandingGraceTicks(int ticks) {
|
||||
this.antarchy$dreamSandLandingGraceTicks = Math.max(0, ticks);
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("TAIL"))
|
||||
private void antarchy$updateDreamSandLowGravity(CallbackInfo ci) {
|
||||
LivingEntity self = (LivingEntity) (Object) this;
|
||||
if (!AntarchySettings.dreamSandEnabled()) {
|
||||
this.antarchy$clearDreamSandLowGravity();
|
||||
return;
|
||||
}
|
||||
|
||||
boolean supportedByDreamSand = this.antarchy$isSupportedByDreamSand(self);
|
||||
int durationTicks = Math.max(1, Mth.ceil(AntarchySettings.dreamSandEffectDurationSeconds() * 20.0D));
|
||||
if (supportedByDreamSand) {
|
||||
this.antarchy$dreamSandLowGravityActive = true;
|
||||
this.antarchy$dreamSandLowGravityTicksRemaining = durationTicks;
|
||||
this.antarchy$dreamSandLandingGraceTicks = 5;
|
||||
} else if (this.antarchy$dreamSandLowGravityTicksRemaining > 0) {
|
||||
this.antarchy$dreamSandLowGravityTicksRemaining--;
|
||||
this.antarchy$dreamSandLowGravityActive = true;
|
||||
} else {
|
||||
this.antarchy$dreamSandLowGravityActive = false;
|
||||
}
|
||||
|
||||
if (this.antarchy$dreamSandLandingGraceTicks > 0 && !supportedByDreamSand) {
|
||||
this.antarchy$dreamSandLandingGraceTicks--;
|
||||
}
|
||||
|
||||
if (!this.antarchy$dreamSandLowGravityActive || self.onGround() || self.onClimbable() || self.isInWaterOrBubble() || self.isInLava()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AntarchyGravityDirection gravityDirection = AntarchyGravityApi.getGravityDirection(self);
|
||||
Vec3 localMotion = AntarchyGravityRotationUtil.vecWorldToPlayer(self.getDeltaMovement(), gravityDirection);
|
||||
if (localMotion.y >= 0.0D) {
|
||||
return;
|
||||
}
|
||||
|
||||
double gravityMultiplier = Math.max(0.0D, Math.min(1.0D, AntarchySettings.dreamSandGravityMultiplier()));
|
||||
Vec3 adjustedLocalMotion = new Vec3(localMotion.x, localMotion.y * gravityMultiplier, localMotion.z);
|
||||
self.setDeltaMovement(AntarchyGravityRotationUtil.vecPlayerToWorld(adjustedLocalMotion, gravityDirection));
|
||||
self.fallDistance = 0.0F;
|
||||
this.antarchy$dreamSandLandingGraceTicks = 5;
|
||||
}
|
||||
|
||||
@Inject(method = "jumpFromGround", at = @At("TAIL"))
|
||||
private void antarchy$boostDreamSandJump(CallbackInfo ci) {
|
||||
if (!this.antarchy$dreamSandLowGravityActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
LivingEntity self = (LivingEntity) (Object) this;
|
||||
AntarchyGravityDirection gravityDirection = AntarchyGravityApi.getGravityDirection(self);
|
||||
Vec3 localMotion = AntarchyGravityRotationUtil.vecWorldToPlayer(self.getDeltaMovement(), gravityDirection);
|
||||
if (localMotion.y <= 0.0D) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 adjustedLocalMotion = new Vec3(
|
||||
localMotion.x,
|
||||
localMotion.y * AntarchySettings.dreamSandJumpVelocityMultiplier(),
|
||||
localMotion.z
|
||||
);
|
||||
self.setDeltaMovement(AntarchyGravityRotationUtil.vecPlayerToWorld(adjustedLocalMotion, gravityDirection));
|
||||
self.fallDistance = 0.0F;
|
||||
this.antarchy$dreamSandLandingGraceTicks = 5;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private boolean antarchy$isSupportedByDreamSand(LivingEntity entity) {
|
||||
AntarchyGravityDirection gravityDirection = AntarchyGravityApi.getGravityDirection(entity);
|
||||
AABB box = entity.getBoundingBox();
|
||||
BlockPos supportPos = gravityDirection.isInverted()
|
||||
? BlockPos.containing(entity.getX(), box.maxY + 0.05D, entity.getZ())
|
||||
: BlockPos.containing(entity.getX(), box.minY - 0.05D, entity.getZ());
|
||||
return entity.level().getBlockState(supportPos).getBlock() instanceof DreamSandBlock;
|
||||
}
|
||||
}
|
||||
+1
-30
@@ -11,9 +11,6 @@ import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
@@ -28,8 +25,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
* Adds the base gravity state and sync hooks to entities.
|
||||
*/
|
||||
public abstract class EntityGravityMixin implements AntarchyGravityAccess {
|
||||
@Unique
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Antarchy/FallDamage");
|
||||
@Unique
|
||||
private static final String ANTARCHY_GRAVITY_DIRECTION_TAG = "AntarchyGravityDirection";
|
||||
@Unique
|
||||
@@ -97,21 +92,7 @@ public abstract class EntityGravityMixin implements AntarchyGravityAccess {
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 localMotion = AntarchyGravityRotationUtil.vecWorldToPlayer(entity.getDeltaMovement(), direction);
|
||||
float previousFallDistance = entity.fallDistance;
|
||||
entity.resetFallDistance();
|
||||
|
||||
if (!entity.level().isClientSide && LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(
|
||||
"[FallDamage] Antiwater contact reset during fluid update: entity={} pos={} localMotion={} previousFallDistance={} onGround={} inWaterStateReturned={}",
|
||||
entity.getClass().getSimpleName(),
|
||||
entity.position(),
|
||||
localMotion,
|
||||
previousFallDistance,
|
||||
entity.onGround(),
|
||||
cir.getReturnValue()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,17 +192,7 @@ public abstract class EntityGravityMixin implements AntarchyGravityAccess {
|
||||
return worldY;
|
||||
}
|
||||
|
||||
double invertedY = -worldY;
|
||||
LOGGER.debug(
|
||||
"[FallDamage] Entity {} inverted checkFallDamage fallback: worldY={} invertedY={} fallDistance={} onGround={} deltaMovement={}",
|
||||
entity.getClass().getSimpleName(),
|
||||
worldY,
|
||||
invertedY,
|
||||
entity.fallDistance,
|
||||
entity.onGround(),
|
||||
entity.getDeltaMovement()
|
||||
);
|
||||
return invertedY;
|
||||
return -worldY;
|
||||
}
|
||||
|
||||
@Unique
|
||||
|
||||
-18
@@ -16,8 +16,6 @@ import net.minecraft.world.entity.MoverType;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -32,9 +30,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
* Fixes move/landing logic that assumes down is always down.
|
||||
*/
|
||||
public abstract class EntityMoveMixin {
|
||||
@Unique
|
||||
private static final Logger ANTARCHY_FALL_LOGGER = LoggerFactory.getLogger("Antarchy/FallDamage");
|
||||
|
||||
@Unique
|
||||
private double antarchy$lastWorldMoveY = 0.0;
|
||||
@Unique
|
||||
@@ -132,20 +127,7 @@ public abstract class EntityMoveMixin {
|
||||
Vec3 delta = endBox.getCenter().subtract(this.antarchy$moveStartBox.getCenter());
|
||||
AABB sweptBox = this.antarchy$moveStartBox.expandTowards(delta).minmax(endBox).inflate(0.05D);
|
||||
if (antarchy$intersectsAntiwater(entity, sweptBox)) {
|
||||
float previousFallDistance = entity.fallDistance;
|
||||
entity.resetFallDistance();
|
||||
if (!entity.level().isClientSide && ANTARCHY_FALL_LOGGER.isDebugEnabled()) {
|
||||
ANTARCHY_FALL_LOGGER.debug(
|
||||
"[FallDamage] Antiwater contact reset during move: entity={} startBox={} endBox={} sweptBox={} playerMoveY={} worldMoveY={} previousFallDistance={}",
|
||||
entity.getClass().getSimpleName(),
|
||||
this.antarchy$moveStartBox,
|
||||
endBox,
|
||||
sweptBox,
|
||||
this.antarchy$lastPlayerMoveY,
|
||||
this.antarchy$lastWorldMoveY,
|
||||
previousFallDistance
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-12
@@ -2,8 +2,6 @@ package com.craisinlord.antarchy.mixins.gravity;
|
||||
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import com.craisinlord.antarchy.content.gravity.GravityWalkNodeEvaluator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
|
||||
import net.minecraft.world.level.pathfinder.NodeEvaluator;
|
||||
import net.minecraft.world.level.pathfinder.PathFinder;
|
||||
@@ -17,20 +15,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
* Makes ground pathing read gravity-aware floor checks.
|
||||
*/
|
||||
public abstract class GroundPathNavigationMixin {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Antarchy/Pathfinding");
|
||||
|
||||
@Inject(method = "createPathFinder", at = @At("HEAD"), cancellable = true)
|
||||
private void antarchy$useGravityEvaluator(int maxVisitedNodes, CallbackInfoReturnable<PathFinder> cir) {
|
||||
var accessor = (PathNavigationAccessor) (Object) this;
|
||||
var mob = accessor.antarchy$getMob();
|
||||
if (AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
LOGGER.debug(
|
||||
"[Path] swap evaluator mob={} maxVisitedNodes={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
maxVisitedNodes
|
||||
);
|
||||
}
|
||||
|
||||
NodeEvaluator evaluator = new GravityWalkNodeEvaluator();
|
||||
accessor.antarchy$setNodeEvaluator(evaluator);
|
||||
cir.setReturnValue(new PathFinder(evaluator, maxVisitedNodes));
|
||||
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
package com.craisinlord.antarchy.mixins.gravity;
|
||||
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(PathNavigation.class)
|
||||
/*
|
||||
* Keeps path debug shapes lined up with gravity-aware nav.
|
||||
*/
|
||||
public abstract class PathNavigationDebugMixin {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Antarchy/Pathfinding");
|
||||
|
||||
@Unique
|
||||
private int antarchy$debugTickCooldown;
|
||||
|
||||
@Inject(method = "moveTo(DDDD)Z", at = @At("HEAD"))
|
||||
private void antarchy$logMoveToPosition(double x, double y, double z, double speed, CallbackInfoReturnable<Boolean> cir) {
|
||||
var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob();
|
||||
if (!AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.debug(
|
||||
"[Path] moveTo(pos) inverted mob={} target=({}, {}, {}) speed={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
speed
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(method = "moveTo(Lnet/minecraft/world/level/pathfinder/Path;D)Z", at = @At("HEAD"))
|
||||
private void antarchy$logMoveToPath(Path path, double speed, CallbackInfoReturnable<Boolean> cir) {
|
||||
var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob();
|
||||
if (!AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.debug(
|
||||
"[Path] moveTo(path) inverted mob={} nodes={} nextIndex={} speed={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
path == null ? -1 : path.getNodeCount(),
|
||||
path == null ? -1 : path.getNextNodeIndex(),
|
||||
speed
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(method = "createPath(DDDI)Lnet/minecraft/world/level/pathfinder/Path;", at = @At("RETURN"))
|
||||
private void antarchy$logCreatePath(double x, double y, double z, int accuracy, CallbackInfoReturnable<Path> cir) {
|
||||
var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob();
|
||||
if (!AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path path = cir.getReturnValue();
|
||||
LOGGER.debug(
|
||||
"[Path] createPath(pos) inverted mob={} target=({}, {}, {}) accuracy={} result={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
accuracy,
|
||||
path == null ? "null" : ("nodes=" + path.getNodeCount() + " nextIndex=" + path.getNextNodeIndex())
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(method = "createPath(Lnet/minecraft/world/entity/Entity;I)Lnet/minecraft/world/level/pathfinder/Path;", at = @At("RETURN"))
|
||||
private void antarchy$logCreatePath(Entity target, int accuracy, CallbackInfoReturnable<Path> cir) {
|
||||
var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob();
|
||||
if (!AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path path = cir.getReturnValue();
|
||||
LOGGER.debug(
|
||||
"[Path] createPath(entity) inverted mob={} target={} accuracy={} result={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
target == null ? "null" : target.getClass().getSimpleName(),
|
||||
accuracy,
|
||||
path == null ? "null" : ("nodes=" + path.getNodeCount() + " nextIndex=" + path.getNextNodeIndex())
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(method = "createPath(Lnet/minecraft/core/BlockPos;I)Lnet/minecraft/world/level/pathfinder/Path;", at = @At("RETURN"))
|
||||
private void antarchy$logCreatePath(BlockPos target, int accuracy, CallbackInfoReturnable<Path> cir) {
|
||||
var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob();
|
||||
if (!AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path path = cir.getReturnValue();
|
||||
LOGGER.debug(
|
||||
"[Path] createPath(blockpos) inverted mob={} target={} accuracy={} result={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
target,
|
||||
accuracy,
|
||||
path == null ? "null" : ("nodes=" + path.getNodeCount() + " nextIndex=" + path.getNextNodeIndex())
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void antarchy$logTick(CallbackInfo ci) {
|
||||
var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob();
|
||||
if (!AntarchyGravityApi.isGravityInverted(mob)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.antarchy$debugTickCooldown-- > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.antarchy$debugTickCooldown = 20;
|
||||
Path path = ((PathNavigationAccessor) (Object) this).antarchy$getPath();
|
||||
LOGGER.debug(
|
||||
"[Path] tick inverted mob={} pathPresent={} pathDone={}",
|
||||
mob.getClass().getSimpleName(),
|
||||
path != null,
|
||||
path != null && path.isDone()
|
||||
);
|
||||
}
|
||||
}
|
||||
-9
@@ -9,8 +9,6 @@ import net.minecraft.world.entity.player.Abilities;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -24,8 +22,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
*/
|
||||
public abstract class PlayerSneakMixin {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Antarchy/Sneak");
|
||||
|
||||
@Shadow @Final private Abilities abilities;
|
||||
@Shadow protected abstract boolean isStayingOnGroundSurface();
|
||||
|
||||
@@ -52,9 +48,6 @@ public abstract class PlayerSneakMixin {
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.debug("[Sneak] inverted player maybeBackOffFromEdge: isNearCeiling={} flying={} stayOnGround={} type={}",
|
||||
isNearCeiling, this.abilities.flying, this.isStayingOnGroundSurface(), type);
|
||||
|
||||
if (!this.abilities.flying
|
||||
&& (type == MoverType.SELF || type == MoverType.PLAYER)
|
||||
&& this.isStayingOnGroundSurface()
|
||||
@@ -63,7 +56,6 @@ public abstract class PlayerSneakMixin {
|
||||
double d = playerMovement.x;
|
||||
double e = playerMovement.z;
|
||||
|
||||
LOGGER.debug("[Sneak] Edge check active: step={} d={} e={}", step, d, e);
|
||||
while (d != 0.0D && canFallAtLeastInverted(this_, d, 0.0D, step, direction)) {
|
||||
if (Math.abs(d) <= 0.05D) d = 0.0D;
|
||||
else if (d > 0.0D) d -= 0.05D;
|
||||
@@ -84,7 +76,6 @@ public abstract class PlayerSneakMixin {
|
||||
else e += 0.05D;
|
||||
}
|
||||
|
||||
LOGGER.debug("[Sneak] Adjusted: x {} -> {} z {} -> {}", playerMovement.x, d, playerMovement.z, e);
|
||||
cir.setReturnValue(AntarchyGravityRotationUtil.vecPlayerToWorld(
|
||||
new Vec3(d, playerMovement.y, e), direction));
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"AmericanFoodConsumeMixin",
|
||||
"AmericanFoodNameMixin",
|
||||
"BlockEntityTypeSignMixin",
|
||||
"BloodCrystalKatanaDashPhaseMixin",
|
||||
"BloodglassMixin",
|
||||
"DreamFireBlockMixin",
|
||||
"DreamSandFallingSpeedMixin",
|
||||
@@ -66,7 +67,6 @@
|
||||
"gravity.LivingEntityMixin",
|
||||
"gravity.MobHurtMixin",
|
||||
"gravity.PathNavigationAccessor",
|
||||
"gravity.PathNavigationDebugMixin",
|
||||
"gravity.PlayerAttackMixin",
|
||||
"gravity.PlayerGravityMixin",
|
||||
"gravity.PlayerPoseFitMixin",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/chiseled_typhonite"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/polished_typhonite"
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"variants": {
|
||||
"type=double": {
|
||||
"model": "antarchy:block/polished_typhonite"
|
||||
},
|
||||
"type=bottom": {
|
||||
"model": "antarchy:block/polished_typhonite_slab"
|
||||
},
|
||||
"type=top": {
|
||||
"model": "antarchy:block/polished_typhonite_slab_top"
|
||||
}
|
||||
}
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=east,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner"
|
||||
},
|
||||
"facing=east,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer"
|
||||
},
|
||||
"facing=east,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs"
|
||||
},
|
||||
"facing=east,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=east,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=east,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,half=top,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=top,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=south,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner"
|
||||
},
|
||||
"facing=south,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer"
|
||||
},
|
||||
"facing=south,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,half=top,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,half=top,shape=straight": {
|
||||
"model": "antarchy:block/polished_typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"multipart": [
|
||||
{
|
||||
"when": { "up": "true" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_post" }
|
||||
},
|
||||
{
|
||||
"when": { "north": "low" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side", "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "east": "low" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side", "y": 90, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "south": "low" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side", "y": 180, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "west": "low" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side", "y": 270, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "north": "tall" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side_tall", "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "east": "tall" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side_tall", "y": 90, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "south": "tall" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side_tall", "y": 180, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "west": "tall" },
|
||||
"apply": { "model": "antarchy:block/polished_typhonite_wall_side_tall", "y": 270, "uvlock": true }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/spiraling_vines"
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/spiraling_vines_plant"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/typhonite"
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"variants": {
|
||||
"type=double": {
|
||||
"model": "antarchy:block/typhonite_bricks"
|
||||
},
|
||||
"type=bottom": {
|
||||
"model": "antarchy:block/typhonite_brick_slab"
|
||||
},
|
||||
"type=top": {
|
||||
"model": "antarchy:block/typhonite_brick_slab_top"
|
||||
}
|
||||
}
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=east,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner"
|
||||
},
|
||||
"facing=east,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer"
|
||||
},
|
||||
"facing=east,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs"
|
||||
},
|
||||
"facing=east,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=east,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=east,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=south,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner"
|
||||
},
|
||||
"facing=south,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer"
|
||||
},
|
||||
"facing=south,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_brick_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"multipart": [
|
||||
{
|
||||
"when": { "up": "true" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_post" }
|
||||
},
|
||||
{
|
||||
"when": { "north": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side", "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "east": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side", "y": 90, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "south": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side", "y": 180, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "west": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side", "y": 270, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "north": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side_tall", "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "east": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side_tall", "y": 90, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "south": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side_tall", "y": 180, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "west": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_brick_wall_side_tall", "y": 270, "uvlock": true }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"variants": {
|
||||
"type=double": {
|
||||
"model": "antarchy:block/typhonite"
|
||||
},
|
||||
"type=bottom": {
|
||||
"model": "antarchy:block/typhonite_slab"
|
||||
},
|
||||
"type=top": {
|
||||
"model": "antarchy:block/typhonite_slab_top"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"variants": {
|
||||
"thickness=base,vertical_direction=down": {
|
||||
"model": "antarchy:block/typhonite_spike_down_base"
|
||||
},
|
||||
"thickness=base,vertical_direction=up": {
|
||||
"model": "antarchy:block/typhonite_spike_up_base"
|
||||
},
|
||||
"thickness=frustum,vertical_direction=down": {
|
||||
"model": "antarchy:block/typhonite_spike_down_frustum"
|
||||
},
|
||||
"thickness=frustum,vertical_direction=up": {
|
||||
"model": "antarchy:block/typhonite_spike_up_frustum"
|
||||
},
|
||||
"thickness=middle,vertical_direction=down": {
|
||||
"model": "antarchy:block/typhonite_spike_down_middle"
|
||||
},
|
||||
"thickness=middle,vertical_direction=up": {
|
||||
"model": "antarchy:block/typhonite_spike_up_middle"
|
||||
},
|
||||
"thickness=tip,vertical_direction=down": {
|
||||
"model": "antarchy:block/typhonite_spike_down_tip"
|
||||
},
|
||||
"thickness=tip,vertical_direction=up": {
|
||||
"model": "antarchy:block/typhonite_spike_up_tip"
|
||||
},
|
||||
"thickness=tip_merge,vertical_direction=down": {
|
||||
"model": "antarchy:block/typhonite_spike_down_tip_merge"
|
||||
},
|
||||
"thickness=tip_merge,vertical_direction=up": {
|
||||
"model": "antarchy:block/typhonite_spike_up_tip_merge"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=east,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner"
|
||||
},
|
||||
"facing=east,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer"
|
||||
},
|
||||
"facing=east,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs"
|
||||
},
|
||||
"facing=east,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=east,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=east,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=north,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=north,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180
|
||||
},
|
||||
"facing=north,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=south,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner"
|
||||
},
|
||||
"facing=south,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer"
|
||||
},
|
||||
"facing=south,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=south,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=bottom,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 90
|
||||
},
|
||||
"facing=west,half=bottom,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=bottom,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=inner_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=inner_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_inner",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,half=top,shape=outer_left": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,half=top,shape=outer_right": {
|
||||
"model": "antarchy:block/typhonite_stairs_outer",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,half=top,shape=straight": {
|
||||
"model": "antarchy:block/typhonite_stairs",
|
||||
"uvlock": true,
|
||||
"x": 180,
|
||||
"y": 180
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"multipart": [
|
||||
{
|
||||
"when": { "up": "true" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_post" }
|
||||
},
|
||||
{
|
||||
"when": { "north": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side", "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "east": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side", "y": 90, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "south": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side", "y": 180, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "west": "low" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side", "y": 270, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "north": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side_tall", "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "east": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side_tall", "y": 90, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "south": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side_tall", "y": 180, "uvlock": true }
|
||||
},
|
||||
{
|
||||
"when": { "west": "tall" },
|
||||
"apply": { "model": "antarchy:block/typhonite_wall_side_tall", "y": 270, "uvlock": true }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/veined_typhonite"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=up,powered=false": { "model": "antarchy:block/vortex_lens" },
|
||||
"facing=up,powered=true": { "model": "antarchy:block/vortex_lens_on" },
|
||||
"facing=down,powered=false": { "model": "antarchy:block/vortex_lens", "x": 180 },
|
||||
"facing=down,powered=true": { "model": "antarchy:block/vortex_lens_on", "x": 180 },
|
||||
"facing=north,powered=false": { "model": "antarchy:block/vortex_lens", "x": 90 },
|
||||
"facing=north,powered=true": { "model": "antarchy:block/vortex_lens_on", "x": 90 },
|
||||
"facing=south,powered=false": { "model": "antarchy:block/vortex_lens", "x": 270 },
|
||||
"facing=south,powered=true": { "model": "antarchy:block/vortex_lens_on", "x": 270 },
|
||||
"facing=west,powered=false": { "model": "antarchy:block/vortex_lens", "x": 90, "y": 270 },
|
||||
"facing=west,powered=true": { "model": "antarchy:block/vortex_lens_on", "x": 90, "y": 270 },
|
||||
"facing=east,powered=false": { "model": "antarchy:block/vortex_lens", "x": 90, "y": 90 },
|
||||
"facing=east,powered=true": { "model": "antarchy:block/vortex_lens_on", "x": 90, "y": 90 }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/whirlflower"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "Linksklicke erneut auf angebundene Beute, um den Stachel loszureißen.",
|
||||
"item.antarchy.fallen_king_crown": "Krone des gefallenen Königs",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "Das Töten feindlicher Kreaturen gewährt Held des Dorfes",
|
||||
"item.antarchy.vortex_eye": "Wirbel-Auge",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "Ultimativer Helm",
|
||||
"item.antarchy.ultimate_chestplate": "Ultimativer Brustpanzer",
|
||||
"item.antarchy.ultimate_leggings": "Ultimativer Beinschutz",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "Gravitationskanone summt",
|
||||
"subtitles.antarchy.gravity_gun_launch": "Gravitationskanone schleudert",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "Gravitationskanone klickt leer",
|
||||
"subtitles.antarchy.antimetal_place": "Antimetall klirrt",
|
||||
"subtitles.antarchy.antimetal_step": "Antimetall klickt",
|
||||
"subtitles.antarchy.antimetal_scaffold": "Antimetallgerüst rasselt",
|
||||
"subtitles.antarchy.bed_bug_ambient": "Bettwanze zwitschert",
|
||||
"subtitles.antarchy.bed_bug_hurt": "Bettwanze wird verletzt",
|
||||
"subtitles.antarchy.bed_bug_attack": "Bettwanze beißt",
|
||||
|
||||
@@ -206,6 +206,24 @@
|
||||
"block.antarchy.smooth_dream_sandstone_stairs": "Smooth Dream Sandstone Stairs",
|
||||
"block.antarchy.smooth_dream_sandstone_slab": "Smooth Dream Sandstone Slab",
|
||||
"block.antarchy.cut_dream_sandstone_slab": "Cut Dream Sandstone Slab",
|
||||
"block.antarchy.typhonite": "Typhonite",
|
||||
"block.antarchy.typhonite_bricks": "Typhonite Bricks",
|
||||
"block.antarchy.chiseled_typhonite": "Chiseled Typhonite",
|
||||
"block.antarchy.polished_typhonite": "Polished Typhonite",
|
||||
"block.antarchy.veined_typhonite": "Veined Typhonite",
|
||||
"block.antarchy.typhonite_spike": "Typhonite Spike",
|
||||
"block.antarchy.typhonite_stairs": "Typhonite Stairs",
|
||||
"block.antarchy.typhonite_slab": "Typhonite Slab",
|
||||
"block.antarchy.typhonite_wall": "Typhonite Wall",
|
||||
"block.antarchy.typhonite_brick_stairs": "Typhonite Brick Stairs",
|
||||
"block.antarchy.typhonite_brick_slab": "Typhonite Brick Slab",
|
||||
"block.antarchy.typhonite_brick_wall": "Typhonite Brick Wall",
|
||||
"block.antarchy.polished_typhonite_stairs": "Polished Typhonite Stairs",
|
||||
"block.antarchy.polished_typhonite_slab": "Polished Typhonite Slab",
|
||||
"block.antarchy.polished_typhonite_wall": "Polished Typhonite Wall",
|
||||
"block.antarchy.spiraling_vines": "Spiraling Vines",
|
||||
"block.antarchy.spiraling_vines_plant": "Spiraling Vines Plant",
|
||||
"block.antarchy.whirlflower": "Whirlflower",
|
||||
"block.antarchy.bed_bug_egg": "Bed Bug Egg",
|
||||
"block.antarchy.wasp_nest": "Wasp Nest",
|
||||
"block.antarchy.red_ant_nest": "Red Ant Nest",
|
||||
@@ -217,6 +235,7 @@
|
||||
"block.antarchy.deepslate_titanium_ore": "Deepslate Titanium Ore",
|
||||
"block.antarchy.bluestone_ore": "Bluestone Ore",
|
||||
"block.antarchy.bluestone_block": "Bluestone Block",
|
||||
"block.antarchy.vortex_lens": "Vortex Lens",
|
||||
"block.antarchy.bluestone_repeater": "Bluestone Repeater",
|
||||
"block.antarchy.bluestone_comparator": "Bluestone Comparator",
|
||||
"block.antarchy.bluestone_torch": "Bluestone Torch",
|
||||
@@ -337,6 +356,23 @@
|
||||
"item.antarchy.smooth_dream_sandstone_stairs": "Smooth Dream Sandstone Stairs",
|
||||
"item.antarchy.smooth_dream_sandstone_slab": "Smooth Dream Sandstone Slab",
|
||||
"item.antarchy.cut_dream_sandstone_slab": "Cut Dream Sandstone Slab",
|
||||
"item.antarchy.typhonite": "Typhonite",
|
||||
"item.antarchy.typhonite_bricks": "Typhonite Bricks",
|
||||
"item.antarchy.chiseled_typhonite": "Chiseled Typhonite",
|
||||
"item.antarchy.polished_typhonite": "Polished Typhonite",
|
||||
"item.antarchy.veined_typhonite": "Veined Typhonite",
|
||||
"item.antarchy.typhonite_spike": "Typhonite Spike",
|
||||
"item.antarchy.typhonite_stairs": "Typhonite Stairs",
|
||||
"item.antarchy.typhonite_slab": "Typhonite Slab",
|
||||
"item.antarchy.typhonite_wall": "Typhonite Wall",
|
||||
"item.antarchy.typhonite_brick_stairs": "Typhonite Brick Stairs",
|
||||
"item.antarchy.typhonite_brick_slab": "Typhonite Brick Slab",
|
||||
"item.antarchy.typhonite_brick_wall": "Typhonite Brick Wall",
|
||||
"item.antarchy.polished_typhonite_stairs": "Polished Typhonite Stairs",
|
||||
"item.antarchy.polished_typhonite_slab": "Polished Typhonite Slab",
|
||||
"item.antarchy.polished_typhonite_wall": "Polished Typhonite Wall",
|
||||
"item.antarchy.spiraling_vines": "Spiraling Vines",
|
||||
"item.antarchy.whirlflower": "Whirlflower",
|
||||
"item.antarchy.dream_torch": "Dream Torch",
|
||||
"item.antarchy.dream_lantern": "Dream Lantern",
|
||||
"item.antarchy.dream_campfire": "Dream Campfire",
|
||||
@@ -488,6 +524,7 @@
|
||||
"item.antarchy.blood_crystal_boots.tooltip2": "Cancels fall damage when falling upward while gravity is inverted.",
|
||||
"item.antarchy.blood_crystal_apple.tooltip": "Grants Bloodglass Ward, providing temporary Bloodglass Hearts that recharge while the effect lasts.",
|
||||
"tooltip.antarchy.blood_crystal_katana.launch": "Launches you forward on hit.",
|
||||
"tooltip.antarchy.blood_crystal_katana.dash": "Reaches distant targets you look at; a full swing grants brief immunity.",
|
||||
"tooltip.antarchy.blood_crystal_katana.trail": "Leaves a crimson trail behind you.",
|
||||
"item.antarchy.mantis_claw": "Mantis Claw",
|
||||
"tooltip.antarchy.mantis_claw.wall_cling": "Dual wield to cling to walls and jump upward.",
|
||||
@@ -526,7 +563,10 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "Attack with tethered prey to snap the stinger free.",
|
||||
"item.antarchy.fallen_king_crown": "Fallen King\u0027s Crown",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "Grants Hero of the Village when you slay hostile mobs",
|
||||
"item.antarchy.vortex_eye": "Vortex Eye",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"entity.antarchy.vortex": "Vortex",
|
||||
"entity.antarchy.wind_vortex": "Wind Vortex",
|
||||
"item.antarchy.vortex_spawn_egg": "Vortex Spawn Egg",
|
||||
"item.antarchy.ultimate_helmet": "Ultimate Helmet",
|
||||
"item.antarchy.ultimate_chestplate": "Ultimate Chestplate",
|
||||
"item.antarchy.ultimate_leggings": "Ultimate Leggings",
|
||||
@@ -881,6 +921,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "Gravity Gun hums",
|
||||
"subtitles.antarchy.gravity_gun_launch": "Gravity Gun launches",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "Gravity Gun dry fires",
|
||||
"subtitles.antarchy.antimetal_place": "Antimetal clangs",
|
||||
"subtitles.antarchy.antimetal_step": "Antimetal clinks",
|
||||
"subtitles.antarchy.antimetal_scaffold": "Antimetal scaffolding rattles",
|
||||
"subtitles.antarchy.portal_gun_fire_blue": "Portal Gun fires",
|
||||
"subtitles.antarchy.portal_gun_fire_orange": "Portal Gun fires",
|
||||
"subtitles.antarchy.portal_gun_invalid_surface": "Portal fizzles",
|
||||
@@ -910,6 +953,11 @@
|
||||
"subtitles.antarchy.molevore_attack": "Molevore attacks",
|
||||
"subtitles.antarchy.molevore_dig": "Molevore digs",
|
||||
"subtitles.antarchy.duct_tape_use": "Duct Tape tears",
|
||||
"subtitles.antarchy.worm_hook_flying": "Worm Hook whooshes",
|
||||
"subtitles.antarchy.blood_crystal_katana_dash": "Blood Crystal Katana dashes",
|
||||
"subtitles.antarchy.blood_crystal_armor_equip": "Blood Crystal Armor equips",
|
||||
"subtitles.antarchy.bloodglass_ward_heart_break": "Bloodglass heart shatters",
|
||||
"subtitles.antarchy.bloodglass_ward_heart_regen": "Bloodglass heart reforms",
|
||||
"subtitles.antarchy.potent_nyxite_hypnotic_gas": "Potent Nyxite hisses",
|
||||
"subtitles.antarchy.potent_nyxite_geyser_eruption": "Potent Nyxite erupts",
|
||||
"subtitles.antarchy.potent_nyxite_geyser_continuous": "Potent Nyxite geyser roars",
|
||||
@@ -1019,6 +1067,7 @@
|
||||
"biome.antarchy.umbral_hills": "Umbral Hills",
|
||||
"biome.antarchy.lucid_pools": "Lucid Pools",
|
||||
"biome.antarchy.dream_dunes": "Dream Dunes",
|
||||
"biome.antarchy.vortex_expanse": "Vortex Expanse",
|
||||
"biome.antarchy.cloud_sea": "Cloud Sea",
|
||||
"block.antarchy.wild_corn": "Wild Corn",
|
||||
"trim_material.antarchy.blood_crystal": "Blood Crystal",
|
||||
@@ -1148,6 +1197,10 @@
|
||||
"advancements.antarchy.bug_apetit.description": "Eat Cooked Bug Meat.",
|
||||
"advancements.antarchy.behavioral_correction.title": "Behavioral Correction",
|
||||
"advancements.antarchy.behavioral_correction.description": "Obtain an Attitude Adjuster.",
|
||||
"advancements.antarchy.let_it_die.title": "Let It Die!",
|
||||
"advancements.antarchy.let_it_die.description": "Obtain any Truffalo Tuft.",
|
||||
"advancements.antarchy.let_it_grow.title": "Let It Grow!",
|
||||
"advancements.antarchy.let_it_grow.description": "Grow a Truffalo Sapling.",
|
||||
"advancements.antarchy.beetle_buddies.title": "Beetle Buddies",
|
||||
"advancements.antarchy.beetle_buddies.description": "Tame a Hercules Beetle.",
|
||||
"advancements.antarchy.herculean_task.title": "Herculean Task",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "Vuelve a hacer clic izquierdo sobre la presa atada para arrancar el aguijón.",
|
||||
"item.antarchy.fallen_king_crown": "Corona del Rey Caído",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "Otorga Héroe de la aldea al matar criaturas hostiles",
|
||||
"item.antarchy.vortex_eye": "Ojo de Vórtice",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "Casco definitivo",
|
||||
"item.antarchy.ultimate_chestplate": "Peto definitivo",
|
||||
"item.antarchy.ultimate_leggings": "Grebas definitivas",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "Pistola gravitatoria zumba",
|
||||
"subtitles.antarchy.gravity_gun_launch": "Pistola gravitatoria lanza",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "Pistola gravitatoria dispara en seco",
|
||||
"subtitles.antarchy.antimetal_place": "El antimetal repica",
|
||||
"subtitles.antarchy.antimetal_step": "El antimetal tintinea",
|
||||
"subtitles.antarchy.antimetal_scaffold": "El andamio de antimetal traquetea",
|
||||
"subtitles.antarchy.bed_bug_ambient": "Chinche de cama gorjea",
|
||||
"subtitles.antarchy.bed_bug_hurt": "Chinche de cama recibe daño",
|
||||
"subtitles.antarchy.bed_bug_attack": "Chinche de cama muerde",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "Frappez à nouveau la proie liée pour arracher le dard.",
|
||||
"item.antarchy.fallen_king_crown": "Couronne du Roi déchu",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "Accorde Héros du village lorsque vous tuez des créatures hostiles",
|
||||
"item.antarchy.vortex_eye": "Œil de Vortex",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "Casque ultime",
|
||||
"item.antarchy.ultimate_chestplate": "Plastron ultime",
|
||||
"item.antarchy.ultimate_leggings": "Jambières ultimes",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "Canon à gravité bourdonne",
|
||||
"subtitles.antarchy.gravity_gun_launch": "Canon à gravité projette",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "Canon à gravité tire à vide",
|
||||
"subtitles.antarchy.antimetal_place": "L'antimétal résonne",
|
||||
"subtitles.antarchy.antimetal_step": "L'antimétal cliquette",
|
||||
"subtitles.antarchy.antimetal_scaffold": "L'échafaudage d'antimétal cliquette",
|
||||
"subtitles.antarchy.bed_bug_ambient": "Punaise de lit pépie",
|
||||
"subtitles.antarchy.bed_bug_hurt": "Punaise de lit est blessé",
|
||||
"subtitles.antarchy.bed_bug_attack": "Punaise de lit mord",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "Colpisci di nuovo la preda legata per strappare via il pungiglione.",
|
||||
"item.antarchy.fallen_king_crown": "Corona del Re Caduto",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "Conferisce Eroe del villaggio quando uccidi creature ostili",
|
||||
"item.antarchy.vortex_eye": "Occhio di Vortice",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "Elmo di Supremo",
|
||||
"item.antarchy.ultimate_chestplate": "Corazza di Supremo",
|
||||
"item.antarchy.ultimate_leggings": "Gambali di Supremo",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "Il cannone gravitazionale ronza",
|
||||
"subtitles.antarchy.gravity_gun_launch": "Il cannone gravitazionale lancia",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "Il cannone gravitazionale scatta a vuoto",
|
||||
"subtitles.antarchy.antimetal_place": "L'antimetallo rimbomba",
|
||||
"subtitles.antarchy.antimetal_step": "L'antimetallo tintinna",
|
||||
"subtitles.antarchy.antimetal_scaffold": "L'impalcatura di antimetallo sferraglia",
|
||||
"subtitles.antarchy.bed_bug_ambient": "La cimice dei letti cinguetta",
|
||||
"subtitles.antarchy.bed_bug_hurt": "La cimice dei letti si ferisce",
|
||||
"subtitles.antarchy.bed_bug_attack": "La cimice dei letti morde",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "つながれた獲物をもう一度左クリックすると針を引き抜きます。",
|
||||
"item.antarchy.fallen_king_crown": "亡き王の王冠",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "敵対モブを倒すと村の英雄を付与します",
|
||||
"item.antarchy.vortex_eye": "渦の目",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "究極のヘルメット",
|
||||
"item.antarchy.ultimate_chestplate": "究極のチェストプレート",
|
||||
"item.antarchy.ultimate_leggings": "究極のレギンス",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "重力銃が低く唸る",
|
||||
"subtitles.antarchy.gravity_gun_launch": "重力銃が発射する",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "重力銃が空撃ちする",
|
||||
"subtitles.antarchy.antimetal_place": "アンチメタルが鳴る",
|
||||
"subtitles.antarchy.antimetal_step": "アンチメタルがカチカチ鳴る",
|
||||
"subtitles.antarchy.antimetal_scaffold": "アンチメタル足場ががたつく",
|
||||
"subtitles.antarchy.bed_bug_ambient": "トコジラミがさえずる",
|
||||
"subtitles.antarchy.bed_bug_hurt": "トコジラミが傷つく",
|
||||
"subtitles.antarchy.bed_bug_attack": "トコジラミが噛む",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "연결된 먹잇감을 다시 좌클릭하여 독침을 뽑습니다.",
|
||||
"item.antarchy.fallen_king_crown": "몰락한 왕의 왕관",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "적대적 생물을 처치하면 마을의 영웅을 부여합니다",
|
||||
"item.antarchy.vortex_eye": "소용돌이 눈",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "궁극 투구",
|
||||
"item.antarchy.ultimate_chestplate": "궁극 흉갑",
|
||||
"item.antarchy.ultimate_leggings": "궁극 레깅스",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "중력총 웅웅거립니다",
|
||||
"subtitles.antarchy.gravity_gun_launch": "중력총 발사합니다",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "중력총 헛발사됩니다",
|
||||
"subtitles.antarchy.antimetal_place": "안티메탈이 쨍그랑거립니다",
|
||||
"subtitles.antarchy.antimetal_step": "안티메탈이 딸깍거립니다",
|
||||
"subtitles.antarchy.antimetal_scaffold": "안티메탈 비계가 덜컹거립니다",
|
||||
"subtitles.antarchy.bed_bug_ambient": "빈대 짹짹거립니다",
|
||||
"subtitles.antarchy.bed_bug_hurt": "빈대 다칩니다",
|
||||
"subtitles.antarchy.bed_bug_attack": "빈대 뭅니다",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "Clique com o botão esquerdo novamente na presa presa para arrancar o ferrão.",
|
||||
"item.antarchy.fallen_king_crown": "Coroa do Rei Caído",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "Concede Herói da Vila ao matar criaturas hostis",
|
||||
"item.antarchy.vortex_eye": "Olho de Vórtice",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "Capacete Supremo",
|
||||
"item.antarchy.ultimate_chestplate": "Peitoral Supremo",
|
||||
"item.antarchy.ultimate_leggings": "Calças Supremas",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "Arma Gravitacional zune",
|
||||
"subtitles.antarchy.gravity_gun_launch": "Arma Gravitacional lança",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "Arma Gravitacional dispara em seco",
|
||||
"subtitles.antarchy.antimetal_place": "Antimetal retine",
|
||||
"subtitles.antarchy.antimetal_step": "Antimetal tilinta",
|
||||
"subtitles.antarchy.antimetal_scaffold": "Andaime de antimetal chacoalha",
|
||||
"subtitles.antarchy.bed_bug_ambient": "Percevejo-de-cama chilreia",
|
||||
"subtitles.antarchy.bed_bug_hurt": "Percevejo-de-cama se machuca",
|
||||
"subtitles.antarchy.bed_bug_attack": "Percevejo-de-cama morde",
|
||||
|
||||
@@ -357,7 +357,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "Нажмите ЛКМ по привязанной добыче, чтобы вырвать жало.",
|
||||
"item.antarchy.fallen_king_crown": "Корона павшего короля",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "Даёт эффект «Герой деревни» при убийстве враждебных мобов",
|
||||
"item.antarchy.vortex_eye": "Око вихря",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "Ультимативный шлем",
|
||||
"item.antarchy.ultimate_chestplate": "Ультимативный нагрудник",
|
||||
"item.antarchy.ultimate_leggings": "Ультимативные поножи",
|
||||
@@ -684,6 +684,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "Пушка гудит",
|
||||
"subtitles.antarchy.gravity_gun_launch": "Пушка стреляет",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "Осечка пушки",
|
||||
"subtitles.antarchy.antimetal_place": "Антиметалл звенит",
|
||||
"subtitles.antarchy.antimetal_step": "Антиметалл щёлкает",
|
||||
"subtitles.antarchy.antimetal_scaffold": "Антиметаллические леса гремят",
|
||||
"subtitles.antarchy.bed_bug_ambient": "Постельный клоп стрекочет",
|
||||
"subtitles.antarchy.bed_bug_hurt": "Постельному клопу больно",
|
||||
"subtitles.antarchy.bed_bug_attack": "Постельный клоп кусает",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "再次左键被牵住的猎物可扯出毒刺。",
|
||||
"item.antarchy.fallen_king_crown": "陨落之王的王冠",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "击杀敌对生物时获得村庄英雄",
|
||||
"item.antarchy.vortex_eye": "漩涡之眼",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "终极头盔",
|
||||
"item.antarchy.ultimate_chestplate": "终极胸甲",
|
||||
"item.antarchy.ultimate_leggings": "终极护腿",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "重力枪嗡鸣",
|
||||
"subtitles.antarchy.gravity_gun_launch": "重力枪发射",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "重力枪空击",
|
||||
"subtitles.antarchy.antimetal_place": "反金属发出撞击声",
|
||||
"subtitles.antarchy.antimetal_step": "反金属发出叮当声",
|
||||
"subtitles.antarchy.antimetal_scaffold": "反金属脚手架咯吱作响",
|
||||
"subtitles.antarchy.bed_bug_ambient": "臭虫唧唧叫",
|
||||
"subtitles.antarchy.bed_bug_hurt": "臭虫受伤",
|
||||
"subtitles.antarchy.bed_bug_attack": "臭虫啃咬",
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
"tooltip.antarchy.scorpion_whip.snap": "再次左鍵被牽住的獵物可扯出毒刺。",
|
||||
"item.antarchy.fallen_king_crown": "隕落之王的王冠",
|
||||
"tooltip.antarchy.fallen_king_crown.hero": "擊殺敵對生物時獲得村莊英雄",
|
||||
"item.antarchy.vortex_eye": "漩渦之眼",
|
||||
"item.antarchy.vortex_charge": "Vortex Charge",
|
||||
"item.antarchy.ultimate_helmet": "終極頭盔",
|
||||
"item.antarchy.ultimate_chestplate": "終極胸甲",
|
||||
"item.antarchy.ultimate_leggings": "終極護腿",
|
||||
@@ -715,6 +715,9 @@
|
||||
"subtitles.antarchy.gravity_gun_hold_loop": "重力槍嗡鳴",
|
||||
"subtitles.antarchy.gravity_gun_launch": "重力槍發射",
|
||||
"subtitles.antarchy.gravity_gun_dryfire": "重力槍空擊",
|
||||
"subtitles.antarchy.antimetal_place": "反金屬發出撞擊聲",
|
||||
"subtitles.antarchy.antimetal_step": "反金屬發出叮噹聲",
|
||||
"subtitles.antarchy.antimetal_scaffold": "反金屬鷹架嘎吱作響",
|
||||
"subtitles.antarchy.bed_bug_ambient": "臭蟲唧唧叫",
|
||||
"subtitles.antarchy.bed_bug_hurt": "臭蟲受傷",
|
||||
"subtitles.antarchy.bed_bug_attack": "臭蟲啃咬",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "antarchy:block/typhonite/chiseled_typhonite"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/slab",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/polished_typhonite",
|
||||
"side": "antarchy:block/typhonite/polished_typhonite",
|
||||
"top": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/slab_top",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/polished_typhonite",
|
||||
"side": "antarchy:block/typhonite/polished_typhonite",
|
||||
"top": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/stairs",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/polished_typhonite",
|
||||
"side": "antarchy:block/typhonite/polished_typhonite",
|
||||
"top": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/inner_stairs",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/polished_typhonite",
|
||||
"side": "antarchy:block/typhonite/polished_typhonite",
|
||||
"top": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/outer_stairs",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/polished_typhonite",
|
||||
"side": "antarchy:block/typhonite/polished_typhonite",
|
||||
"top": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/wall_inventory",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/template_wall_post",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/template_wall_side",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/template_wall_side_tall",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/polished_typhonite"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cross",
|
||||
"textures": {
|
||||
"cross": "antarchy:block/spiraling_vines/spiraling_vines_top"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cross",
|
||||
"textures": {
|
||||
"cross": "antarchy:block/spiraling_vines/spiraling_vines"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "antarchy:block/typhonite/typhonite"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/slab",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"side": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"top": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/slab_top",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"side": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"top": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/stairs",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"side": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"top": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/inner_stairs",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"side": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"top": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"parent": "minecraft:block/outer_stairs",
|
||||
"textures": {
|
||||
"bottom": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"side": "antarchy:block/typhonite/typhonite_bricks",
|
||||
"top": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/wall_inventory",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/template_wall_post",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/template_wall_side",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/template_wall_side_tall",
|
||||
"textures": {
|
||||
"wall": "antarchy:block/typhonite/typhonite_bricks"
|
||||
}
|
||||
}
|
||||
Loaded 100 of 350 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user