WIP 1.20.1 port
2 new squirrel anims tons of stuff
This commit is contained in:
1 parent
94c3676dea
commit
58e504cf1d
264 files changed
+14991
-3282
No files matched your search
@@ -10,9 +10,13 @@ public final class AntarchySettings {
|
|||||||
private static int easterBunnyNaturalSpawnChancePercent = 1;
|
private static int easterBunnyNaturalSpawnChancePercent = 1;
|
||||||
private static boolean rainbowAntsLeadToInfinityDimensions = true;
|
private static boolean rainbowAntsLeadToInfinityDimensions = true;
|
||||||
private static boolean brownAntRequiresReagent = false;
|
private static boolean brownAntRequiresReagent = false;
|
||||||
|
private static boolean brownAntRightClickDimension = true;
|
||||||
private static boolean redAntRequiresReagent = false;
|
private static boolean redAntRequiresReagent = false;
|
||||||
|
private static boolean redAntRightClickDimension = true;
|
||||||
private static boolean rainbowAntRequiresReagent = true;
|
private static boolean rainbowAntRequiresReagent = true;
|
||||||
|
private static boolean rainbowAntRightClickDimension = true;
|
||||||
private static boolean termiteRequiresReagent = false;
|
private static boolean termiteRequiresReagent = false;
|
||||||
|
private static boolean termiteRightClickDimension = true;
|
||||||
private static boolean antsStealFromChests = true;
|
private static boolean antsStealFromChests = true;
|
||||||
private static boolean duplicatorTreeEnabled = true;
|
private static boolean duplicatorTreeEnabled = true;
|
||||||
private static boolean glowVinesUnderLeaves = true;
|
private static boolean glowVinesUnderLeaves = true;
|
||||||
@@ -461,6 +465,22 @@ public final class AntarchySettings {
|
|||||||
return rainbowAntsLeadToInfinityDimensions;
|
return rainbowAntsLeadToInfinityDimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean brownAntRightClickDimension() {
|
||||||
|
return brownAntRightClickDimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean redAntRightClickDimension() {
|
||||||
|
return redAntRightClickDimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean rainbowAntRightClickDimension() {
|
||||||
|
return rainbowAntRightClickDimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean termiteRightClickDimension() {
|
||||||
|
return termiteRightClickDimension;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean brownAntRequiresReagent() {
|
public static boolean brownAntRequiresReagent() {
|
||||||
return brownAntRequiresReagent;
|
return brownAntRequiresReagent;
|
||||||
}
|
}
|
||||||
@@ -984,6 +1004,22 @@ public final class AntarchySettings {
|
|||||||
rainbowAntsLeadToInfinityDimensions = value;
|
rainbowAntsLeadToInfinityDimensions = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBrownAntRightClickDimension(boolean value) {
|
||||||
|
brownAntRightClickDimension = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setRedAntRightClickDimension(boolean value) {
|
||||||
|
redAntRightClickDimension = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setRainbowAntRightClickDimension(boolean value) {
|
||||||
|
rainbowAntRightClickDimension = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setTermiteRightClickDimension(boolean value) {
|
||||||
|
termiteRightClickDimension = value;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setPermanentPortalsEnabled(boolean value) {
|
public static void setPermanentPortalsEnabled(boolean value) {
|
||||||
permanentPortalsEnabled = value;
|
permanentPortalsEnabled = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import com.craisinlord.antarchy.content.entity.MolewormEntity;
|
|||||||
import com.craisinlord.antarchy.content.entity.MantisEntity;
|
import com.craisinlord.antarchy.content.entity.MantisEntity;
|
||||||
import com.craisinlord.antarchy.content.entity.ReverieEntity;
|
import com.craisinlord.antarchy.content.entity.ReverieEntity;
|
||||||
import com.craisinlord.antarchy.content.entity.ScorpionEntity;
|
import com.craisinlord.antarchy.content.entity.ScorpionEntity;
|
||||||
|
import com.craisinlord.antarchy.content.entity.nightmare.NightmareBiteEntity;
|
||||||
|
import com.craisinlord.antarchy.content.entity.nightmare.NightmarePortalEntity;
|
||||||
import com.craisinlord.antarchy.content.block.entity.AntNestBlockEntity;
|
import com.craisinlord.antarchy.content.block.entity.AntNestBlockEntity;
|
||||||
import com.craisinlord.antarchy.content.block.entity.DreamCampfireBlockEntity;
|
import com.craisinlord.antarchy.content.block.entity.DreamCampfireBlockEntity;
|
||||||
import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
|
import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
|
||||||
@@ -66,6 +68,10 @@ public final class AntarchyObjects {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<EntityType<OctopusBombEntity>> OCTOPUS_BOMB = (Supplier<EntityType<OctopusBombEntity>>) UNBOUND;
|
public static Supplier<EntityType<OctopusBombEntity>> OCTOPUS_BOMB = (Supplier<EntityType<OctopusBombEntity>>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Supplier<EntityType<NightmarePortalEntity>> NIGHTMARE_PORTAL = (Supplier<EntityType<NightmarePortalEntity>>) UNBOUND;
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Supplier<EntityType<NightmareBiteEntity>> NIGHTMARE_BITE = (Supplier<EntityType<NightmareBiteEntity>>) UNBOUND;
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<EntityType<MolewormEntity>> MOLEWORM = (Supplier<EntityType<MolewormEntity>>) UNBOUND;
|
public static Supplier<EntityType<MolewormEntity>> MOLEWORM = (Supplier<EntityType<MolewormEntity>>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<EntityType<MantisEntity>> MANTIS = (Supplier<EntityType<MantisEntity>>) UNBOUND;
|
public static Supplier<EntityType<MantisEntity>> MANTIS = (Supplier<EntityType<MantisEntity>>) UNBOUND;
|
||||||
@@ -201,9 +207,9 @@ public final class AntarchyObjects {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Block> NYXITE_SPIKE = (Supplier<Block>) UNBOUND;
|
public static Supplier<Block> NYXITE_SPIKE = (Supplier<Block>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Block> CHITEN_BLOCK = (Supplier<Block>) UNBOUND;
|
public static Supplier<Block> CHITIN_BLOCK = (Supplier<Block>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Block> CHITEN_SPIKE = (Supplier<Block>) UNBOUND;
|
public static Supplier<Block> CHITIN_SPIKE = (Supplier<Block>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Block> POTENT_NYXITE = (Supplier<Block>) UNBOUND;
|
public static Supplier<Block> POTENT_NYXITE = (Supplier<Block>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -251,6 +257,8 @@ public final class AntarchyObjects {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Holder<MobEffect>> STINKY_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
|
public static Supplier<Holder<MobEffect>> STINKY_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Supplier<Holder<MobEffect>> GLIMMERING_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Fluid> LUMEN = (Supplier<Fluid>) UNBOUND;
|
public static Supplier<Fluid> LUMEN = (Supplier<Fluid>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Fluid> FLOWING_LUMEN = (Supplier<Fluid>) UNBOUND;
|
public static Supplier<Fluid> FLOWING_LUMEN = (Supplier<Fluid>) UNBOUND;
|
||||||
@@ -301,6 +309,8 @@ public final class AntarchyObjects {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<Block> CRITTER_CAGE_BLOCK = (Supplier<Block>) UNBOUND;
|
public static Supplier<Block> CRITTER_CAGE_BLOCK = (Supplier<Block>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Supplier<Block> LUCID_ANCHOR = (Supplier<Block>) UNBOUND;
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<BlockEntityType<AntNestBlockEntity>> ANT_NEST_BLOCK_ENTITY = (Supplier<BlockEntityType<AntNestBlockEntity>>) UNBOUND;
|
public static Supplier<BlockEntityType<AntNestBlockEntity>> ANT_NEST_BLOCK_ENTITY = (Supplier<BlockEntityType<AntNestBlockEntity>>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<BlockEntityType<DreamCampfireBlockEntity>> DREAM_CAMPFIRE_BLOCK_ENTITY = (Supplier<BlockEntityType<DreamCampfireBlockEntity>>) UNBOUND;
|
public static Supplier<BlockEntityType<DreamCampfireBlockEntity>> DREAM_CAMPFIRE_BLOCK_ENTITY = (Supplier<BlockEntityType<DreamCampfireBlockEntity>>) UNBOUND;
|
||||||
@@ -314,6 +324,9 @@ public final class AntarchyObjects {
|
|||||||
public static Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.CritterCageBlockEntity>> CRITTER_CAGE_BLOCK_ENTITY =
|
public static Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.CritterCageBlockEntity>> CRITTER_CAGE_BLOCK_ENTITY =
|
||||||
(Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.CritterCageBlockEntity>>) UNBOUND;
|
(Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.CritterCageBlockEntity>>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.LucidAnchorBlockEntity>> LUCID_ANCHOR_BLOCK_ENTITY =
|
||||||
|
(Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.LucidAnchorBlockEntity>>) UNBOUND;
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<SimpleParticleType> STINKY_GAS = (Supplier<SimpleParticleType>) UNBOUND;
|
public static Supplier<SimpleParticleType> STINKY_GAS = (Supplier<SimpleParticleType>) UNBOUND;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Supplier<SimpleParticleType> STINKY_FLY = (Supplier<SimpleParticleType>) UNBOUND;
|
public static Supplier<SimpleParticleType> STINKY_FLY = (Supplier<SimpleParticleType>) UNBOUND;
|
||||||
@@ -393,8 +406,8 @@ public final class AntarchyObjects {
|
|||||||
Supplier<Block> triffidGooBlock,
|
Supplier<Block> triffidGooBlock,
|
||||||
Supplier<Block> paleNyxite,
|
Supplier<Block> paleNyxite,
|
||||||
Supplier<Block> nyxiteSpike,
|
Supplier<Block> nyxiteSpike,
|
||||||
Supplier<Block> chitenBlock,
|
Supplier<Block> chitinBlock,
|
||||||
Supplier<Block> chitenSpike,
|
Supplier<Block> chitinSpike,
|
||||||
Supplier<Block> potentNyxite,
|
Supplier<Block> potentNyxite,
|
||||||
Supplier<Block> antimetal,
|
Supplier<Block> antimetal,
|
||||||
Supplier<Block> polishedAntimetal,
|
Supplier<Block> polishedAntimetal,
|
||||||
@@ -494,8 +507,8 @@ public final class AntarchyObjects {
|
|||||||
TRIFFID_GOO_BLOCK = triffidGooBlock;
|
TRIFFID_GOO_BLOCK = triffidGooBlock;
|
||||||
PALE_NYXITE = paleNyxite;
|
PALE_NYXITE = paleNyxite;
|
||||||
NYXITE_SPIKE = nyxiteSpike;
|
NYXITE_SPIKE = nyxiteSpike;
|
||||||
CHITEN_BLOCK = chitenBlock;
|
CHITIN_BLOCK = chitinBlock;
|
||||||
CHITEN_SPIKE = chitenSpike;
|
CHITIN_SPIKE = chitinSpike;
|
||||||
POTENT_NYXITE = potentNyxite;
|
POTENT_NYXITE = potentNyxite;
|
||||||
ANTIMETAL = antimetal;
|
ANTIMETAL = antimetal;
|
||||||
POLISHED_ANTIMETAL = polishedAntimetal;
|
POLISHED_ANTIMETAL = polishedAntimetal;
|
||||||
@@ -556,6 +569,14 @@ public final class AntarchyObjects {
|
|||||||
TENTACLE = supplier;
|
TENTACLE = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setNightmarePortal(Supplier<EntityType<NightmarePortalEntity>> supplier) {
|
||||||
|
NIGHTMARE_PORTAL = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setNightmareBite(Supplier<EntityType<NightmareBiteEntity>> supplier) {
|
||||||
|
NIGHTMARE_BITE = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setLotus(Supplier<Block> supplier) {
|
public static void setLotus(Supplier<Block> supplier) {
|
||||||
LOTUS = supplier;
|
LOTUS = supplier;
|
||||||
}
|
}
|
||||||
@@ -608,6 +629,10 @@ public final class AntarchyObjects {
|
|||||||
SPIRIT_APPLE = supplier;
|
SPIRIT_APPLE = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setGlimmeringEffect(Supplier<Holder<MobEffect>> supplier) {
|
||||||
|
GLIMMERING_EFFECT = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setElka(Supplier<EntityType<com.craisinlord.antarchy.content.entity.ElkaEntity>> supplier) {
|
public static void setElka(Supplier<EntityType<com.craisinlord.antarchy.content.entity.ElkaEntity>> supplier) {
|
||||||
ELKA = supplier;
|
ELKA = supplier;
|
||||||
}
|
}
|
||||||
@@ -632,6 +657,10 @@ public final class AntarchyObjects {
|
|||||||
CRITTER_CAGE_BLOCK = supplier;
|
CRITTER_CAGE_BLOCK = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setLucidAnchor(Supplier<Block> supplier) {
|
||||||
|
LUCID_ANCHOR = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setStarCoralBlock(Supplier<Block> supplier) {
|
public static void setStarCoralBlock(Supplier<Block> supplier) {
|
||||||
STAR_CORAL_BLOCK = supplier;
|
STAR_CORAL_BLOCK = supplier;
|
||||||
}
|
}
|
||||||
@@ -688,6 +717,10 @@ public final class AntarchyObjects {
|
|||||||
CRITTER_CAGE_BLOCK_ENTITY = supplier;
|
CRITTER_CAGE_BLOCK_ENTITY = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setLucidAnchorBlockEntity(Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.LucidAnchorBlockEntity>> supplier) {
|
||||||
|
LUCID_ANCHOR_BLOCK_ENTITY = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setCritterCageProjectile(Supplier<net.minecraft.world.entity.EntityType<com.craisinlord.antarchy.content.entity.CritterCageProjectileEntity>> supplier) {
|
public static void setCritterCageProjectile(Supplier<net.minecraft.world.entity.EntityType<com.craisinlord.antarchy.content.entity.CritterCageProjectileEntity>> supplier) {
|
||||||
CRITTER_CAGE_PROJECTILE = supplier;
|
CRITTER_CAGE_PROJECTILE = supplier;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ public final class AntarchyTags {
|
|||||||
public static final TagKey<Block> MINERS_DREAM_CARVABLE = TagKey.create(Registries.BLOCK, id("miners_dream_carvable"));
|
public static final TagKey<Block> MINERS_DREAM_CARVABLE = TagKey.create(Registries.BLOCK, id("miners_dream_carvable"));
|
||||||
public static final TagKey<Block> BLUESTONE_COMPONENTS = TagKey.create(Registries.BLOCK, id("bluestone_components"));
|
public static final TagKey<Block> BLUESTONE_COMPONENTS = TagKey.create(Registries.BLOCK, id("bluestone_components"));
|
||||||
public static final TagKey<Block> BLUESTONE_CONNECTABLE = TagKey.create(Registries.BLOCK, id("bluestone_connectable"));
|
public static final TagKey<Block> BLUESTONE_CONNECTABLE = TagKey.create(Registries.BLOCK, id("bluestone_connectable"));
|
||||||
|
public static final TagKey<Block> ANTIMETAL_INVERSION_BLOCKS = TagKey.create(Registries.BLOCK, id("antimetal_inversion_blocks"));
|
||||||
|
public static final TagKey<Block> TIGER_EYE_CAMOUFLAGE_BLACKLIST = TagKey.create(Registries.BLOCK, id("tiger_eye_camouflage_blacklist"));
|
||||||
|
public static final TagKey<Block> LUCID_ANCHOR_BASE_BLOCKS = TagKey.create(Registries.BLOCK, id("lucid_anchor_base_blocks"));
|
||||||
|
|
||||||
private Blocks() {
|
private Blocks() {
|
||||||
}
|
}
|
||||||
@@ -71,6 +74,8 @@ public final class AntarchyTags {
|
|||||||
public static final TagKey<EntityType<?>> STINKY_REPELLED_HOSTILES = TagKey.create(Registries.ENTITY_TYPE, id("stinky_repelled_hostiles"));
|
public static final TagKey<EntityType<?>> STINKY_REPELLED_HOSTILES = TagKey.create(Registries.ENTITY_TYPE, id("stinky_repelled_hostiles"));
|
||||||
public static final TagKey<EntityType<?>> SCORPION_WHIP_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("scorpion_whip_immune"));
|
public static final TagKey<EntityType<?>> SCORPION_WHIP_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("scorpion_whip_immune"));
|
||||||
public static final TagKey<EntityType<?>> SCORPION_WHIP_BLACKLIST = TagKey.create(Registries.ENTITY_TYPE, id("scorpion_whip_blacklist"));
|
public static final TagKey<EntityType<?>> SCORPION_WHIP_BLACKLIST = TagKey.create(Registries.ENTITY_TYPE, id("scorpion_whip_blacklist"));
|
||||||
|
public static final TagKey<EntityType<?>> TIGER_EYE_DETECTION_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("tiger_eye_detection_immune"));
|
||||||
|
public static final TagKey<EntityType<?>> LUCID_ANCHOR_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("lucid_anchor_immune"));
|
||||||
|
|
||||||
private Entities() {
|
private Entities() {
|
||||||
}
|
}
|
||||||
@@ -110,6 +115,7 @@ public final class AntarchyTags {
|
|||||||
public static final TagKey<Item> GLIMMER_AUGMENT_ANT = TagKey.create(Registries.ITEM, id("glimmer_augment_ant"));
|
public static final TagKey<Item> GLIMMER_AUGMENT_ANT = TagKey.create(Registries.ITEM, id("glimmer_augment_ant"));
|
||||||
public static final TagKey<Item> GLIMMER_AUGMENT_ELKA = TagKey.create(Registries.ITEM, id("glimmer_augment_elka"));
|
public static final TagKey<Item> GLIMMER_AUGMENT_ELKA = TagKey.create(Registries.ITEM, id("glimmer_augment_elka"));
|
||||||
public static final TagKey<Item> HFCS_CANNOT_AMERICANIZE = TagKey.create(Registries.ITEM, id("hfcs_cannot_americanize"));
|
public static final TagKey<Item> HFCS_CANNOT_AMERICANIZE = TagKey.create(Registries.ITEM, id("hfcs_cannot_americanize"));
|
||||||
|
public static final TagKey<Item> TIGER_EYE_ARMOR = TagKey.create(Registries.ITEM, id("tigers_eye_armor"));
|
||||||
|
|
||||||
private Items() {
|
private Items() {
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -16,11 +16,11 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||||||
import net.minecraft.world.level.block.state.properties.DripstoneThickness;
|
import net.minecraft.world.level.block.state.properties.DripstoneThickness;
|
||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
|
||||||
public class ChitenSpikeBlock extends PointedDripstoneBlock {
|
public class ChitinSpikeBlock extends PointedDripstoneBlock {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public static final MapCodec<PointedDripstoneBlock> CODEC = (MapCodec) Block.simpleCodec(ChitenSpikeBlock::new);
|
public static final MapCodec<PointedDripstoneBlock> CODEC = (MapCodec) Block.simpleCodec(ChitinSpikeBlock::new);
|
||||||
|
|
||||||
public ChitenSpikeBlock(BlockBehaviour.Properties properties) {
|
public ChitinSpikeBlock(BlockBehaviour.Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,14 +99,14 @@ public class ChitenSpikeBlock extends PointedDripstoneBlock {
|
|||||||
|
|
||||||
if (state.getValue(TIP_DIRECTION) == Direction.DOWN) {
|
if (state.getValue(TIP_DIRECTION) == Direction.DOWN) {
|
||||||
BlockPos.MutableBlockPos root = pos.mutable();
|
BlockPos.MutableBlockPos root = pos.mutable();
|
||||||
while (isChitenSpikeWithDirection(level.getBlockState(root.above()), Direction.DOWN)) {
|
while (isChitinSpikeWithDirection(level.getBlockState(root.above()), Direction.DOWN)) {
|
||||||
root.move(Direction.UP);
|
root.move(Direction.UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockPos.MutableBlockPos cursor = root.mutable();
|
BlockPos.MutableBlockPos cursor = root.mutable();
|
||||||
while (isChitenSpikeWithDirection(level.getBlockState(cursor), Direction.DOWN)) {
|
while (isChitinSpikeWithDirection(level.getBlockState(cursor), Direction.DOWN)) {
|
||||||
BlockState fallingState = level.getBlockState(cursor);
|
BlockState fallingState = level.getBlockState(cursor);
|
||||||
if (isChitenSpikeWithDirection(fallingState, Direction.DOWN)) {
|
if (isChitinSpikeWithDirection(fallingState, Direction.DOWN)) {
|
||||||
net.minecraft.world.entity.item.FallingBlockEntity.fall(level, cursor, fallingState);
|
net.minecraft.world.entity.item.FallingBlockEntity.fall(level, cursor, fallingState);
|
||||||
}
|
}
|
||||||
cursor.move(Direction.DOWN);
|
cursor.move(Direction.DOWN);
|
||||||
@@ -115,7 +115,7 @@ public class ChitenSpikeBlock extends PointedDripstoneBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockPos.MutableBlockPos cursor = pos.mutable();
|
BlockPos.MutableBlockPos cursor = pos.mutable();
|
||||||
while (isChitenSpikeWithDirection(level.getBlockState(cursor), Direction.UP)) {
|
while (isChitinSpikeWithDirection(level.getBlockState(cursor), Direction.UP)) {
|
||||||
BlockState spikeState = level.getBlockState(cursor);
|
BlockState spikeState = level.getBlockState(cursor);
|
||||||
dropResources(spikeState, level, cursor);
|
dropResources(spikeState, level, cursor);
|
||||||
level.removeBlock(cursor, false);
|
level.removeBlock(cursor, false);
|
||||||
@@ -135,20 +135,20 @@ public class ChitenSpikeBlock extends PointedDripstoneBlock {
|
|||||||
private static DripstoneThickness calculateDripstoneThickness(LevelReader level, BlockPos pos, Direction direction, boolean mergeTips) {
|
private static DripstoneThickness calculateDripstoneThickness(LevelReader level, BlockPos pos, Direction direction, boolean mergeTips) {
|
||||||
Direction opposite = direction.getOpposite();
|
Direction opposite = direction.getOpposite();
|
||||||
BlockState forwardState = level.getBlockState(pos.relative(direction));
|
BlockState forwardState = level.getBlockState(pos.relative(direction));
|
||||||
if (isChitenSpikeWithDirection(forwardState, opposite)) {
|
if (isChitinSpikeWithDirection(forwardState, opposite)) {
|
||||||
return !mergeTips && forwardState.getValue(THICKNESS) != DripstoneThickness.TIP_MERGE
|
return !mergeTips && forwardState.getValue(THICKNESS) != DripstoneThickness.TIP_MERGE
|
||||||
? DripstoneThickness.TIP
|
? DripstoneThickness.TIP
|
||||||
: DripstoneThickness.TIP_MERGE;
|
: DripstoneThickness.TIP_MERGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isChitenSpikeWithDirection(forwardState, direction)) {
|
if (!isChitinSpikeWithDirection(forwardState, direction)) {
|
||||||
return DripstoneThickness.TIP;
|
return DripstoneThickness.TIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
DripstoneThickness forwardThickness = forwardState.getValue(THICKNESS);
|
DripstoneThickness forwardThickness = forwardState.getValue(THICKNESS);
|
||||||
if (forwardThickness != DripstoneThickness.TIP && forwardThickness != DripstoneThickness.TIP_MERGE) {
|
if (forwardThickness != DripstoneThickness.TIP && forwardThickness != DripstoneThickness.TIP_MERGE) {
|
||||||
BlockState backState = level.getBlockState(pos.relative(opposite));
|
BlockState backState = level.getBlockState(pos.relative(opposite));
|
||||||
return !isChitenSpikeWithDirection(backState, direction) ? DripstoneThickness.BASE : DripstoneThickness.MIDDLE;
|
return !isChitinSpikeWithDirection(backState, direction) ? DripstoneThickness.BASE : DripstoneThickness.MIDDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DripstoneThickness.FRUSTUM;
|
return DripstoneThickness.FRUSTUM;
|
||||||
@@ -157,10 +157,10 @@ public class ChitenSpikeBlock extends PointedDripstoneBlock {
|
|||||||
private static boolean isValidPointedDripstonePlacement(LevelReader level, BlockPos pos, Direction direction) {
|
private static boolean isValidPointedDripstonePlacement(LevelReader level, BlockPos pos, Direction direction) {
|
||||||
BlockPos supportPos = pos.relative(direction.getOpposite());
|
BlockPos supportPos = pos.relative(direction.getOpposite());
|
||||||
BlockState supportState = level.getBlockState(supportPos);
|
BlockState supportState = level.getBlockState(supportPos);
|
||||||
return supportState.isFaceSturdy(level, supportPos, direction) || isChitenSpikeWithDirection(supportState, direction);
|
return supportState.isFaceSturdy(level, supportPos, direction) || isChitinSpikeWithDirection(supportState, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isChitenSpikeWithDirection(BlockState state, Direction direction) {
|
private static boolean isChitinSpikeWithDirection(BlockState state, Direction direction) {
|
||||||
return state.is(AntarchyObjects.CHITEN_SPIKE.get()) && state.getValue(TIP_DIRECTION) == direction;
|
return state.is(AntarchyObjects.CHITIN_SPIKE.get()) && state.getValue(TIP_DIRECTION) == direction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+17
@@ -5,6 +5,8 @@ import com.craisinlord.antarchy.mixins.AccessorFireBlock;
|
|||||||
import com.mojang.serialization.MapCodec;
|
import com.mojang.serialization.MapCodec;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.FireBlock;
|
import net.minecraft.world.level.block.FireBlock;
|
||||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
@@ -25,6 +27,21 @@ public class DreamFireBlock extends FireBlock {
|
|||||||
return CODEC;
|
return CODEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||||
|
if (level.getBlockState(pos.below()).is(AntarchyTags.Blocks.DREAM_FIRE_BASE_BLOCKS)) {
|
||||||
|
if (!this.canSurvive(state, level, pos)) {
|
||||||
|
level.removeBlock(pos, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
level.scheduleTick(pos, this, 30 + random.nextInt(10));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.tick(state, level, pos, random);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
|
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
|
||||||
return level.getBlockState(pos.below()).is(AntarchyTags.Blocks.DREAM_FIRE_BASE_BLOCKS)
|
return level.getBlockState(pos.below()).is(AntarchyTags.Blocks.DREAM_FIRE_BASE_BLOCKS)
|
||||||
|
|||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
package com.craisinlord.antarchy.content.block;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||||
|
import com.craisinlord.antarchy.content.block.entity.LucidAnchorBlockEntity;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
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.RenderShape;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class LucidAnchorBlock extends BaseEntityBlock {
|
||||||
|
public static final MapCodec<LucidAnchorBlock> CODEC = Block.simpleCodec(LucidAnchorBlock::new);
|
||||||
|
public static final BooleanProperty ACTIVE = BlockStateProperties.LIT;
|
||||||
|
|
||||||
|
public LucidAnchorBlock(BlockBehaviour.Properties properties) {
|
||||||
|
super(properties);
|
||||||
|
this.registerDefaultState(this.stateDefinition.any().setValue(ACTIVE, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapCodec<LucidAnchorBlock> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||||
|
builder.add(ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RenderShape getRenderShape(BlockState state) {
|
||||||
|
return RenderShape.MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
return new LucidAnchorBlockEntity(pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
||||||
|
return level.isClientSide
|
||||||
|
? null
|
||||||
|
: createTickerHelper(blockEntityType, AntarchyObjects.LUCID_ANCHOR_BLOCK_ENTITY.get(), (tickLevel, tickPos, tickState, blockEntity) -> {
|
||||||
|
if (tickLevel instanceof net.minecraft.server.level.ServerLevel serverLevel) {
|
||||||
|
LucidAnchorBlockEntity.serverTick(serverLevel, tickPos, tickState, blockEntity);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||||
|
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||||
|
markStructureDirty(level, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos neighborPos, boolean movedByPiston) {
|
||||||
|
super.neighborChanged(state, level, pos, block, neighborPos, movedByPiston);
|
||||||
|
markStructureDirty(level, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void markStructureDirty(Level level, BlockPos pos) {
|
||||||
|
if (level.getBlockEntity(pos) instanceof LucidAnchorBlockEntity lucidAnchor) {
|
||||||
|
lucidAnchor.markStructureDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+344
@@ -0,0 +1,344 @@
|
|||||||
|
package com.craisinlord.antarchy.content.block.entity;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||||
|
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyTags;
|
||||||
|
import com.craisinlord.antarchy.content.block.LucidAnchorBlock;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.core.component.DataComponents;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.IntArrayTag;
|
||||||
|
import net.minecraft.network.protocol.Packet;
|
||||||
|
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.effect.MobEffect;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
|
import net.minecraft.world.entity.EntitySelector;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.BeaconBeamBlock;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
|
||||||
|
public class LucidAnchorBlockEntity extends BlockEntity {
|
||||||
|
private static final int EFFECT_INTERVAL_TICKS = 20;
|
||||||
|
private static final int VALIDATION_INTERVAL_TICKS = 60;
|
||||||
|
private static final int EFFECT_DURATION_TICKS = 60;
|
||||||
|
private static final int EFFECT_REFRESH_THRESHOLD_TICKS = 30;
|
||||||
|
private static final int DEFAULT_BEAM_COLOR = 0xFFFF1A1A;
|
||||||
|
|
||||||
|
private int pyramidLevel;
|
||||||
|
private boolean active;
|
||||||
|
private boolean beamPathClear;
|
||||||
|
private int beamLength;
|
||||||
|
private boolean structureDirty = true;
|
||||||
|
private long lastValidationTick = Long.MIN_VALUE;
|
||||||
|
private List<BeamSection> beamSections = List.of();
|
||||||
|
|
||||||
|
public LucidAnchorBlockEntity(BlockPos pos, BlockState blockState) {
|
||||||
|
super(AntarchyObjects.LUCID_ANCHOR_BLOCK_ENTITY.get(), pos, blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void serverTick(ServerLevel level, BlockPos pos, BlockState state, LucidAnchorBlockEntity blockEntity) {
|
||||||
|
blockEntity.serverTick(level, pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markStructureDirty() {
|
||||||
|
this.structureDirty = true;
|
||||||
|
this.setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return this.active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPyramidLevel() {
|
||||||
|
return this.pyramidLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBeamLength() {
|
||||||
|
return this.beamLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BeamSection> getBeamSections() {
|
||||||
|
return this.beamSections;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void serverTick(ServerLevel level, BlockPos pos, BlockState state) {
|
||||||
|
long gameTime = level.getGameTime();
|
||||||
|
if (this.structureDirty || gameTime - this.lastValidationTick >= VALIDATION_INTERVAL_TICKS) {
|
||||||
|
this.revalidate(level, pos, state);
|
||||||
|
this.structureDirty = false;
|
||||||
|
this.lastValidationTick = gameTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.active && gameTime % EFFECT_INTERVAL_TICKS == 0L) {
|
||||||
|
this.applyInvertedField(level, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void revalidate(ServerLevel level, BlockPos pos, BlockState state) {
|
||||||
|
int newPyramidLevel = calculatePyramidLevel(level, pos);
|
||||||
|
BeamValidation beamValidation = validateBeamPath(level, pos);
|
||||||
|
boolean newActive = newPyramidLevel > 0 && beamValidation.clear();
|
||||||
|
boolean stateChanged = this.pyramidLevel != newPyramidLevel
|
||||||
|
|| this.beamPathClear != beamValidation.clear()
|
||||||
|
|| this.active != newActive
|
||||||
|
|| this.beamLength != beamValidation.length()
|
||||||
|
|| !this.beamSections.equals(beamValidation.sections());
|
||||||
|
|
||||||
|
boolean activeChanged = this.active != newActive;
|
||||||
|
this.pyramidLevel = newPyramidLevel;
|
||||||
|
this.beamPathClear = beamValidation.clear();
|
||||||
|
this.beamLength = beamValidation.length();
|
||||||
|
this.beamSections = beamValidation.sections();
|
||||||
|
this.active = newActive;
|
||||||
|
|
||||||
|
if (state.getBlock() instanceof LucidAnchorBlock && state.getValue(LucidAnchorBlock.ACTIVE) != newActive) {
|
||||||
|
level.setBlock(pos, state.setValue(LucidAnchorBlock.ACTIVE, newActive), Block.UPDATE_CLIENTS);
|
||||||
|
state = level.getBlockState(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeChanged) {
|
||||||
|
level.playSound(null, pos, newActive ? SoundEvents.BEACON_ACTIVATE : SoundEvents.BEACON_DEACTIVATE, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stateChanged) {
|
||||||
|
this.syncVisualState(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyInvertedField(ServerLevel level, BlockPos pos) {
|
||||||
|
if (this.pyramidLevel <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int radius = 10 + this.pyramidLevel * 10;
|
||||||
|
AABB area = new AABB(
|
||||||
|
pos.getX() - radius,
|
||||||
|
level.getMinBuildHeight(),
|
||||||
|
pos.getZ() - radius,
|
||||||
|
pos.getX() + radius + 1.0D,
|
||||||
|
pos.getY() + 1.0D,
|
||||||
|
pos.getZ() + radius + 1.0D
|
||||||
|
);
|
||||||
|
Holder<MobEffect> invertedEffect = AntarchyObjects.INVERTED_EFFECT.get();
|
||||||
|
for (LivingEntity entity : level.getEntitiesOfClass(LivingEntity.class, area, entity -> EntitySelector.NO_SPECTATORS.test(entity) && entity.isAlive())) {
|
||||||
|
if (entity.getType().is(AntarchyTags.Entities.LUCID_ANCHOR_IMMUNE) || entity.getType().is(AntarchyTags.Entities.INVERTED_IMMUNE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MobEffectInstance current = entity.getEffect(invertedEffect);
|
||||||
|
if (current != null && current.getDuration() > EFFECT_REFRESH_THRESHOLD_TICKS && current.getAmplifier() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.addEffect(new MobEffectInstance(invertedEffect, EFFECT_DURATION_TICKS, 0, true, true, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncVisualState(BlockState state) {
|
||||||
|
this.setChanged();
|
||||||
|
if (this.level != null) {
|
||||||
|
this.level.sendBlockUpdated(this.worldPosition, state, state, Block.UPDATE_CLIENTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
|
super.saveAdditional(tag, registries);
|
||||||
|
tag.putInt("PyramidLevel", this.pyramidLevel);
|
||||||
|
tag.putBoolean("Active", this.active);
|
||||||
|
tag.putBoolean("BeamPathClear", this.beamPathClear);
|
||||||
|
tag.putInt("BeamLength", this.beamLength);
|
||||||
|
tag.putBoolean("StructureDirty", this.structureDirty);
|
||||||
|
int[] colors = new int[this.beamSections.size()];
|
||||||
|
int[] lengths = new int[this.beamSections.size()];
|
||||||
|
for (int i = 0; i < this.beamSections.size(); i++) {
|
||||||
|
BeamSection section = this.beamSections.get(i);
|
||||||
|
colors[i] = section.color();
|
||||||
|
lengths[i] = section.length();
|
||||||
|
}
|
||||||
|
tag.put("BeamColors", new IntArrayTag(colors));
|
||||||
|
tag.put("BeamLengths", new IntArrayTag(lengths));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
|
super.loadAdditional(tag, registries);
|
||||||
|
this.pyramidLevel = tag.getInt("PyramidLevel");
|
||||||
|
this.active = tag.getBoolean("Active");
|
||||||
|
this.beamPathClear = tag.getBoolean("BeamPathClear");
|
||||||
|
this.beamLength = tag.getInt("BeamLength");
|
||||||
|
this.structureDirty = true;
|
||||||
|
int[] colors = tag.getIntArray("BeamColors");
|
||||||
|
int[] lengths = tag.getIntArray("BeamLengths");
|
||||||
|
List<BeamSection> sections = new ArrayList<>();
|
||||||
|
for (int i = 0; i < Math.min(colors.length, lengths.length); i++) {
|
||||||
|
if (lengths[i] > 0) {
|
||||||
|
sections.add(new BeamSection(colors[i], lengths[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.beamSections = sections.isEmpty() ? List.of() : List.copyOf(sections);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||||
|
return this.saveCustomOnly(registries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Packet<ClientGamePacketListener> getUpdatePacket() {
|
||||||
|
return ClientboundBlockEntityDataPacket.create(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculatePyramidLevel(Level level, BlockPos anchorPos) {
|
||||||
|
int completedLayers = 0;
|
||||||
|
BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
|
||||||
|
for (int layer = 1; layer <= 4; layer++) {
|
||||||
|
int y = anchorPos.getY() + layer;
|
||||||
|
if (y > level.getMaxBuildHeight()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean complete = true;
|
||||||
|
for (int x = anchorPos.getX() - layer; x <= anchorPos.getX() + layer && complete; x++) {
|
||||||
|
for (int z = anchorPos.getZ() - layer; z <= anchorPos.getZ() + layer; z++) {
|
||||||
|
cursor.set(x, y, z);
|
||||||
|
if (!level.getBlockState(cursor).is(AntarchyTags.Blocks.LUCID_ANCHOR_BASE_BLOCKS)) {
|
||||||
|
complete = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!complete) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
completedLayers = layer;
|
||||||
|
}
|
||||||
|
return completedLayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BeamValidation validateBeamPath(Level level, BlockPos anchorPos) {
|
||||||
|
int minBuildHeight = level.getMinBuildHeight();
|
||||||
|
int floorTolerance = minBuildHeight + 5;
|
||||||
|
if (anchorPos.getY() <= minBuildHeight) {
|
||||||
|
return BeamValidation.inactive();
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos.MutableBlockPos cursor = anchorPos.below().mutable();
|
||||||
|
List<BeamSection> sections = new ArrayList<>();
|
||||||
|
int currentColor = DEFAULT_BEAM_COLOR;
|
||||||
|
int currentLength = 0;
|
||||||
|
int totalLength = 0;
|
||||||
|
boolean clear = false;
|
||||||
|
|
||||||
|
for (int y = anchorPos.getY() - 1; y >= minBuildHeight; y--) {
|
||||||
|
cursor.set(anchorPos.getX(), y, anchorPos.getZ());
|
||||||
|
BlockState state = level.getBlockState(cursor);
|
||||||
|
|
||||||
|
if (state.is(Blocks.BEDROCK)) {
|
||||||
|
if (y <= floorTolerance) {
|
||||||
|
currentLength++;
|
||||||
|
totalLength++;
|
||||||
|
clear = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isBeamPassable(level, cursor, state)) {
|
||||||
|
if (y <= floorTolerance) {
|
||||||
|
currentLength++;
|
||||||
|
totalLength++;
|
||||||
|
clear = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return BeamValidation.inactive();
|
||||||
|
}
|
||||||
|
|
||||||
|
int encounteredColor = colorForBeamState(state, currentColor);
|
||||||
|
if (encounteredColor != currentColor && currentLength > 0) {
|
||||||
|
sections.add(new BeamSection(currentColor, currentLength));
|
||||||
|
currentColor = encounteredColor;
|
||||||
|
currentLength = 0;
|
||||||
|
} else {
|
||||||
|
currentColor = encounteredColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentLength++;
|
||||||
|
totalLength++;
|
||||||
|
if (y <= floorTolerance && state.isAir()) {
|
||||||
|
clear = true;
|
||||||
|
}
|
||||||
|
if (y == minBuildHeight) {
|
||||||
|
clear = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clear || totalLength <= 0) {
|
||||||
|
return BeamValidation.inactive();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentLength > 0) {
|
||||||
|
sections.add(new BeamSection(currentColor, currentLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BeamValidation(true, totalLength, List.copyOf(sections));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isBeamPassable(Level level, BlockPos pos, BlockState state) {
|
||||||
|
if (state.isAir()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!level.getFluidState(pos).isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (state.getBlock() instanceof BeaconBeamBlock) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return state.getLightBlock(level, pos) < 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int colorForBeamState(BlockState state, int fallbackColor) {
|
||||||
|
if (!(state.getBlock() instanceof BeaconBeamBlock beamBlock)) {
|
||||||
|
return fallbackColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int diffuse = beamBlock.getColor().getTextureDiffuseColor();
|
||||||
|
int red = (diffuse >> 16) & 0xFF;
|
||||||
|
int green = (diffuse >> 8) & 0xFF;
|
||||||
|
int blue = diffuse & 0xFF;
|
||||||
|
if (fallbackColor == DEFAULT_BEAM_COLOR) {
|
||||||
|
return 0xFF000000 | diffuse;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fallbackRed = (fallbackColor >> 16) & 0xFF;
|
||||||
|
int fallbackGreen = (fallbackColor >> 8) & 0xFF;
|
||||||
|
int fallbackBlue = fallbackColor & 0xFF;
|
||||||
|
return 0xFF000000
|
||||||
|
| (((fallbackRed + red) / 2) << 16)
|
||||||
|
| (((fallbackGreen + green) / 2) << 8)
|
||||||
|
| ((fallbackBlue + blue) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record BeamSection(int color, int length) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private record BeamValidation(boolean clear, int length, List<BeamSection> sections) {
|
||||||
|
private static BeamValidation inactive() {
|
||||||
|
return new BeamValidation(false, 0, List.of());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public final class TigerEyeCamouflageClientState {
|
||||||
|
public record CamouflageState(boolean active, int blockStateId) {}
|
||||||
|
|
||||||
|
private static final Map<Integer, CamouflageState> STATES = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private TigerEyeCamouflageClientState() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void update(int entityId, boolean active, int blockStateId) {
|
||||||
|
if (!active) {
|
||||||
|
STATES.remove(entityId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
STATES.put(entityId, new CamouflageState(true, blockStateId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CamouflageState get(int entityId) {
|
||||||
|
return STATES.get(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
STATES.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
public final class TigerEyeClientHooks {
|
||||||
|
private static Supplier<Component> camouflageKeyText = () -> Component.translatable("key.antarchy.tigers_eye_camouflage");
|
||||||
|
|
||||||
|
private TigerEyeClientHooks() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCamouflageKeyTextSupplier(Supplier<Component> supplier) {
|
||||||
|
camouflageKeyText = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Component camouflageKeyText() {
|
||||||
|
return camouflageKeyText.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
-4
@@ -7,10 +7,12 @@ import com.craisinlord.antarchy.content.entity.HerculesBeetleEntity;
|
|||||||
import com.craisinlord.antarchy.content.entity.ToreterrorEntity;
|
import com.craisinlord.antarchy.content.entity.ToreterrorEntity;
|
||||||
import com.craisinlord.antarchy.content.entity.brutalfly.BrutalflyEntity;
|
import com.craisinlord.antarchy.content.entity.brutalfly.BrutalflyEntity;
|
||||||
import com.craisinlord.antarchy.content.entity.kraken.KrakenEntity;
|
import com.craisinlord.antarchy.content.entity.kraken.KrakenEntity;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.BossEvent;
|
import net.minecraft.world.BossEvent;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
@@ -19,6 +21,7 @@ public final class CustomBossBarRenderer {
|
|||||||
private static final int BAR_WIDTH = 182;
|
private static final int BAR_WIDTH = 182;
|
||||||
private static final int BAR_HEIGHT = 5;
|
private static final int BAR_HEIGHT = 5;
|
||||||
private static final int GLOBAL_Y_OFFSET = 15;
|
private static final int GLOBAL_Y_OFFSET = 15;
|
||||||
|
private static final Map<UUID, Textures> TEXTURES_BY_BOSS_ID = new HashMap<>();
|
||||||
|
|
||||||
private static final Map<Class<? extends Entity>, Textures> BY_ENTITY_CLASS = Map.of(
|
private static final Map<Class<? extends Entity>, Textures> BY_ENTITY_CLASS = Map.of(
|
||||||
KrakenEntity.class, textures("blue", "kraken", 204, 56, 4),
|
KrakenEntity.class, textures("blue", "kraken", 204, 56, 4),
|
||||||
@@ -28,6 +31,14 @@ public final class CustomBossBarRenderer {
|
|||||||
HerculesBeetleEntity.class, textures("beetle", "hercules_beetle", 194, 33, 1),
|
HerculesBeetleEntity.class, textures("beetle", "hercules_beetle", 194, 33, 1),
|
||||||
EmperorScorpionEntity.class, textures("purple", "scorpion", 218, 34, -2)
|
EmperorScorpionEntity.class, textures("purple", "scorpion", 218, 34, -2)
|
||||||
);
|
);
|
||||||
|
private static final Map<String, Textures> BY_LOCALIZED_NAME_AND_COLOR = Map.of(
|
||||||
|
key(Component.translatable("entity.antarchy.kraken").getString(), BossEvent.BossBarColor.BLUE), BY_ENTITY_CLASS.get(KrakenEntity.class),
|
||||||
|
key(Component.translatable("entity.antarchy.toreterror").getString(), BossEvent.BossBarColor.GREEN), BY_ENTITY_CLASS.get(ToreterrorEntity.class),
|
||||||
|
key(Component.translatable("entity.antarchy.alpha_mantis").getString(), BossEvent.BossBarColor.GREEN), BY_ENTITY_CLASS.get(AlphaMantisEntity.class),
|
||||||
|
key(Component.translatable("entity.antarchy.brutalfly").getString(), BossEvent.BossBarColor.YELLOW), BY_ENTITY_CLASS.get(BrutalflyEntity.class),
|
||||||
|
key(Component.translatable("entity.antarchy.hercules_beetle").getString(), BossEvent.BossBarColor.RED), BY_ENTITY_CLASS.get(HerculesBeetleEntity.class),
|
||||||
|
key(Component.translatable("entity.antarchy.emperor_scorpion").getString(), BossEvent.BossBarColor.PURPLE), BY_ENTITY_CLASS.get(EmperorScorpionEntity.class)
|
||||||
|
);
|
||||||
|
|
||||||
private CustomBossBarRenderer() {
|
private CustomBossBarRenderer() {
|
||||||
}
|
}
|
||||||
@@ -60,11 +71,25 @@ public final class CustomBossBarRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Textures lookup(BossEvent bossEvent) {
|
private static Textures lookup(BossEvent bossEvent) {
|
||||||
Entity entity = findEntity(bossEvent.getId());
|
Textures cached = TEXTURES_BY_BOSS_ID.get(bossEvent.getId());
|
||||||
if (entity == null) {
|
if (cached != null) {
|
||||||
return null;
|
return cached;
|
||||||
}
|
}
|
||||||
return BY_ENTITY_CLASS.get(entity.getClass());
|
|
||||||
|
Entity entity = findEntity(bossEvent.getId());
|
||||||
|
if (entity != null) {
|
||||||
|
Textures textures = BY_ENTITY_CLASS.get(entity.getClass());
|
||||||
|
if (textures != null) {
|
||||||
|
TEXTURES_BY_BOSS_ID.put(bossEvent.getId(), textures);
|
||||||
|
return textures;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Textures fallback = BY_LOCALIZED_NAME_AND_COLOR.get(key(bossEvent.getName().getString(), bossEvent.getColor()));
|
||||||
|
if (fallback != null) {
|
||||||
|
TEXTURES_BY_BOSS_ID.put(bossEvent.getId(), fallback);
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Entity findEntity(UUID id) {
|
private static Entity findEntity(UUID id) {
|
||||||
@@ -91,6 +116,10 @@ public final class CustomBossBarRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String key(String name, BossEvent.BossBarColor color) {
|
||||||
|
return color.name() + "|" + name;
|
||||||
|
}
|
||||||
|
|
||||||
private record Textures(ResourceLocation background, ResourceLocation progress, ResourceLocation overlay, int overlayWidth, int overlayHeight, int barYOffset) {
|
private record Textures(ResourceLocation background, ResourceLocation progress, ResourceLocation overlay, int overlayWidth, int overlayHeight, int barYOffset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client.model;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.Antarchy;
|
||||||
|
import com.craisinlord.antarchy.content.entity.nightmare.NightmareBiteEntity;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import software.bernie.geckolib.model.GeoModel;
|
||||||
|
|
||||||
|
public class NightmareBiteModel extends GeoModel<NightmareBiteEntity> {
|
||||||
|
private static final ResourceLocation PHASE_ONE_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/nightmare_bite.png");
|
||||||
|
private static final ResourceLocation PHASE_TWO_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/nightmare_bite_phase_2.png");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getModelResource(NightmareBiteEntity animatable) {
|
||||||
|
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/nightmare_bite.geo.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getTextureResource(NightmareBiteEntity animatable) {
|
||||||
|
return animatable.isPhaseTwo() ? PHASE_TWO_TEXTURE : PHASE_ONE_TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getAnimationResource(NightmareBiteEntity animatable) {
|
||||||
|
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/nightmare_bite.animation.json");
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-3
@@ -6,8 +6,10 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import software.bernie.geckolib.model.GeoModel;
|
import software.bernie.geckolib.model.GeoModel;
|
||||||
|
|
||||||
public class NightmareModel extends GeoModel<NightmareEntity> {
|
public class NightmareModel extends GeoModel<NightmareEntity> {
|
||||||
public static final ResourceLocation EMISSIVE_TEXTURE =
|
private static final ResourceLocation PHASE_ONE_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/nightmare/nightmare.png");
|
||||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/nightmare_emissive.png");
|
private static final ResourceLocation PHASE_TWO_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/nightmare/nightmare_phase_2.png");
|
||||||
|
private static final ResourceLocation PHASE_ONE_EMISSIVE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/nightmare/nightmare_emissive.png");
|
||||||
|
private static final ResourceLocation PHASE_TWO_EMISSIVE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/nightmare/nightmare_phase_2_emissive.png");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceLocation getModelResource(NightmareEntity animatable) {
|
public ResourceLocation getModelResource(NightmareEntity animatable) {
|
||||||
@@ -16,11 +18,19 @@ public class NightmareModel extends GeoModel<NightmareEntity> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceLocation getTextureResource(NightmareEntity animatable) {
|
public ResourceLocation getTextureResource(NightmareEntity animatable) {
|
||||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/nightmare.png");
|
return textureFor(animatable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceLocation getAnimationResource(NightmareEntity animatable) {
|
public ResourceLocation getAnimationResource(NightmareEntity animatable) {
|
||||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/nightmare.animation.json");
|
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/nightmare.animation.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation textureFor(NightmareEntity animatable) {
|
||||||
|
return animatable.hasPhaseTwoTexture() ? PHASE_TWO_TEXTURE : PHASE_ONE_TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation emissiveTextureFor(NightmareEntity animatable) {
|
||||||
|
return animatable.hasPhaseTwoTexture() ? PHASE_TWO_EMISSIVE : PHASE_ONE_EMISSIVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client.model;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.Antarchy;
|
||||||
|
import com.craisinlord.antarchy.content.entity.nightmare.NightmarePortalEntity;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import software.bernie.geckolib.model.GeoModel;
|
||||||
|
|
||||||
|
public class NightmarePortalModel extends GeoModel<NightmarePortalEntity> {
|
||||||
|
public static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/nightmare_portal.png");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getModelResource(NightmarePortalEntity animatable) {
|
||||||
|
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/nightmare_portal.geo.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getTextureResource(NightmarePortalEntity animatable) {
|
||||||
|
return TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getAnimationResource(NightmarePortalEntity animatable) {
|
||||||
|
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/nightmare_portal.animation.json");
|
||||||
|
}
|
||||||
|
}
|
||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client.renderer;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.block.entity.LucidAnchorBlockEntity;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import com.mojang.math.Axis;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.joml.Matrix3f;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
public class LucidAnchorBlockEntityRenderer implements BlockEntityRenderer<LucidAnchorBlockEntity> {
|
||||||
|
private static final ResourceLocation BEAM_TEXTURE = ResourceLocation.withDefaultNamespace("textures/entity/beacon_beam.png");
|
||||||
|
private static final float INNER_RADIUS = 0.14F;
|
||||||
|
private static final float OUTER_RADIUS = 0.28F;
|
||||||
|
private static final float START_OFFSET = -0.02F;
|
||||||
|
|
||||||
|
public LucidAnchorBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(LucidAnchorBlockEntity blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {
|
||||||
|
if (!blockEntity.isActive() || blockEntity.getBeamLength() <= 0 || blockEntity.getBeamSections().isEmpty() || blockEntity.getLevel() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long gameTime = blockEntity.getLevel().getGameTime();
|
||||||
|
float scroll = (gameTime + partialTick) * 0.02F;
|
||||||
|
float startY = START_OFFSET;
|
||||||
|
float endY = START_OFFSET - blockEntity.getBeamLength();
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.translate(0.5D, 0.0D, 0.5D);
|
||||||
|
|
||||||
|
float currentTop = startY;
|
||||||
|
for (LucidAnchorBlockEntity.BeamSection section : blockEntity.getBeamSections()) {
|
||||||
|
float sectionBottom = currentTop - section.length();
|
||||||
|
renderBeamPrism(poseStack, buffer.getBuffer(RenderType.entityTranslucent(BEAM_TEXTURE)), currentTop, sectionBottom, INNER_RADIUS, section.color(), 1.0F, scroll);
|
||||||
|
renderBeamPrism(poseStack, buffer.getBuffer(RenderType.entityTranslucent(BEAM_TEXTURE)), currentTop, sectionBottom, OUTER_RADIUS, darken(section.color()), 0.45F, -scroll);
|
||||||
|
currentTop = sectionBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTop > endY) {
|
||||||
|
renderBeamPrism(poseStack, buffer.getBuffer(RenderType.entityTranslucent(BEAM_TEXTURE)), currentTop, endY, INNER_RADIUS, 0xFFFF1A1A, 1.0F, scroll);
|
||||||
|
renderBeamPrism(poseStack, buffer.getBuffer(RenderType.entityTranslucent(BEAM_TEXTURE)), currentTop, endY, OUTER_RADIUS, 0xFF7A0000, 0.45F, -scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewDistance() {
|
||||||
|
return 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void renderBeamPrism(PoseStack poseStack, VertexConsumer consumer, float topY, float bottomY, float radius, int color, float alphaScale, float scroll) {
|
||||||
|
PoseStack.Pose pose = poseStack.last();
|
||||||
|
Matrix4f matrix = pose.pose();
|
||||||
|
Matrix3f normal = pose.normal();
|
||||||
|
float red = ((color >> 16) & 0xFF) / 255.0F;
|
||||||
|
float green = ((color >> 8) & 0xFF) / 255.0F;
|
||||||
|
float blue = (color & 0xFF) / 255.0F;
|
||||||
|
float alpha = ((color >>> 24) & 0xFF) / 255.0F * alphaScale;
|
||||||
|
float vTop = scroll + topY * 0.25F;
|
||||||
|
float vBottom = scroll + bottomY * 0.25F;
|
||||||
|
|
||||||
|
addFace(consumer, matrix, normal, -radius, topY, -radius, radius, topY, -radius, radius, bottomY, -radius, -radius, bottomY, -radius, red, green, blue, alpha, vTop, vBottom);
|
||||||
|
addFace(consumer, matrix, normal, radius, topY, radius, -radius, topY, radius, -radius, bottomY, radius, radius, bottomY, radius, red, green, blue, alpha, vTop, vBottom);
|
||||||
|
addFace(consumer, matrix, normal, -radius, topY, radius, -radius, topY, -radius, -radius, bottomY, -radius, -radius, bottomY, radius, red, green, blue, alpha, vTop, vBottom);
|
||||||
|
addFace(consumer, matrix, normal, radius, topY, -radius, radius, topY, radius, radius, bottomY, radius, radius, bottomY, -radius, red, green, blue, alpha, vTop, vBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addFace(
|
||||||
|
VertexConsumer consumer,
|
||||||
|
Matrix4f matrix,
|
||||||
|
Matrix3f normal,
|
||||||
|
float x0,
|
||||||
|
float y0,
|
||||||
|
float z0,
|
||||||
|
float x1,
|
||||||
|
float y1,
|
||||||
|
float z1,
|
||||||
|
float x2,
|
||||||
|
float y2,
|
||||||
|
float z2,
|
||||||
|
float x3,
|
||||||
|
float y3,
|
||||||
|
float z3,
|
||||||
|
float red,
|
||||||
|
float green,
|
||||||
|
float blue,
|
||||||
|
float alpha,
|
||||||
|
float vTop,
|
||||||
|
float vBottom
|
||||||
|
) {
|
||||||
|
addVertex(consumer, matrix, normal, x0, y0, z0, red, green, blue, alpha, 0.0F, vTop);
|
||||||
|
addVertex(consumer, matrix, normal, x1, y1, z1, red, green, blue, alpha, 1.0F, vTop);
|
||||||
|
addVertex(consumer, matrix, normal, x2, y2, z2, red, green, blue, alpha, 1.0F, vBottom);
|
||||||
|
addVertex(consumer, matrix, normal, x3, y3, z3, red, green, blue, alpha, 0.0F, vBottom);
|
||||||
|
|
||||||
|
addVertex(consumer, matrix, normal, x3, y3, z3, red, green, blue, alpha, 0.0F, vBottom);
|
||||||
|
addVertex(consumer, matrix, normal, x2, y2, z2, red, green, blue, alpha, 1.0F, vBottom);
|
||||||
|
addVertex(consumer, matrix, normal, x1, y1, z1, red, green, blue, alpha, 1.0F, vTop);
|
||||||
|
addVertex(consumer, matrix, normal, x0, y0, z0, red, green, blue, alpha, 0.0F, vTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addVertex(VertexConsumer consumer, Matrix4f matrix, Matrix3f normal, float x, float y, float z, float red, float green, float blue, float alpha, float u, float v) {
|
||||||
|
consumer.addVertex(matrix, x, y, z)
|
||||||
|
.setColor(red, green, blue, alpha)
|
||||||
|
.setUv(u, v)
|
||||||
|
.setOverlay(OverlayTexture.NO_OVERLAY)
|
||||||
|
.setLight(LightTexture.FULL_BRIGHT)
|
||||||
|
.setNormal(0.0F, 1.0F, 0.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int darken(int color) {
|
||||||
|
int red = (int) (((color >> 16) & 0xFF) * 0.45F);
|
||||||
|
int green = (int) (((color >> 8) & 0xFF) * 0.2F);
|
||||||
|
int blue = (int) ((color & 0xFF) * 0.2F);
|
||||||
|
return (color & 0xFF000000) | (red << 16) | (green << 8) | blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client.renderer;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.client.model.NightmareBiteModel;
|
||||||
|
import com.craisinlord.antarchy.content.entity.nightmare.NightmareBiteEntity;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||||
|
import software.bernie.geckolib.renderer.GeoEntityRenderer;
|
||||||
|
|
||||||
|
public class NightmareBiteRenderer extends GeoEntityRenderer<NightmareBiteEntity> {
|
||||||
|
public NightmareBiteRenderer(EntityRendererProvider.Context context) {
|
||||||
|
super(context, new NightmareBiteModel());
|
||||||
|
this.shadowRadius = 0.0F;
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client.renderer;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.client.model.NightmarePortalModel;
|
||||||
|
import com.craisinlord.antarchy.content.entity.nightmare.NightmarePortalEntity;
|
||||||
|
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.EntityRendererProvider;
|
||||||
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import software.bernie.geckolib.cache.object.BakedGeoModel;
|
||||||
|
import software.bernie.geckolib.renderer.GeoEntityRenderer;
|
||||||
|
|
||||||
|
public class NightmarePortalRenderer extends GeoEntityRenderer<NightmarePortalEntity> {
|
||||||
|
public NightmarePortalRenderer(EntityRendererProvider.Context context) {
|
||||||
|
super(context, new NightmarePortalModel());
|
||||||
|
this.shadowRadius = 0.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(NightmarePortalEntity entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight) {
|
||||||
|
BakedGeoModel model = this.getGeoModel().getBakedModel(this.getGeoModel().getModelResource(entity));
|
||||||
|
RenderType renderType = RenderType.eyes(NightmarePortalModel.TEXTURE);
|
||||||
|
VertexConsumer buffer = bufferSource.getBuffer(renderType);
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.scale(1.0F, 1.0F, 1.0F);
|
||||||
|
this.reRender(model, poseStack, bufferSource, entity, renderType, buffer, partialTick, 0xF000F0, OverlayTexture.NO_OVERLAY, 0xFFFFFFFF);
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable RenderType getRenderType(NightmarePortalEntity animatable, ResourceLocation texture, @Nullable MultiBufferSource bufferSource, float partialTick) {
|
||||||
|
return RenderType.eyes(NightmarePortalModel.TEXTURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -35,7 +35,7 @@ public class NightmareRenderer extends GeoEntityRenderer<NightmareEntity> {
|
|||||||
public void render(PoseStack poseStack, NightmareEntity animatable, BakedGeoModel bakedModel, @Nullable RenderType renderType,
|
public void render(PoseStack poseStack, NightmareEntity animatable, BakedGeoModel bakedModel, @Nullable RenderType renderType,
|
||||||
MultiBufferSource bufferSource, @Nullable VertexConsumer buffer, float partialTick,
|
MultiBufferSource bufferSource, @Nullable VertexConsumer buffer, float partialTick,
|
||||||
int packedLight, int packedOverlay) {
|
int packedLight, int packedOverlay) {
|
||||||
RenderType emissiveType = RenderType.eyes(NightmareModel.EMISSIVE_TEXTURE);
|
RenderType emissiveType = RenderType.eyes(NightmareModel.emissiveTextureFor(animatable));
|
||||||
VertexConsumer emissiveBuffer = bufferSource.getBuffer(emissiveType);
|
VertexConsumer emissiveBuffer = bufferSource.getBuffer(emissiveType);
|
||||||
this.getRenderer().reRender(
|
this.getRenderer().reRender(
|
||||||
bakedModel,
|
bakedModel,
|
||||||
|
|||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client.renderer;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||||
|
import com.craisinlord.antarchy.content.client.TigerEyeCamouflageClientState;
|
||||||
|
import com.craisinlord.antarchy.content.item.TigerEyeArmorUtil;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import net.minecraft.client.model.PlayerModel;
|
||||||
|
import net.minecraft.client.player.AbstractClientPlayer;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.entity.RenderLayerParent;
|
||||||
|
import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
|
||||||
|
public final class TigerEyeCamouflagePlayerLayer extends RenderLayer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> {
|
||||||
|
public TigerEyeCamouflagePlayerLayer(RenderLayerParent<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> renderer) {
|
||||||
|
super(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack poseStack, MultiBufferSource buffer, int packedLight, AbstractClientPlayer player,
|
||||||
|
float limbSwing, float limbSwingAmount, float partialTick, float ageInTicks, float netHeadYaw,
|
||||||
|
float headPitch) {
|
||||||
|
if (player.isSpectator() || player.isInvisible() || player.hasEffect(AntarchyObjects.PARALYZED_EFFECT.get())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!TigerEyeArmorUtil.hasFullSet(player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TigerEyeCamouflageClientState.CamouflageState state = TigerEyeCamouflageClientState.get(player.getId());
|
||||||
|
if (state == null || !state.active()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var blockState = Block.stateById(state.blockStateId());
|
||||||
|
if (!TigerEyeArmorUtil.isValidCamouflageBlock(blockState)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.scale(1.1F, 1.1F, 1.1F);
|
||||||
|
var resolved = TigerEyeCamouflageTextureResolver.resolve(blockState, BlockPos.containing(player.position()));
|
||||||
|
VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.entityCutoutNoCull(resolved.texture()));
|
||||||
|
this.getParentModel().renderToBuffer(
|
||||||
|
poseStack,
|
||||||
|
vertexConsumer,
|
||||||
|
packedLight,
|
||||||
|
LivingEntityRenderer.getOverlayCoords(player, 0.0F),
|
||||||
|
resolved.argbTint()
|
||||||
|
);
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
}
|
||||||
+146
@@ -0,0 +1,146 @@
|
|||||||
|
package com.craisinlord.antarchy.content.client.renderer;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.color.block.BlockColors;
|
||||||
|
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||||
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||||
|
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public final class TigerEyeCamouflageTextureResolver {
|
||||||
|
public record ResolvedTexture(ResourceLocation texture, int argbTint) {}
|
||||||
|
|
||||||
|
// PlayerModel's skin layout is always laid out on a 64x64 canvas, regardless of the
|
||||||
|
// block texture's actual size, so the generated overlay texture must match that grid
|
||||||
|
// for every body part to sample the block texture at the same pixel density.
|
||||||
|
private static final int SKIN_SIZE = 64;
|
||||||
|
private static final Map<Integer, ResolvedTexture> CACHE = new ConcurrentHashMap<>();
|
||||||
|
private static final ResourceLocation FALLBACK_TEXTURE = ResourceLocation.withDefaultNamespace("textures/block/stone.png");
|
||||||
|
private static final long QUAD_SEED = 0x54EADL;
|
||||||
|
|
||||||
|
private TigerEyeCamouflageTextureResolver() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResolvedTexture resolve(BlockState state, BlockPos pos) {
|
||||||
|
int stateId = Block.getId(state);
|
||||||
|
ResolvedTexture cached = CACHE.get(stateId);
|
||||||
|
if (cached != null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolvedTexture resolved = resolveUncached(state, pos);
|
||||||
|
CACHE.put(stateId, resolved);
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearCache() {
|
||||||
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
for (ResolvedTexture resolved : CACHE.values()) {
|
||||||
|
if (!resolved.texture().equals(FALLBACK_TEXTURE)) {
|
||||||
|
minecraft.getTextureManager().release(resolved.texture());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CACHE.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ResolvedTexture resolveUncached(BlockState state, BlockPos pos) {
|
||||||
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
BlockRenderDispatcher dispatcher = minecraft.getBlockRenderer();
|
||||||
|
var model = dispatcher.getBlockModel(state);
|
||||||
|
List<BakedQuad> upwardQuads = model.getQuads(state, Direction.UP, RandomSource.create(QUAD_SEED));
|
||||||
|
TextureAtlasSprite sprite = firstSprite(upwardQuads);
|
||||||
|
int tintIndex = -1;
|
||||||
|
if (sprite == null) {
|
||||||
|
sprite = model.getParticleIcon();
|
||||||
|
} else if (!upwardQuads.isEmpty()) {
|
||||||
|
tintIndex = upwardQuads.getFirst().getTintIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sprite == null) {
|
||||||
|
return new ResolvedTexture(FALLBACK_TEXTURE, 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tint = 0xFFFFFFFF;
|
||||||
|
if (tintIndex >= 0) {
|
||||||
|
BlockColors colors = minecraft.getBlockColors();
|
||||||
|
int color = colors.getColor(state, minecraft.level, pos, tintIndex);
|
||||||
|
if (color != -1) {
|
||||||
|
tint = 0xFF000000 | color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLocation tiled = buildTiledSkin(minecraft, sprite.contents().name());
|
||||||
|
return new ResolvedTexture(tiled, tint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ResourceLocation buildTiledSkin(Minecraft minecraft, ResourceLocation spriteId) {
|
||||||
|
ResourceLocation source = ResourceLocation.fromNamespaceAndPath(
|
||||||
|
spriteId.getNamespace(),
|
||||||
|
"textures/" + spriteId.getPath() + ".png"
|
||||||
|
);
|
||||||
|
ResourceLocation target = ResourceLocation.fromNamespaceAndPath(
|
||||||
|
spriteId.getNamespace(),
|
||||||
|
"dynamic/tiger_eye_camouflage/" + spriteId.getPath()
|
||||||
|
);
|
||||||
|
|
||||||
|
try (InputStream stream = openStream(minecraft, source)) {
|
||||||
|
if (stream == null) {
|
||||||
|
return FALLBACK_TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (NativeImage sourceImage = NativeImage.read(stream)) {
|
||||||
|
int tileWidth = sourceImage.getWidth();
|
||||||
|
// Animated block textures stack frames vertically below a square first frame.
|
||||||
|
int tileHeight = tileWidth <= sourceImage.getHeight() ? tileWidth : sourceImage.getHeight();
|
||||||
|
|
||||||
|
NativeImage canvas = new NativeImage(SKIN_SIZE, SKIN_SIZE, false);
|
||||||
|
for (int y = 0; y < SKIN_SIZE; y++) {
|
||||||
|
for (int x = 0; x < SKIN_SIZE; x++) {
|
||||||
|
canvas.setPixelRGBA(x, y, sourceImage.getPixelRGBA(x % tileWidth, y % tileHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minecraft.getTextureManager().register(target, new DynamicTexture(canvas));
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
return FALLBACK_TEXTURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream openStream(Minecraft minecraft, ResourceLocation location) {
|
||||||
|
return minecraft.getResourceManager().getResource(location)
|
||||||
|
.map(resource -> {
|
||||||
|
try {
|
||||||
|
return resource.open();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextureAtlasSprite firstSprite(List<BakedQuad> quads) {
|
||||||
|
if (quads == null || quads.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (BakedQuad quad : quads) {
|
||||||
|
if (quad != null && quad.getSprite() != null) {
|
||||||
|
return quad.getSprite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
-7
@@ -1,6 +1,5 @@
|
|||||||
package com.craisinlord.antarchy.content.creative;
|
package com.craisinlord.antarchy.content.creative;
|
||||||
|
|
||||||
import com.craisinlord.antarchy.Antarchy;
|
|
||||||
import com.craisinlord.antarchy.content.entity.glimmer.GlimmerVariant;
|
import com.craisinlord.antarchy.content.entity.glimmer.GlimmerVariant;
|
||||||
import com.craisinlord.antarchy.content.item.GlimmerBottleItem;
|
import com.craisinlord.antarchy.content.item.GlimmerBottleItem;
|
||||||
import com.craisinlord.antarchy.content.item.ultimate.UltimateGearHelper;
|
import com.craisinlord.antarchy.content.item.ultimate.UltimateGearHelper;
|
||||||
@@ -21,6 +20,8 @@ import net.minecraft.world.item.alchemy.PotionContents;
|
|||||||
import net.minecraft.world.level.ItemLike;
|
import net.minecraft.world.level.ItemLike;
|
||||||
|
|
||||||
public final class CreativeTabContents {
|
public final class CreativeTabContents {
|
||||||
|
private static final String MODID = "antarchy";
|
||||||
|
|
||||||
private CreativeTabContents() {}
|
private CreativeTabContents() {}
|
||||||
|
|
||||||
private record CatalogEntry(String path, String neoTabPath, String insertAfterPath) {}
|
private record CatalogEntry(String path, String neoTabPath, String insertAfterPath) {}
|
||||||
@@ -89,6 +90,7 @@ public final class CreativeTabContents {
|
|||||||
entry("mossy_shellstone_brick_slab", "building_blocks"),
|
entry("mossy_shellstone_brick_slab", "building_blocks"),
|
||||||
entry("mossy_shellstone_brick_wall", "building_blocks"),
|
entry("mossy_shellstone_brick_wall", "building_blocks"),
|
||||||
entry("cracked_shellstone_bricks", "building_blocks"),
|
entry("cracked_shellstone_bricks", "building_blocks"),
|
||||||
|
entry("shellstone_pillar", "building_blocks"),
|
||||||
entry("blush_moss_block", "building_blocks"),
|
entry("blush_moss_block", "building_blocks"),
|
||||||
entry("blush_moss_carpet", "building_blocks"),
|
entry("blush_moss_carpet", "building_blocks"),
|
||||||
entry("lumen_froglight", "natural_blocks"),
|
entry("lumen_froglight", "natural_blocks"),
|
||||||
@@ -108,16 +110,22 @@ public final class CreativeTabContents {
|
|||||||
entry("nyxite_brick_slab", "building_blocks"),
|
entry("nyxite_brick_slab", "building_blocks"),
|
||||||
entry("nyxite_brick_wall", "building_blocks"),
|
entry("nyxite_brick_wall", "building_blocks"),
|
||||||
entry("chiseled_nyxite", "building_blocks"),
|
entry("chiseled_nyxite", "building_blocks"),
|
||||||
|
entry("nyxite_pillar", "building_blocks"),
|
||||||
entry("pale_nyxite", "building_blocks"),
|
entry("pale_nyxite", "building_blocks"),
|
||||||
entry("nyxite_spike", "building_blocks"),
|
entry("nyxite_spike", "building_blocks"),
|
||||||
entry("potent_nyxite", "building_blocks"),
|
entry("potent_nyxite", "building_blocks"),
|
||||||
entry("antimetal", "building_blocks"),
|
entry("antimetal", "building_blocks"),
|
||||||
|
entry("antimetal_stairs", "building_blocks"),
|
||||||
|
entry("antimetal_slab", "building_blocks"),
|
||||||
entry("polished_antimetal", "building_blocks"),
|
entry("polished_antimetal", "building_blocks"),
|
||||||
|
entry("polished_antimetal_stairs", "building_blocks"),
|
||||||
|
entry("polished_antimetal_slab", "building_blocks"),
|
||||||
entry("antimetal_scaffolding", "building_blocks"),
|
entry("antimetal_scaffolding", "building_blocks"),
|
||||||
entry("antimetal_rail", "redstone_blocks"),
|
entry("antimetal_rail", "redstone_blocks"),
|
||||||
entry("antimetal_powered_rail", "redstone_blocks"),
|
entry("antimetal_powered_rail", "redstone_blocks"),
|
||||||
entry("antimetal_detector_rail", "redstone_blocks"),
|
entry("antimetal_detector_rail", "redstone_blocks"),
|
||||||
entry("antimetal_activator_rail", "redstone_blocks"),
|
entry("antimetal_activator_rail", "redstone_blocks"),
|
||||||
|
entry("upper", "redstone_blocks"),
|
||||||
entry("umbral_moss_block", "building_blocks"),
|
entry("umbral_moss_block", "building_blocks"),
|
||||||
entry("umbral_moss_carpet", "building_blocks"),
|
entry("umbral_moss_carpet", "building_blocks"),
|
||||||
entry("dream_torch", "building_blocks"),
|
entry("dream_torch", "building_blocks"),
|
||||||
@@ -134,6 +142,7 @@ public final class CreativeTabContents {
|
|||||||
entry("smooth_dream_sandstone_stairs", "building_blocks"),
|
entry("smooth_dream_sandstone_stairs", "building_blocks"),
|
||||||
entry("smooth_dream_sandstone_slab", "building_blocks"),
|
entry("smooth_dream_sandstone_slab", "building_blocks"),
|
||||||
entry("cut_dream_sandstone_slab", "building_blocks"),
|
entry("cut_dream_sandstone_slab", "building_blocks"),
|
||||||
|
entry("antigravel", "natural_blocks"),
|
||||||
entry("budding_blood_crystal", "building_blocks"),
|
entry("budding_blood_crystal", "building_blocks"),
|
||||||
entry("blood_crystal_block", "building_blocks"),
|
entry("blood_crystal_block", "building_blocks"),
|
||||||
entry("blood_crystal_cluster", "building_blocks"),
|
entry("blood_crystal_cluster", "building_blocks"),
|
||||||
@@ -145,6 +154,7 @@ public final class CreativeTabContents {
|
|||||||
entry("biomite_turf", "building_blocks"),
|
entry("biomite_turf", "building_blocks"),
|
||||||
entry("biowart", "building_blocks"),
|
entry("biowart", "building_blocks"),
|
||||||
entry("biowart_tendrils", "building_blocks"),
|
entry("biowart_tendrils", "building_blocks"),
|
||||||
|
entry("loam", "natural_blocks"),
|
||||||
entry("broodstone", "building_blocks"),
|
entry("broodstone", "building_blocks"),
|
||||||
entry("polished_broodstone", "building_blocks"),
|
entry("polished_broodstone", "building_blocks"),
|
||||||
entry("chiseled_broodstone", "building_blocks"),
|
entry("chiseled_broodstone", "building_blocks"),
|
||||||
@@ -158,12 +168,13 @@ public final class CreativeTabContents {
|
|||||||
entry("broodstone_brick_stairs", "building_blocks"),
|
entry("broodstone_brick_stairs", "building_blocks"),
|
||||||
entry("broodstone_brick_slab", "building_blocks"),
|
entry("broodstone_brick_slab", "building_blocks"),
|
||||||
entry("broodstone_brick_wall", "building_blocks"),
|
entry("broodstone_brick_wall", "building_blocks"),
|
||||||
|
entry("broodstone_pillar", "building_blocks"),
|
||||||
entry("myrmite_coal_ore", "building_blocks"),
|
entry("myrmite_coal_ore", "building_blocks"),
|
||||||
entry("broodstone_uranium_ore", "building_blocks"),
|
entry("broodstone_uranium_ore", "building_blocks"),
|
||||||
entry("broodstone_titanium_ore", "building_blocks"),
|
entry("broodstone_titanium_ore", "building_blocks"),
|
||||||
entry("bile_vein", "building_blocks"),
|
entry("bile_vein", "building_blocks"),
|
||||||
entry("chiten_block", "building_blocks"),
|
entry("chitin_block", "building_blocks"),
|
||||||
entry("chiten_spike", "building_blocks"),
|
entry("chitin_spike", "building_blocks"),
|
||||||
entry("amber_moss_block", "building_blocks"),
|
entry("amber_moss_block", "building_blocks"),
|
||||||
entry("amber_moss_carpet", "building_blocks"),
|
entry("amber_moss_carpet", "building_blocks"),
|
||||||
entry("uranium_block", "building_blocks"),
|
entry("uranium_block", "building_blocks"),
|
||||||
@@ -180,6 +191,7 @@ public final class CreativeTabContents {
|
|||||||
entry("bluestone_repeater", "redstone_blocks"),
|
entry("bluestone_repeater", "redstone_blocks"),
|
||||||
entry("bluestone_comparator", "redstone_blocks"),
|
entry("bluestone_comparator", "redstone_blocks"),
|
||||||
entry("bluestone_torch", "redstone_blocks"),
|
entry("bluestone_torch", "redstone_blocks"),
|
||||||
|
entry("bluestone_lamp", "redstone_blocks"),
|
||||||
entry("titanium_block", "building_blocks"),
|
entry("titanium_block", "building_blocks"),
|
||||||
entry("raw_titanium_block", "building_blocks"),
|
entry("raw_titanium_block", "building_blocks"),
|
||||||
entry("cut_titanium", "building_blocks"),
|
entry("cut_titanium", "building_blocks"),
|
||||||
@@ -205,6 +217,7 @@ public final class CreativeTabContents {
|
|||||||
entry("seashell", "natural_blocks"),
|
entry("seashell", "natural_blocks"),
|
||||||
entry("hushweed", "natural_blocks"),
|
entry("hushweed", "natural_blocks"),
|
||||||
entry("amber_lichen", "natural_blocks"),
|
entry("amber_lichen", "natural_blocks"),
|
||||||
|
entry("mucus", "natural_blocks"),
|
||||||
entry("creepvine", "natural_blocks"),
|
entry("creepvine", "natural_blocks"),
|
||||||
entry("hanging_creeproots", "natural_blocks"),
|
entry("hanging_creeproots", "natural_blocks"),
|
||||||
entry("molting_vines", "natural_blocks"),
|
entry("molting_vines", "natural_blocks"),
|
||||||
@@ -243,6 +256,7 @@ public final class CreativeTabContents {
|
|||||||
entry("antiwater_bucket", "tools_and_utilities"),
|
entry("antiwater_bucket", "tools_and_utilities"),
|
||||||
entry("lumen_bucket", "tools_and_utilities"),
|
entry("lumen_bucket", "tools_and_utilities"),
|
||||||
entry("cloud_bucket", "tools_and_utilities"),
|
entry("cloud_bucket", "tools_and_utilities"),
|
||||||
|
entry("lucid_anchor", "tools_and_utilities"),
|
||||||
entry("reverie_bottle", "tools_and_utilities"),
|
entry("reverie_bottle", "tools_and_utilities"),
|
||||||
entry("glimmer_bottle", "tools_and_utilities"),
|
entry("glimmer_bottle", "tools_and_utilities"),
|
||||||
entry("critter_cage", "tools_and_utilities"),
|
entry("critter_cage", "tools_and_utilities"),
|
||||||
@@ -283,6 +297,10 @@ public final class CreativeTabContents {
|
|||||||
entry("blood_crystal_chestplate", "combat"),
|
entry("blood_crystal_chestplate", "combat"),
|
||||||
entry("blood_crystal_leggings", "combat"),
|
entry("blood_crystal_leggings", "combat"),
|
||||||
entry("blood_crystal_boots", "combat"),
|
entry("blood_crystal_boots", "combat"),
|
||||||
|
entry("tigers_eye_helmet", "combat"),
|
||||||
|
entry("tigers_eye_chestplate", "combat"),
|
||||||
|
entry("tigers_eye_leggings", "combat"),
|
||||||
|
entry("tigers_eye_boots", "combat"),
|
||||||
entry("moggles", "combat"),
|
entry("moggles", "combat"),
|
||||||
entry("scorpion_whip", "combat"),
|
entry("scorpion_whip", "combat"),
|
||||||
entry("fallen_king_crown", "combat"),
|
entry("fallen_king_crown", "combat"),
|
||||||
@@ -306,15 +324,15 @@ public final class CreativeTabContents {
|
|||||||
entry("mud_pie", "ingredients"),
|
entry("mud_pie", "ingredients"),
|
||||||
entry("lucid_eye", "ingredients"),
|
entry("lucid_eye", "ingredients"),
|
||||||
entry("blood_crystal_shard", "ingredients"),
|
entry("blood_crystal_shard", "ingredients"),
|
||||||
|
entry("tigers_eye", "ingredients"),
|
||||||
entry("blood_crystal_apple", "ingredients"),
|
entry("blood_crystal_apple", "ingredients"),
|
||||||
entry("spirit_apple", "ingredients"),
|
entry("spirit_apple", "ingredients"),
|
||||||
entry("mantis_claw", "combat"),
|
entry("mantis_claw", "combat"),
|
||||||
entry("hercules_horn", "ingredients"),
|
entry("hercules_horn", "ingredients"),
|
||||||
entry("king_scale", "ingredients"),
|
entry("king_scale", "ingredients"),
|
||||||
entry("queen_scale", "ingredients"),
|
entry("queen_scale", "ingredients"),
|
||||||
entry("chiten", "ingredients"),
|
entry("chitin", "ingredients"),
|
||||||
entry("jerry_nucleus", "ingredients"),
|
entry("jerry_nucleus", "ingredients"),
|
||||||
entry("carapace", "ingredients"),
|
|
||||||
entry("stink_bug", "ingredients"),
|
entry("stink_bug", "ingredients"),
|
||||||
entry("brutalfly_wing", "ingredients"),
|
entry("brutalfly_wing", "ingredients"),
|
||||||
entry("primordial_scute", "ingredients"),
|
entry("primordial_scute", "ingredients"),
|
||||||
@@ -323,6 +341,7 @@ public final class CreativeTabContents {
|
|||||||
entry("emperor_scorpion_stinger", "ingredients"),
|
entry("emperor_scorpion_stinger", "ingredients"),
|
||||||
entry("kraken_tooth", "ingredients"),
|
entry("kraken_tooth", "ingredients"),
|
||||||
entry("kraken_tentacle", "ingredients"),
|
entry("kraken_tentacle", "ingredients"),
|
||||||
|
entry("kraken_kalamari", "ingredients"),
|
||||||
entry("jumpy_bug_leg", "ingredients"),
|
entry("jumpy_bug_leg", "ingredients"),
|
||||||
entry("cornea_ear", "ingredients"),
|
entry("cornea_ear", "ingredients"),
|
||||||
entry("corn", "ingredients"),
|
entry("corn", "ingredients"),
|
||||||
@@ -493,7 +512,7 @@ public final class CreativeTabContents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Item item(String path) {
|
private static Item item(String path) {
|
||||||
return BuiltInRegistries.ITEM.get(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, path));
|
return BuiltInRegistries.ITEM.get(ResourceLocation.fromNamespaceAndPath(MODID, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Item vanillaItem(String path) {
|
private static Item vanillaItem(String path) {
|
||||||
@@ -501,7 +520,7 @@ public final class CreativeTabContents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Holder<Potion> potion(String path) {
|
private static Holder<Potion> potion(String path) {
|
||||||
Potion potion = BuiltInRegistries.POTION.get(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, path));
|
Potion potion = BuiltInRegistries.POTION.get(ResourceLocation.fromNamespaceAndPath(MODID, path));
|
||||||
return potion == null ? null : BuiltInRegistries.POTION.wrapAsHolder(potion);
|
return potion == null ? null : BuiltInRegistries.POTION.wrapAsHolder(potion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+20
@@ -103,6 +103,26 @@ public class AlphaMantisEntity extends MantisEntity {
|
|||||||
return 1.05D;
|
return 1.05D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected double configuredMaxHealth() {
|
||||||
|
return AntarchySettings.alphaMantisHealth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected double configuredAttackDamage() {
|
||||||
|
return AntarchySettings.alphaMantisAttackDamage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected double configuredMovementSpeed() {
|
||||||
|
return AntarchySettings.alphaMantisMovementSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected double configuredFlyingSpeed() {
|
||||||
|
return AntarchySettings.alphaMantisFlyingSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ public class BedBugEntity extends Animal implements GeoEntity {
|
|||||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
||||||
BedBugSpawnData bedBugSpawnData = spawnGroupData instanceof BedBugSpawnData data ? data : new BedBugSpawnData();
|
BedBugSpawnData bedBugSpawnData = spawnGroupData instanceof BedBugSpawnData data ? data : new BedBugSpawnData();
|
||||||
super.finalizeSpawn(level, difficulty, spawnReason, null);
|
super.finalizeSpawn(level, difficulty, spawnReason, null);
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.bedBugHealth());
|
||||||
|
|
||||||
if (bedBugSpawnData.eggNestPos == null && (spawnReason == MobSpawnType.NATURAL || spawnReason == MobSpawnType.CHUNK_GENERATION) && this.random.nextFloat() < 0.55F) {
|
if (bedBugSpawnData.eggNestPos == null && (spawnReason == MobSpawnType.NATURAL || spawnReason == MobSpawnType.CHUNK_GENERATION) && this.random.nextFloat() < 0.55F) {
|
||||||
bedBugSpawnData.eggNestPos = this.createNaturalEggNest(level);
|
bedBugSpawnData.eggNestPos = this.createNaturalEggNest(level);
|
||||||
|
|||||||
+1
@@ -234,6 +234,7 @@ public class ButterflyEntity extends Animal implements FlyingAnimal, GeoEntity {
|
|||||||
@Override
|
@Override
|
||||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData spawnGroupData) {
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData spawnGroupData) {
|
||||||
this.assignRandomTextureVariant();
|
this.assignRandomTextureVariant();
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.butterflyHealth());
|
||||||
return super.finalizeSpawn(level, difficulty, spawnType, spawnGroupData);
|
return super.finalizeSpawn(level, difficulty, spawnType, spawnGroupData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
@@ -128,6 +128,12 @@ public class CaterpillarEntity extends Animal implements GeoEntity {
|
|||||||
.add(Attributes.FOLLOW_RANGE, 14.0D);
|
.add(Attributes.FOLLOW_RANGE, 14.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.caterpillarHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PathNavigation createNavigation(Level level) {
|
protected PathNavigation createNavigation(Level level) {
|
||||||
GroundPathNavigation navigation = new GroundPathNavigation(this, level) {
|
GroundPathNavigation navigation = new GroundPathNavigation(this, level) {
|
||||||
|
|||||||
@@ -48,6 +48,12 @@ public class CheepEntity extends AbstractFish implements GeoEntity {
|
|||||||
.add(Attributes.MOVEMENT_SPEED, 0.5D);
|
.add(Attributes.MOVEMENT_SPEED, 0.5D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.cheepHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getBucketItemStack() {
|
public ItemStack getBucketItemStack() {
|
||||||
return new ItemStack(Items.WATER_BUCKET);
|
return new ItemStack(Items.WATER_BUCKET);
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.craisinlord.antarchy.content.entity;
|
||||||
|
|
||||||
|
import net.minecraft.world.entity.Mob;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||||
|
|
||||||
|
public final class ConfiguredMobSpawnUtil {
|
||||||
|
private ConfiguredMobSpawnUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyConfiguredHealth(Mob mob, double maxHealth) {
|
||||||
|
AttributeInstance maxHealthAttribute = mob.getAttribute(Attributes.MAX_HEALTH);
|
||||||
|
if (maxHealthAttribute != null) {
|
||||||
|
maxHealthAttribute.setBaseValue(maxHealth);
|
||||||
|
}
|
||||||
|
mob.setHealth((float) maxHealth);
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -74,6 +74,12 @@ public class CreepingHorrorEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.FOLLOW_RANGE, 16.0D);
|
.add(Attributes.FOLLOW_RANGE, 16.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.creepingHorrorHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<CreepingHorrorEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<CreepingHorrorEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -160,6 +160,12 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
|||||||
.add(Attributes.ATTACK_DAMAGE, 4.0D);
|
.add(Attributes.ATTACK_DAMAGE, 4.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.dorrieHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasSaddle() {
|
public boolean hasSaddle() {
|
||||||
return this.entityData.get(HAS_SADDLE);
|
return this.entityData.get(HAS_SADDLE);
|
||||||
}
|
}
|
||||||
|
|||||||
+276
-16
@@ -15,6 +15,7 @@ import net.minecraft.network.syncher.SynchedEntityData;
|
|||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.level.ServerBossEvent;
|
import net.minecraft.server.level.ServerBossEvent;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.util.RandomSource;
|
import net.minecraft.util.RandomSource;
|
||||||
@@ -37,7 +38,6 @@ import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
|
|||||||
import net.minecraft.world.entity.ai.goal.RandomStrollGoal;
|
import net.minecraft.world.entity.ai.goal.RandomStrollGoal;
|
||||||
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
|
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
|
||||||
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.DifficultyInstance;
|
import net.minecraft.world.DifficultyInstance;
|
||||||
import net.minecraft.world.entity.monster.Monster;
|
import net.minecraft.world.entity.monster.Monster;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
@@ -55,6 +55,9 @@ import software.bernie.geckolib.animation.RawAnimation;
|
|||||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
||||||
private static final byte CLAW_ATTACK_EVENT = 4;
|
private static final byte CLAW_ATTACK_EVENT = 4;
|
||||||
@@ -85,6 +88,21 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
private static final float HARDEN_HEAL_AMOUNT = 2.0F;
|
private static final float HARDEN_HEAL_AMOUNT = 2.0F;
|
||||||
private static final int HARDEN_MIN_DURATION_TICKS = 100;
|
private static final int HARDEN_MIN_DURATION_TICKS = 100;
|
||||||
private static final int HARDEN_MAX_DURATION_TICKS = 200;
|
private static final int HARDEN_MAX_DURATION_TICKS = 200;
|
||||||
|
private static final double CLAW_VERTICAL_TOLERANCE = 2.5D;
|
||||||
|
private static final double STING_VERTICAL_TOLERANCE = 3.25D;
|
||||||
|
private static final double CLAW_FORWARD_DOT = 0.05D;
|
||||||
|
private static final double STING_FORWARD_DOT = 0.45D;
|
||||||
|
private static final double CLAW_STRIKE_FORWARD = 2.6D;
|
||||||
|
private static final double STING_STRIKE_FORWARD = 3.4D;
|
||||||
|
private static final double CLAW_STRIKE_RADIUS = 2.35D;
|
||||||
|
private static final double STING_STRIKE_RADIUS = 2.15D;
|
||||||
|
private static final double ENCOUNTER_HOME_RADIUS = 72.0D;
|
||||||
|
private static final double ENCOUNTER_LEASH_RADIUS = 96.0D;
|
||||||
|
private static final double HOME_REACHED_RADIUS = 9.0D;
|
||||||
|
private static final double FORCED_RETURN_RADIUS = 144.0D;
|
||||||
|
private static final int RESET_DELAY_TICKS = 240;
|
||||||
|
private static final double HOME_RETURN_SPEED = 1.0D;
|
||||||
|
private static final double NEARBY_SCORPION_CHECK_RADIUS = 32.0D;
|
||||||
|
|
||||||
private static final ResourceKey<Level> THORAXIS_KEY =
|
private static final ResourceKey<Level> THORAXIS_KEY =
|
||||||
ResourceKey.create(Registries.DIMENSION,
|
ResourceKey.create(Registries.DIMENSION,
|
||||||
@@ -113,12 +131,17 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
private int hardenDurationTicks;
|
private int hardenDurationTicks;
|
||||||
private int hardenHealTicks;
|
private int hardenHealTicks;
|
||||||
private int hardenSummonedScorpions;
|
private int hardenSummonedScorpions;
|
||||||
|
private int disengageTicks;
|
||||||
private float hardenLockedYaw;
|
private float hardenLockedYaw;
|
||||||
private float hardenLockedPitch;
|
private float hardenLockedPitch;
|
||||||
|
private float attackYaw;
|
||||||
private boolean attackDamageApplied;
|
private boolean attackDamageApplied;
|
||||||
private AttackType currentAttack = AttackType.NONE;
|
private AttackType currentAttack = AttackType.NONE;
|
||||||
private HardenPhase hardenPhase = HardenPhase.NONE;
|
private HardenPhase hardenPhase = HardenPhase.NONE;
|
||||||
|
private AttackType previousAttack = AttackType.NONE;
|
||||||
|
@Nullable private BlockPos encounterHome;
|
||||||
@Nullable private LivingEntity attackTarget;
|
@Nullable private LivingEntity attackTarget;
|
||||||
|
private final Set<UUID> summonedScorpionIds = new HashSet<>();
|
||||||
|
|
||||||
public EmperorScorpionEntity(EntityType<? extends EmperorScorpionEntity> entityType, Level level) {
|
public EmperorScorpionEntity(EntityType<? extends EmperorScorpionEntity> entityType, Level level) {
|
||||||
super(entityType, level);
|
super(entityType, level);
|
||||||
@@ -137,6 +160,13 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.FOLLOW_RANGE, AntarchySettings.emperorScorpionFollowRange());
|
.add(Attributes.FOLLOW_RANGE, AntarchySettings.emperorScorpionFollowRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
super.defineSynchedData(builder);
|
super.defineSynchedData(builder);
|
||||||
@@ -204,7 +234,11 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
if (!this.level().isClientSide) {
|
||||||
|
this.tickEncounterState();
|
||||||
|
}
|
||||||
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
|
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
|
||||||
|
this.bossEvent.setVisible(this.shouldShowBossBar());
|
||||||
|
|
||||||
if (this.clawCooldownTicks > 0) {
|
if (this.clawCooldownTicks > 0) {
|
||||||
this.clawCooldownTicks--;
|
this.clawCooldownTicks--;
|
||||||
@@ -271,8 +305,10 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
this.attackTarget = target;
|
this.attackTarget = target;
|
||||||
this.currentAttack = attackType;
|
this.currentAttack = attackType;
|
||||||
|
this.previousAttack = attackType;
|
||||||
this.attackAnimTicks = attackType.animTicks();
|
this.attackAnimTicks = attackType.animTicks();
|
||||||
this.attackDamageApplied = false;
|
this.attackDamageApplied = false;
|
||||||
|
this.attackYaw = this.getYRot();
|
||||||
this.getNavigation().stop();
|
this.getNavigation().stop();
|
||||||
if (attackType == AttackType.CLAW) {
|
if (attackType == AttackType.CLAW) {
|
||||||
this.clawCooldownTicks = AntarchySettings.emperorScorpionClawCooldownTicks();
|
this.clawCooldownTicks = AntarchySettings.emperorScorpionClawCooldownTicks();
|
||||||
@@ -291,7 +327,12 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.attackAnimTicks > this.currentAttack.commitTick()) {
|
||||||
this.getLookControl().setLookAt(this.attackTarget, 30.0F, 30.0F);
|
this.getLookControl().setLookAt(this.attackTarget, 30.0F, 30.0F);
|
||||||
|
this.attackYaw = this.getYRot();
|
||||||
|
} else {
|
||||||
|
this.lockAttackRotation();
|
||||||
|
}
|
||||||
if (!this.attackDamageApplied
|
if (!this.attackDamageApplied
|
||||||
&& this.attackAnimTicks == this.currentAttack.hitTick()
|
&& this.attackAnimTicks == this.currentAttack.hitTick()
|
||||||
&& this.canHitAttackTarget(this.attackTarget, this.currentAttack)) {
|
&& this.canHitAttackTarget(this.attackTarget, this.currentAttack)) {
|
||||||
@@ -305,8 +346,28 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean canHitAttackTarget(LivingEntity target, AttackType attackType) {
|
private boolean canHitAttackTarget(LivingEntity target, AttackType attackType) {
|
||||||
double range = attackType == AttackType.STING ? STING_RANGE : CLAW_RANGE;
|
if (!target.isAlive() || !this.hasLineOfSight(target)) {
|
||||||
return this.distanceToSqr(target) <= range * range && this.hasLineOfSight(target);
|
return false;
|
||||||
|
}
|
||||||
|
Vec3 origin = this.getStrikeOrigin(attackType);
|
||||||
|
Vec3 targetCenter = target.position().add(0.0D, target.getBbHeight() * 0.5D, 0.0D);
|
||||||
|
Vec3 offset = targetCenter.subtract(origin);
|
||||||
|
double verticalTolerance = attackType == AttackType.STING ? STING_VERTICAL_TOLERANCE : CLAW_VERTICAL_TOLERANCE;
|
||||||
|
if (Math.abs(offset.y) > verticalTolerance) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Vec3 horizontal = new Vec3(offset.x, 0.0D, offset.z);
|
||||||
|
if (horizontal.lengthSqr() < 1.0E-6D) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Vec3 forward = Vec3.directionFromRotation(0.0F, this.attackYaw);
|
||||||
|
double forwardDot = horizontal.normalize().dot(new Vec3(forward.x, 0.0D, forward.z).normalize());
|
||||||
|
double minForwardDot = attackType == AttackType.STING ? STING_FORWARD_DOT : CLAW_FORWARD_DOT;
|
||||||
|
if (forwardDot < minForwardDot) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double strikeRadius = attackType == AttackType.STING ? STING_STRIKE_RADIUS : CLAW_STRIKE_RADIUS;
|
||||||
|
return origin.distanceToSqr(targetCenter) <= strikeRadius * strikeRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetAttackState() {
|
private void resetAttackState() {
|
||||||
@@ -316,6 +377,13 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
this.attackTarget = null;
|
this.attackTarget = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vec3 getStrikeOrigin(AttackType attackType) {
|
||||||
|
Vec3 forward = Vec3.directionFromRotation(0.0F, this.attackYaw);
|
||||||
|
double forwardOffset = attackType == AttackType.STING ? STING_STRIKE_FORWARD : CLAW_STRIKE_FORWARD;
|
||||||
|
double verticalOffset = attackType == AttackType.STING ? this.getBbHeight() * 0.8D : this.getBbHeight() * 0.52D;
|
||||||
|
return this.position().add(forward.x * forwardOffset, verticalOffset, forward.z * forwardOffset);
|
||||||
|
}
|
||||||
|
|
||||||
private void tickHardenState() {
|
private void tickHardenState() {
|
||||||
if (this.getHardenPhase() == HardenPhase.NONE) {
|
if (this.getHardenPhase() == HardenPhase.NONE) {
|
||||||
if (this.hardenCooldownTicks <= 0 && this.getTarget() != null && this.getTarget().isAlive()) {
|
if (this.hardenCooldownTicks <= 0 && this.getTarget() != null && this.getTarget().isAlive()) {
|
||||||
@@ -330,9 +398,13 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
switch (this.getHardenPhase()) {
|
switch (this.getHardenPhase()) {
|
||||||
case CASTING -> {
|
case CASTING -> {
|
||||||
|
LivingEntity target = this.getTarget();
|
||||||
|
if (target != null) {
|
||||||
|
this.getLookControl().setLookAt(target, 20.0F, 20.0F);
|
||||||
|
}
|
||||||
if (this.hardenCastTicks % this.hardenCastSpawnTicks == 0
|
if (this.hardenCastTicks % this.hardenCastSpawnTicks == 0
|
||||||
&& this.hardenSummonedScorpions < AntarchySettings.emperorScorpionMaxSummonedScorpions()
|
&& this.hardenSummonedScorpions < AntarchySettings.emperorScorpionMaxSummonedScorpions()
|
||||||
&& this.countNearbyScorpionMinions() < AntarchySettings.emperorScorpionMaxNearbyScorpions()) {
|
&& this.countOwnedNearbyScorpionMinions() < AntarchySettings.emperorScorpionMaxNearbyScorpions()) {
|
||||||
this.summonScorpionMinion();
|
this.summonScorpionMinion();
|
||||||
this.hardenSummonedScorpions++;
|
this.hardenSummonedScorpions++;
|
||||||
if (this.hardenSummonedScorpions >= AntarchySettings.emperorScorpionMaxSummonedScorpions()) {
|
if (this.hardenSummonedScorpions >= AntarchySettings.emperorScorpionMaxSummonedScorpions()) {
|
||||||
@@ -369,7 +441,7 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
this.setDeltaMovement(0.0D, motion.y, 0.0D);
|
this.setDeltaMovement(0.0D, motion.y, 0.0D);
|
||||||
if (--this.hardenStateTicks <= 0) {
|
if (--this.hardenStateTicks <= 0) {
|
||||||
this.setHardenPhase(HardenPhase.NONE);
|
this.setHardenPhase(HardenPhase.NONE);
|
||||||
this.hardenCooldownTicks = Math.max(1, AntarchySettings.emperorScorpionSummonIntervalTicks());
|
this.hardenCooldownTicks = Math.max(1, AntarchySettings.emperorScorpionHardenCooldownTicks());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,6 +456,7 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
this.hardenHealTicks = 0;
|
this.hardenHealTicks = 0;
|
||||||
this.hardenSummonedScorpions = 0;
|
this.hardenSummonedScorpions = 0;
|
||||||
this.resetAttackState();
|
this.resetAttackState();
|
||||||
|
this.previousAttack = AttackType.NONE;
|
||||||
this.getNavigation().stop();
|
this.getNavigation().stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,13 +481,12 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
this.setAggressive(false);
|
this.setAggressive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final double NEARBY_SCORPION_CHECK_RADIUS = 24.0D;
|
private int countOwnedNearbyScorpionMinions() {
|
||||||
|
UUID ownerId = this.getUUID();
|
||||||
private int countNearbyScorpionMinions() {
|
|
||||||
return this.level().getEntitiesOfClass(
|
return this.level().getEntitiesOfClass(
|
||||||
ScorpionEntity.class,
|
ScorpionEntity.class,
|
||||||
this.getBoundingBox().inflate(NEARBY_SCORPION_CHECK_RADIUS),
|
this.getBoundingBox().inflate(NEARBY_SCORPION_CHECK_RADIUS),
|
||||||
Entity::isAlive
|
scorpion -> scorpion.isAlive() && scorpion.isSummonedFor(ownerId)
|
||||||
).size();
|
).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,16 +500,19 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vec3 anchor = this.getTarget() != null ? this.getTarget().position() : this.position();
|
||||||
Vec3 ring = Vec3.directionFromRotation(0.0F, this.random.nextFloat() * 360.0F)
|
Vec3 ring = Vec3.directionFromRotation(0.0F, this.random.nextFloat() * 360.0F)
|
||||||
.scale(2.75D + this.random.nextDouble() * 1.75D);
|
.scale(2.75D + this.random.nextDouble() * 1.75D);
|
||||||
BlockPos spawnPos = BlockPos.containing(this.getX() + ring.x, this.getY(), this.getZ() + ring.z);
|
BlockPos spawnPos = BlockPos.containing(anchor.x + ring.x, this.getY(), anchor.z + ring.z);
|
||||||
scorpion.moveTo(spawnPos.getX() + 0.5D, spawnPos.getY(), spawnPos.getZ() + 0.5D, this.random.nextFloat() * 360.0F, 0.0F);
|
scorpion.moveTo(spawnPos.getX() + 0.5D, spawnPos.getY(), spawnPos.getZ() + 0.5D, this.random.nextFloat() * 360.0F, 0.0F);
|
||||||
scorpion.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(spawnPos), MobSpawnType.MOB_SUMMONED, null);
|
scorpion.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(spawnPos), MobSpawnType.MOB_SUMMONED, null);
|
||||||
scorpion.setPersistenceRequired();
|
scorpion.setPersistenceRequired();
|
||||||
|
scorpion.setSummonOwner(this.getUUID());
|
||||||
if (this.getTarget() instanceof LivingEntity target) {
|
if (this.getTarget() instanceof LivingEntity target) {
|
||||||
scorpion.setTarget(target);
|
scorpion.setTarget(target);
|
||||||
}
|
}
|
||||||
serverLevel.addFreshEntity(scorpion);
|
serverLevel.addFreshEntity(scorpion);
|
||||||
|
this.summonedScorpionIds.add(scorpion.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) {
|
private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) {
|
||||||
@@ -447,6 +522,7 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
horizontal = horizontal.normalize().scale(horizontalSpeed);
|
horizontal = horizontal.normalize().scale(horizontalSpeed);
|
||||||
|
this.attackYaw = (float) (net.minecraft.util.Mth.atan2(horizontal.z, horizontal.x) * (180.0D / Math.PI)) - 90.0F;
|
||||||
this.setDeltaMovement(this.getDeltaMovement().add(horizontal.x, verticalSpeed, horizontal.z));
|
this.setDeltaMovement(this.getDeltaMovement().add(horizontal.x, verticalSpeed, horizontal.z));
|
||||||
this.hasImpulse = true;
|
this.hasImpulse = true;
|
||||||
}
|
}
|
||||||
@@ -509,6 +585,14 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
this.entityData.set(HARDEN_PHASE, phase.ordinal());
|
this.entityData.set(HARDEN_PHASE, phase.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void lockAttackRotation() {
|
||||||
|
this.setYRot(this.attackYaw);
|
||||||
|
this.setYHeadRot(this.attackYaw);
|
||||||
|
this.yBodyRot = this.attackYaw;
|
||||||
|
this.yBodyRotO = this.attackYaw;
|
||||||
|
this.yHeadRotO = this.attackYaw;
|
||||||
|
}
|
||||||
|
|
||||||
private void lockHardenRotation() {
|
private void lockHardenRotation() {
|
||||||
if (!this.isHardenSequenceActive()) {
|
if (!this.isHardenSequenceActive()) {
|
||||||
return;
|
return;
|
||||||
@@ -600,6 +684,11 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
tag.putInt("HardenDurationTicks", this.hardenDurationTicks);
|
tag.putInt("HardenDurationTicks", this.hardenDurationTicks);
|
||||||
tag.putInt("HardenHealTicks", this.hardenHealTicks);
|
tag.putInt("HardenHealTicks", this.hardenHealTicks);
|
||||||
tag.putInt("HardenSummonedScorpions", this.hardenSummonedScorpions);
|
tag.putInt("HardenSummonedScorpions", this.hardenSummonedScorpions);
|
||||||
|
if (this.encounterHome != null) {
|
||||||
|
tag.putInt("EncounterHomeX", this.encounterHome.getX());
|
||||||
|
tag.putInt("EncounterHomeY", this.encounterHome.getY());
|
||||||
|
tag.putInt("EncounterHomeZ", this.encounterHome.getZ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -631,6 +720,16 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
if (tag.contains("HardenSummonedScorpions")) {
|
if (tag.contains("HardenSummonedScorpions")) {
|
||||||
this.hardenSummonedScorpions = tag.getInt("HardenSummonedScorpions");
|
this.hardenSummonedScorpions = tag.getInt("HardenSummonedScorpions");
|
||||||
}
|
}
|
||||||
|
if (tag.contains("EncounterHomeX") && tag.contains("EncounterHomeY") && tag.contains("EncounterHomeZ")) {
|
||||||
|
this.encounterHome = new BlockPos(tag.getInt("EncounterHomeX"), tag.getInt("EncounterHomeY"), tag.getInt("EncounterHomeZ"));
|
||||||
|
}
|
||||||
|
this.resetAttackState();
|
||||||
|
this.attackYaw = this.getYRot();
|
||||||
|
if (this.getHardenPhase() == HardenPhase.CASTING) {
|
||||||
|
this.setHardenPhase(HardenPhase.NONE);
|
||||||
|
}
|
||||||
|
this.disengageTicks = 0;
|
||||||
|
this.summonedScorpionIds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -653,6 +752,9 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(RemovalReason reason) {
|
public void remove(RemovalReason reason) {
|
||||||
|
if (!this.level().isClientSide) {
|
||||||
|
this.discardOwnedScorpions();
|
||||||
|
}
|
||||||
super.remove(reason);
|
super.remove(reason);
|
||||||
this.bossEvent.removeAllPlayers();
|
this.bossEvent.removeAllPlayers();
|
||||||
}
|
}
|
||||||
@@ -661,6 +763,148 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
return this.attackAnimTicks > 0;
|
return this.attackAnimTicks > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tickEncounterState() {
|
||||||
|
if (this.encounterHome == null) {
|
||||||
|
this.encounterHome = this.blockPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
LivingEntity target = this.getTarget();
|
||||||
|
if (!this.isValidEncounterTarget(target)) {
|
||||||
|
if (target != null) {
|
||||||
|
this.setTarget(null);
|
||||||
|
}
|
||||||
|
target = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target != null) {
|
||||||
|
this.disengageTicks = 0;
|
||||||
|
if (this.isOutsideLeashRadius()) {
|
||||||
|
this.resetEncounter(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isAttackLocked() || this.isHardenSequenceActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.hasOwnedScorpionsNearby()) {
|
||||||
|
this.disengageTicks = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isAtEncounterHome()) {
|
||||||
|
this.disengageTicks++;
|
||||||
|
if (this.disengageTicks >= RESET_DELAY_TICKS) {
|
||||||
|
this.resetEncounter(true);
|
||||||
|
} else {
|
||||||
|
this.navigateHome();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.disengageTicks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidEncounterTarget(@Nullable LivingEntity target) {
|
||||||
|
if (target == null || !target.isAlive() || !target.level().equals(this.level())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (target instanceof Player player && (player.isCreative() || player.isSpectator())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.encounterHome == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return target.distanceToSqr(Vec3.atCenterOf(this.encounterHome)) <= ENCOUNTER_LEASH_RADIUS * ENCOUNTER_LEASH_RADIUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldShowBossBar() {
|
||||||
|
return this.getTarget() != null
|
||||||
|
|| this.isAttackLocked()
|
||||||
|
|| this.isHardenSequenceActive()
|
||||||
|
|| this.hasOwnedScorpionsNearby()
|
||||||
|
|| !this.isAtEncounterHome();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAtEncounterHome() {
|
||||||
|
if (this.encounterHome == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.distanceToSqr(Vec3.atCenterOf(this.encounterHome)) <= HOME_REACHED_RADIUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOutsideLeashRadius() {
|
||||||
|
if (this.encounterHome == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.distanceToSqr(Vec3.atCenterOf(this.encounterHome)) > ENCOUNTER_LEASH_RADIUS * ENCOUNTER_LEASH_RADIUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasOwnedScorpionsNearby() {
|
||||||
|
return this.countOwnedNearbyScorpionMinions() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void navigateHome() {
|
||||||
|
if (this.encounterHome == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Vec3 homeCenter = Vec3.atCenterOf(this.encounterHome);
|
||||||
|
if (this.distanceToSqr(homeCenter) > FORCED_RETURN_RADIUS * FORCED_RETURN_RADIUS) {
|
||||||
|
this.moveTo(homeCenter.x, this.encounterHome.getY(), homeCenter.z, this.getYRot(), this.getXRot());
|
||||||
|
this.setDeltaMovement(Vec3.ZERO);
|
||||||
|
this.hasImpulse = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.getNavigation().moveTo(homeCenter.x, this.encounterHome.getY(), homeCenter.z, HOME_RETURN_SPEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetEncounter(boolean restoreHealth) {
|
||||||
|
this.resetAttackState();
|
||||||
|
this.getNavigation().stop();
|
||||||
|
this.setTarget(null);
|
||||||
|
this.setAggressive(false);
|
||||||
|
this.setHardenPhase(HardenPhase.NONE);
|
||||||
|
this.hardenCastTicks = 0;
|
||||||
|
this.hardenCastSpawnTicks = 0;
|
||||||
|
this.hardenStateTicks = 0;
|
||||||
|
this.hardenDurationTicks = 0;
|
||||||
|
this.hardenHealTicks = 0;
|
||||||
|
this.hardenSummonedScorpions = 0;
|
||||||
|
this.hardenCooldownTicks = Math.max(1, AntarchySettings.emperorScorpionHardenCooldownTicks());
|
||||||
|
this.disengageTicks = 0;
|
||||||
|
this.previousAttack = AttackType.NONE;
|
||||||
|
if (restoreHealth) {
|
||||||
|
this.setHealth(this.getMaxHealth());
|
||||||
|
}
|
||||||
|
this.discardOwnedScorpions();
|
||||||
|
if (this.encounterHome != null) {
|
||||||
|
Vec3 homeCenter = Vec3.atCenterOf(this.encounterHome);
|
||||||
|
this.moveTo(homeCenter.x, this.encounterHome.getY(), homeCenter.z, this.getYRot(), this.getXRot());
|
||||||
|
this.setDeltaMovement(Vec3.ZERO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void discardOwnedScorpions() {
|
||||||
|
if (!(this.level() instanceof ServerLevel serverLevel)) {
|
||||||
|
this.summonedScorpionIds.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UUID ownerId = this.getUUID();
|
||||||
|
for (UUID scorpionId : Set.copyOf(this.summonedScorpionIds)) {
|
||||||
|
Entity entity = serverLevel.getEntity(scorpionId);
|
||||||
|
if (entity instanceof ScorpionEntity scorpion && scorpion.isAlive() && scorpion.isSummonedFor(ownerId)) {
|
||||||
|
scorpion.remove(RemovalReason.DISCARDED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.level().getEntitiesOfClass(
|
||||||
|
ScorpionEntity.class,
|
||||||
|
this.getBoundingBox().inflate(NEARBY_SCORPION_CHECK_RADIUS * 2.0D),
|
||||||
|
scorpion -> scorpion.isAlive() && scorpion.isSummonedFor(ownerId)
|
||||||
|
).forEach(scorpion -> scorpion.remove(RemovalReason.DISCARDED));
|
||||||
|
this.summonedScorpionIds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isHardenSequenceActive() {
|
public boolean isHardenSequenceActive() {
|
||||||
return this.getHardenPhase() != HardenPhase.NONE;
|
return this.getHardenPhase() != HardenPhase.NONE;
|
||||||
}
|
}
|
||||||
@@ -761,23 +1005,31 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWithinMeleeAttackRange(LivingEntity target) {
|
public boolean isWithinMeleeAttackRange(LivingEntity target) {
|
||||||
|
if (this.encounterHome != null && target.distanceToSqr(Vec3.atCenterOf(this.encounterHome)) > ENCOUNTER_HOME_RADIUS * ENCOUNTER_HOME_RADIUS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return this.distanceToSqr(target) <= STING_RANGE * STING_RANGE;
|
return this.distanceToSqr(target) <= STING_RANGE * STING_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AttackType selectAttack(LivingEntity target) {
|
private AttackType selectAttack(LivingEntity target) {
|
||||||
boolean inClawRange = this.clawCooldownTicks <= 0 && this.distanceToSqr(target) <= CLAW_RANGE * CLAW_RANGE;
|
double horizontalDistance = this.distanceToSqr(target);
|
||||||
boolean inStingRange = this.stingCooldownTicks <= 0 && this.distanceToSqr(target) <= STING_RANGE * STING_RANGE;
|
boolean inClawRange = this.clawCooldownTicks <= 0 && horizontalDistance <= CLAW_RANGE * CLAW_RANGE;
|
||||||
|
boolean inStingRange = this.stingCooldownTicks <= 0 && horizontalDistance <= STING_RANGE * STING_RANGE;
|
||||||
boolean canClaw = inClawRange && this.hasLineOfSight(target);
|
boolean canClaw = inClawRange && this.hasLineOfSight(target);
|
||||||
boolean canSting = inStingRange && this.hasLineOfSight(target);
|
boolean canSting = inStingRange && this.hasLineOfSight(target);
|
||||||
if (canSting && (!canClaw || this.random.nextFloat() < 0.3F)) {
|
if (canClaw && canSting) {
|
||||||
|
double heightDifference = target.getY() - this.getY();
|
||||||
|
if (heightDifference > 1.25D || horizontalDistance > CLAW_RANGE * CLAW_RANGE * 0.7D) {
|
||||||
|
return this.previousAttack == AttackType.STING && this.random.nextFloat() < 0.5F ? AttackType.CLAW : AttackType.STING;
|
||||||
|
}
|
||||||
|
return this.previousAttack == AttackType.CLAW && this.random.nextFloat() < 0.55F ? AttackType.STING : AttackType.CLAW;
|
||||||
|
}
|
||||||
|
if (canSting) {
|
||||||
return AttackType.STING;
|
return AttackType.STING;
|
||||||
}
|
}
|
||||||
if (canClaw) {
|
if (canClaw) {
|
||||||
return AttackType.CLAW;
|
return AttackType.CLAW;
|
||||||
}
|
}
|
||||||
if (canSting) {
|
|
||||||
return AttackType.STING;
|
|
||||||
}
|
|
||||||
return AttackType.NONE;
|
return AttackType.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -801,6 +1053,14 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
|||||||
default -> 0;
|
default -> 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int commitTick() {
|
||||||
|
return switch (this) {
|
||||||
|
case CLAW -> Math.max(1, this.hitTick() + 3);
|
||||||
|
case STING -> Math.max(1, this.hitTick() + 4);
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum HardenPhase {
|
private enum HardenPhase {
|
||||||
|
|||||||
+7
@@ -202,6 +202,13 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
|||||||
.add(Attributes.ARMOR, 12.0D);
|
.add(Attributes.ARMOR, 12.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.herculesBeetleHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<HerculesBeetleEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<HerculesBeetleEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+7
@@ -62,6 +62,13 @@ public class LurkingTerrorEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.FLYING_SPEED, 0.55D);
|
.add(Attributes.FLYING_SPEED, 0.55D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.lurkingTerrorHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<LurkingTerrorEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<LurkingTerrorEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import net.minecraft.world.entity.LivingEntity;
|
|||||||
import net.minecraft.world.entity.Mob;
|
import net.minecraft.world.entity.Mob;
|
||||||
import net.minecraft.world.entity.MobSpawnType;
|
import net.minecraft.world.entity.MobSpawnType;
|
||||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||||
import net.minecraft.world.entity.ai.goal.FloatGoal;
|
import net.minecraft.world.entity.ai.goal.FloatGoal;
|
||||||
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
|
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
|
||||||
@@ -24,6 +25,7 @@ import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
|||||||
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
|
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
|
||||||
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||||||
import net.minecraft.world.entity.monster.Monster;
|
import net.minecraft.world.entity.monster.Monster;
|
||||||
|
import net.minecraft.world.entity.SpawnGroupData;
|
||||||
import net.minecraft.world.level.block.LeavesBlock;
|
import net.minecraft.world.level.block.LeavesBlock;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
@@ -68,6 +70,7 @@ public class MantisEntity extends Monster implements GeoEntity {
|
|||||||
protected int flyBurstTicks;
|
protected int flyBurstTicks;
|
||||||
protected int flyCooldownTicks;
|
protected int flyCooldownTicks;
|
||||||
private int debugLogTicks = 0;
|
private int debugLogTicks = 0;
|
||||||
|
private int configSyncTicks;
|
||||||
|
|
||||||
public MantisEntity(EntityType<? extends MantisEntity> entityType, Level level) {
|
public MantisEntity(EntityType<? extends MantisEntity> entityType, Level level) {
|
||||||
super(entityType, level);
|
super(entityType, level);
|
||||||
@@ -89,6 +92,13 @@ public class MantisEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.ARMOR, 4.0D);
|
.add(Attributes.ARMOR, 4.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, this.configuredMaxHealth());
|
||||||
|
this.syncConfiguredAttributes(false);
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<MantisEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<MantisEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
if (spawnReason == MobSpawnType.SPAWN_EGG
|
if (spawnReason == MobSpawnType.SPAWN_EGG
|
||||||
|| spawnReason == MobSpawnType.SPAWNER
|
|| spawnReason == MobSpawnType.SPAWNER
|
||||||
@@ -200,6 +210,11 @@ public class MantisEntity extends Monster implements GeoEntity {
|
|||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
if (!this.level().isClientSide) {
|
if (!this.level().isClientSide) {
|
||||||
|
if (this.configSyncTicks-- <= 0) {
|
||||||
|
this.configSyncTicks = 20;
|
||||||
|
this.syncConfiguredAttributes(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.attackAnimationTicks > 0) {
|
if (this.attackAnimationTicks > 0) {
|
||||||
this.attackAnimationTicks--;
|
this.attackAnimationTicks--;
|
||||||
}
|
}
|
||||||
@@ -278,6 +293,22 @@ public class MantisEntity extends Monster implements GeoEntity {
|
|||||||
return COMBAT_SPEED;
|
return COMBAT_SPEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected double configuredMaxHealth() {
|
||||||
|
return AntarchySettings.mantisHealth();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected double configuredAttackDamage() {
|
||||||
|
return AntarchySettings.mantisAttackDamage();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected double configuredMovementSpeed() {
|
||||||
|
return AntarchySettings.mantisMovementSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected double configuredFlyingSpeed() {
|
||||||
|
return AntarchySettings.mantisFlyingSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
protected void onActiveTarget(LivingEntity target) {
|
protected void onActiveTarget(LivingEntity target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,6 +380,36 @@ public class MantisEntity extends Monster implements GeoEntity {
|
|||||||
return this.flyBurstTicks > 0;
|
return this.flyBurstTicks > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncConfiguredAttributes(boolean rescaleCurrentHealth) {
|
||||||
|
syncAttribute(this.getAttribute(Attributes.MAX_HEALTH), this.configuredMaxHealth(), rescaleCurrentHealth);
|
||||||
|
syncAttribute(this.getAttribute(Attributes.ATTACK_DAMAGE), this.configuredAttackDamage(), false);
|
||||||
|
syncAttribute(this.getAttribute(Attributes.MOVEMENT_SPEED), this.configuredMovementSpeed(), false);
|
||||||
|
syncAttribute(this.getAttribute(Attributes.FLYING_SPEED), this.configuredFlyingSpeed(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncAttribute(@Nullable AttributeInstance attributeInstance, double desiredValue, boolean rescaleCurrentHealth) {
|
||||||
|
if (attributeInstance == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double previousValue = attributeInstance.getBaseValue();
|
||||||
|
if (Math.abs(previousValue - desiredValue) < 1.0E-6D) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeInstance.setBaseValue(desiredValue);
|
||||||
|
if (!rescaleCurrentHealth) {
|
||||||
|
this.setHealth((float) this.getMaxHealth());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float currentHealth = this.getHealth();
|
||||||
|
float syncedHealth = previousValue > 0.0D
|
||||||
|
? (float) net.minecraft.util.Mth.clamp((currentHealth / (float) previousValue) * desiredValue, 0.0D, desiredValue)
|
||||||
|
: (float) desiredValue;
|
||||||
|
this.setHealth(syncedHealth);
|
||||||
|
}
|
||||||
|
|
||||||
private void tickDebugLog() {
|
private void tickDebugLog() {
|
||||||
if (++this.debugLogTicks < 100) {
|
if (++this.debugLogTicks < 100) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+7
@@ -109,6 +109,13 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.KNOCKBACK_RESISTANCE, AntarchySettings.missileSquidKnockbackResistance());
|
.add(Attributes.KNOCKBACK_RESISTANCE, AntarchySettings.missileSquidKnockbackResistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.missileSquidHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<MissileSquidEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<MissileSquidEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
return level.getDifficulty() != Difficulty.PEACEFUL
|
return level.getDifficulty() != Difficulty.PEACEFUL
|
||||||
&& pos.getY() <= level.getSeaLevel() - 10
|
&& pos.getY() <= level.getSeaLevel() - 10
|
||||||
|
|||||||
+6
-1
@@ -59,6 +59,10 @@ public class MolevoreEntity extends Monster implements GeoEntity {
|
|||||||
Registries.BIOME,
|
Registries.BIOME,
|
||||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "moleworm_caves")
|
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "moleworm_caves")
|
||||||
);
|
);
|
||||||
|
private static final ResourceKey<Biome> CAVARYN_MOLEWORM_CAVES = ResourceKey.create(
|
||||||
|
Registries.BIOME,
|
||||||
|
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "cavaryn_moleworm_caves")
|
||||||
|
);
|
||||||
private static final EntityDataAccessor<Integer> ACTION_STATE = SynchedEntityData.defineId(MolevoreEntity.class, EntityDataSerializers.INT);
|
private static final EntityDataAccessor<Integer> ACTION_STATE = SynchedEntityData.defineId(MolevoreEntity.class, EntityDataSerializers.INT);
|
||||||
|
|
||||||
private static final int ACTION_NONE = 0;
|
private static final int ACTION_NONE = 0;
|
||||||
@@ -122,7 +126,7 @@ public class MolevoreEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasSpawnPocket(LevelAccessor level, BlockPos pos) {
|
private static boolean hasSpawnPocket(LevelAccessor level, BlockPos pos) {
|
||||||
if (!level.getBiome(pos).is(MOLEWORM_CAVES)) {
|
if (!level.getBiome(pos).is(MOLEWORM_CAVES) && !level.getBiome(pos).is(CAVARYN_MOLEWORM_CAVES)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +184,7 @@ public class MolevoreEntity extends Monster implements GeoEntity {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
||||||
SpawnGroupData finalized = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
SpawnGroupData finalized = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.molevoreHealth());
|
||||||
if (spawnReason != MobSpawnType.SPAWN_EGG) {
|
if (spawnReason != MobSpawnType.SPAWN_EGG) {
|
||||||
this.startDigUp();
|
this.startDigUp();
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -80,6 +80,13 @@ public class MolewormEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.ATTACK_DAMAGE, AntarchySettings.molewormAttackDamage());
|
.add(Attributes.ATTACK_DAMAGE, AntarchySettings.molewormAttackDamage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.molewormHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static boolean canSpawn(EntityType<MolewormEntity> entityType, LevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<MolewormEntity> entityType, LevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
return Silverfish.checkSilverfishSpawnRules((EntityType<Silverfish>) (EntityType<?>) entityType, level, spawnReason, pos, random);
|
return Silverfish.checkSilverfishSpawnRules((EntityType<Silverfish>) (EntityType<?>) entityType, level, spawnReason, pos, random);
|
||||||
|
|||||||
+1
@@ -160,6 +160,7 @@ public class OuranwoodDeerEntity extends Animal implements GeoEntity {
|
|||||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
||||||
DeerSpawnData deerSpawnData = spawnGroupData instanceof DeerSpawnData data ? data : new DeerSpawnData();
|
DeerSpawnData deerSpawnData = spawnGroupData instanceof DeerSpawnData data ? data : new DeerSpawnData();
|
||||||
SpawnGroupData result = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
SpawnGroupData result = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.ouranwoodDeerHealth());
|
||||||
|
|
||||||
if (spawnReason == MobSpawnType.NATURAL || spawnReason == MobSpawnType.CHUNK_GENERATION || spawnReason == MobSpawnType.SPAWN_EGG) {
|
if (spawnReason == MobSpawnType.NATURAL || spawnReason == MobSpawnType.CHUNK_GENERATION || spawnReason == MobSpawnType.SPAWN_EGG) {
|
||||||
this.setVariant(Variant.values()[this.random.nextInt(Variant.values().length)]);
|
this.setVariant(Variant.values()[this.random.nextInt(Variant.values().length)]);
|
||||||
|
|||||||
@@ -204,6 +204,13 @@ public class ReverieEntity extends PathfinderMob implements FlyingAnimal, GeoEnt
|
|||||||
.add(Attributes.FOLLOW_RANGE, 32.0D);
|
.add(Attributes.FOLLOW_RANGE, 32.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.reverieHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<ReverieEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<ReverieEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+7
@@ -120,6 +120,13 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
|||||||
.add(Attributes.FOLLOW_RANGE, 16.0D);
|
.add(Attributes.FOLLOW_RANGE, 16.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.rollyPollyHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
super.defineSynchedData(builder);
|
super.defineSynchedData(builder);
|
||||||
|
|||||||
+22
@@ -44,11 +44,14 @@ import software.bernie.geckolib.animation.RawAnimation;
|
|||||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ScorpionEntity extends Monster implements GeoEntity {
|
public class ScorpionEntity extends Monster implements GeoEntity {
|
||||||
private static final byte ATTACK_ANIM_EVENT = 4;
|
private static final byte ATTACK_ANIM_EVENT = 4;
|
||||||
private static final EntityDataAccessor<Integer> TEXTURE_VARIANT =
|
private static final EntityDataAccessor<Integer> TEXTURE_VARIANT =
|
||||||
SynchedEntityData.defineId(ScorpionEntity.class, EntityDataSerializers.INT);
|
SynchedEntityData.defineId(ScorpionEntity.class, EntityDataSerializers.INT);
|
||||||
private static final String TEXTURE_VARIANT_KEY = "TextureVariant";
|
private static final String TEXTURE_VARIANT_KEY = "TextureVariant";
|
||||||
|
private static final String SUMMON_OWNER_KEY = "SummonOwner";
|
||||||
public static final int BLUE_VARIANT = 0;
|
public static final int BLUE_VARIANT = 0;
|
||||||
public static final int GREEN_VARIANT = 1;
|
public static final int GREEN_VARIANT = 1;
|
||||||
|
|
||||||
@@ -67,6 +70,7 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
private int attackCooldownTicks = 0;
|
private int attackCooldownTicks = 0;
|
||||||
private boolean attackDamageApplied = false;
|
private boolean attackDamageApplied = false;
|
||||||
@Nullable private LivingEntity attackTarget;
|
@Nullable private LivingEntity attackTarget;
|
||||||
|
@Nullable private UUID summonOwner;
|
||||||
|
|
||||||
public ScorpionEntity(EntityType<? extends ScorpionEntity> entityType, Level level) {
|
public ScorpionEntity(EntityType<? extends ScorpionEntity> entityType, Level level) {
|
||||||
super(entityType, level);
|
super(entityType, level);
|
||||||
@@ -115,6 +119,7 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
@Override
|
@Override
|
||||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData spawnGroupData) {
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData spawnGroupData) {
|
||||||
this.assignRandomTextureVariant();
|
this.assignRandomTextureVariant();
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.scorpionHealth());
|
||||||
return super.finalizeSpawn(level, difficulty, spawnType, spawnGroupData);
|
return super.finalizeSpawn(level, difficulty, spawnType, spawnGroupData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,6 +242,9 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
public void addAdditionalSaveData(CompoundTag tag) {
|
public void addAdditionalSaveData(CompoundTag tag) {
|
||||||
super.addAdditionalSaveData(tag);
|
super.addAdditionalSaveData(tag);
|
||||||
tag.putInt(TEXTURE_VARIANT_KEY, this.getTextureVariant());
|
tag.putInt(TEXTURE_VARIANT_KEY, this.getTextureVariant());
|
||||||
|
if (this.summonOwner != null) {
|
||||||
|
tag.putUUID(SUMMON_OWNER_KEY, this.summonOwner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -247,6 +255,7 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
} else {
|
} else {
|
||||||
this.assignRandomTextureVariant();
|
this.assignRandomTextureVariant();
|
||||||
}
|
}
|
||||||
|
this.summonOwner = tag.hasUUID(SUMMON_OWNER_KEY) ? tag.getUUID(SUMMON_OWNER_KEY) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -277,6 +286,19 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
this.entityData.set(TEXTURE_VARIANT, variant == GREEN_VARIANT ? GREEN_VARIANT : BLUE_VARIANT);
|
this.entityData.set(TEXTURE_VARIANT, variant == GREEN_VARIANT ? GREEN_VARIANT : BLUE_VARIANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSummonOwner(@Nullable UUID summonOwner) {
|
||||||
|
this.summonOwner = summonOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public UUID getSummonOwner() {
|
||||||
|
return this.summonOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSummonedFor(UUID ownerId) {
|
||||||
|
return ownerId.equals(this.summonOwner);
|
||||||
|
}
|
||||||
|
|
||||||
private void assignRandomTextureVariant() {
|
private void assignRandomTextureVariant() {
|
||||||
this.setTextureVariant(this.random.nextBoolean() ? BLUE_VARIANT : GREEN_VARIANT);
|
this.setTextureVariant(this.random.nextBoolean() ? BLUE_VARIANT : GREEN_VARIANT);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -153,6 +153,13 @@ public class ToreterrorEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.ARMOR_TOUGHNESS, 4.0D);
|
.add(Attributes.ARMOR_TOUGHNESS, 4.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.toreterrorHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<ToreterrorEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, net.minecraft.util.RandomSource random) {
|
public static boolean canSpawn(EntityType<ToreterrorEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, net.minecraft.util.RandomSource random) {
|
||||||
boolean sturdy = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP);
|
boolean sturdy = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP);
|
||||||
return level.getDifficulty() != Difficulty.PEACEFUL && sturdy;
|
return level.getDifficulty() != Difficulty.PEACEFUL && sturdy;
|
||||||
|
|||||||
@@ -101,6 +101,13 @@ public class TriffidEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.MOVEMENT_SPEED, 0.0D);
|
.add(Attributes.MOVEMENT_SPEED, 0.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.triffidHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<TriffidEntity> entityType, LevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<TriffidEntity> entityType, LevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
if (pos.getY() < level.getMinBuildHeight() || pos.getY() + 7 >= level.getMaxBuildHeight()) {
|
if (pos.getY() < level.getMinBuildHeight() || pos.getY() + 7 >= level.getMaxBuildHeight()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+25
-5
@@ -2,7 +2,6 @@ package com.craisinlord.antarchy.content.entity;
|
|||||||
|
|
||||||
import com.craisinlord.antarchy.content.block.AntimetalScaffoldingBlock;
|
import com.craisinlord.antarchy.content.block.AntimetalScaffoldingBlock;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||||
@@ -14,6 +13,7 @@ import net.minecraft.world.entity.EntityType;
|
|||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.PointedDripstoneBlock;
|
import net.minecraft.world.level.block.PointedDripstoneBlock;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
@@ -32,6 +32,7 @@ public class UpwardFallingBlockEntity extends Entity {
|
|||||||
private static final int MAX_TICKS = 200;
|
private static final int MAX_TICKS = 200;
|
||||||
|
|
||||||
public int time = 0;
|
public int time = 0;
|
||||||
|
private boolean breaksOnLeaves = true;
|
||||||
|
|
||||||
public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) {
|
public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) {
|
||||||
super(type, level);
|
super(type, level);
|
||||||
@@ -48,6 +49,10 @@ public class UpwardFallingBlockEntity extends Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void fallUp(Level level, BlockPos pos, BlockState state) {
|
public static void fallUp(Level level, BlockPos pos, BlockState state) {
|
||||||
|
fallUp(level, pos, state, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fallUp(Level level, BlockPos pos, BlockState state, boolean breaksOnLeaves) {
|
||||||
if (level.isClientSide) return;
|
if (level.isClientSide) return;
|
||||||
// Prevent stacking multiple entities from the same block position
|
// Prevent stacking multiple entities from the same block position
|
||||||
if (!level.getEntitiesOfClass(UpwardFallingBlockEntity.class, new AABB(pos)).isEmpty()) return;
|
if (!level.getEntitiesOfClass(UpwardFallingBlockEntity.class, new AABB(pos)).isEmpty()) return;
|
||||||
@@ -55,6 +60,7 @@ public class UpwardFallingBlockEntity extends Entity {
|
|||||||
level.removeBlock(pos, false);
|
level.removeBlock(pos, false);
|
||||||
UpwardFallingBlockEntity entity = new UpwardFallingBlockEntity(TYPE.get(), level);
|
UpwardFallingBlockEntity entity = new UpwardFallingBlockEntity(TYPE.get(), level);
|
||||||
entity.entityData.set(DATA_BLOCK_STATE, state);
|
entity.entityData.set(DATA_BLOCK_STATE, state);
|
||||||
|
entity.breaksOnLeaves = breaksOnLeaves;
|
||||||
entity.setPos(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5);
|
entity.setPos(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5);
|
||||||
level.addFreshEntity(entity);
|
level.addFreshEntity(entity);
|
||||||
}
|
}
|
||||||
@@ -90,21 +96,35 @@ public class UpwardFallingBlockEntity extends Entity {
|
|||||||
BlockPos headPos = BlockPos.containing(getX(), getY() + getBbHeight(), getZ());
|
BlockPos headPos = BlockPos.containing(getX(), getY() + getBbHeight(), getZ());
|
||||||
BlockState above = level().getBlockState(headPos);
|
BlockState above = level().getBlockState(headPos);
|
||||||
|
|
||||||
// Leaves block the entity but can't hold scaffolding — drop as item
|
// Leaves block the entity but can't hold scaffolding — drop as item, unless this
|
||||||
if (above.is(BlockTags.LEAVES)) {
|
// instance is allowed to land on leaves like a normal falling block would
|
||||||
|
if (above.is(BlockTags.LEAVES) && this.breaksOnLeaves) {
|
||||||
dropAndRemove(blockState);
|
dropAndRemove(blockState);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hitCeiling = above.isFaceSturdy(level(), headPos, Direction.DOWN);
|
boolean hitCeiling = !above.isAir() && !above.getCollisionShape(level(), headPos).isEmpty();
|
||||||
boolean hitScaffolding = above.getBlock() instanceof AntimetalScaffoldingBlock;
|
boolean hitScaffolding = above.getBlock() instanceof AntimetalScaffoldingBlock;
|
||||||
|
|
||||||
if (hitCeiling || hitScaffolding) {
|
if (hitCeiling || hitScaffolding) {
|
||||||
dropAndRemove(blockState);
|
placeAtLanding(blockState, headPos.below());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void placeAtLanding(BlockState state, BlockPos landingPos) {
|
||||||
|
if (!level().isClientSide) {
|
||||||
|
BlockState existing = level().getBlockState(landingPos);
|
||||||
|
if (existing.canBeReplaced()) {
|
||||||
|
level().setBlock(landingPos, state, Block.UPDATE_ALL);
|
||||||
|
} else {
|
||||||
|
dropAndRemove(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
discard();
|
||||||
|
}
|
||||||
|
|
||||||
private void damageEntitiesAlongPath(BlockState state) {
|
private void damageEntitiesAlongPath(BlockState state) {
|
||||||
float damage = getImpactDamage(state);
|
float damage = getImpactDamage(state);
|
||||||
if (damage <= 0.0F) {
|
if (damage <= 0.0F) {
|
||||||
|
|||||||
+34
@@ -125,6 +125,10 @@ public final class AntTeleportHelper {
|
|||||||
return InteractionResult.PASS;
|
return InteractionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isRightClickDimensionEnabled(entityTypeId)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
if (entityTypeId.equals(ResourceLocation.fromNamespaceAndPath("antarchy", "brown_ant"))) {
|
if (entityTypeId.equals(ResourceLocation.fromNamespaceAndPath("antarchy", "brown_ant"))) {
|
||||||
return teleportToOrFromConfiguredDimension(player, AntarchySettings.brownAntDestinationDimension());
|
return teleportToOrFromConfiguredDimension(player, AntarchySettings.brownAntDestinationDimension());
|
||||||
}
|
}
|
||||||
@@ -156,6 +160,10 @@ public final class AntTeleportHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static InteractionResult handleInteraction(BaseAntEntity ant, Player player, ItemStack itemStack) {
|
static InteractionResult handleInteraction(BaseAntEntity ant, Player player, ItemStack itemStack) {
|
||||||
|
if (!isRightClickDimensionEnabled(ant)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
if (ant.requiresActivationReagent() && !ant.isTeleportActivatedState()) {
|
if (ant.requiresActivationReagent() && !ant.isTeleportActivatedState()) {
|
||||||
if (!(player instanceof ServerPlayer serverPlayer)) {
|
if (!(player instanceof ServerPlayer serverPlayer)) {
|
||||||
return InteractionResult.SUCCESS;
|
return InteractionResult.SUCCESS;
|
||||||
@@ -184,6 +192,32 @@ public final class AntTeleportHelper {
|
|||||||
return teleportToOrFromConfiguredDimension(serverPlayer, ant.destinationDimension());
|
return teleportToOrFromConfiguredDimension(serverPlayer, ant.destinationDimension());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean isRightClickDimensionEnabled(BaseAntEntity ant) {
|
||||||
|
return ant instanceof BrownAntEntity
|
||||||
|
? AntarchySettings.brownAntRightClickDimension()
|
||||||
|
: ant instanceof RedAntEntity
|
||||||
|
? AntarchySettings.redAntRightClickDimension()
|
||||||
|
: ant instanceof RainbowAntEntity
|
||||||
|
? AntarchySettings.rainbowAntRightClickDimension()
|
||||||
|
: ant instanceof TermiteEntity && AntarchySettings.termiteRightClickDimension();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isRightClickDimensionEnabled(ResourceLocation entityTypeId) {
|
||||||
|
if (entityTypeId.equals(ResourceLocation.fromNamespaceAndPath("antarchy", "brown_ant"))) {
|
||||||
|
return AntarchySettings.brownAntRightClickDimension();
|
||||||
|
}
|
||||||
|
if (entityTypeId.equals(ResourceLocation.fromNamespaceAndPath("antarchy", "red_ant"))) {
|
||||||
|
return AntarchySettings.redAntRightClickDimension();
|
||||||
|
}
|
||||||
|
if (entityTypeId.equals(ResourceLocation.fromNamespaceAndPath("antarchy", "rainbow_ant"))) {
|
||||||
|
return AntarchySettings.rainbowAntRightClickDimension();
|
||||||
|
}
|
||||||
|
if (entityTypeId.equals(ResourceLocation.fromNamespaceAndPath("antarchy", "termite"))) {
|
||||||
|
return AntarchySettings.termiteRightClickDimension();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static InteractionResult activateTeleport(BaseAntEntity ant, ServerPlayer player, ItemStack stack) {
|
private static InteractionResult activateTeleport(BaseAntEntity ant, ServerPlayer player, ItemStack stack) {
|
||||||
ant.setTeleportActivatedState(true);
|
ant.setTeleportActivatedState(true);
|
||||||
if (!player.getAbilities().instabuild) {
|
if (!player.getAbilities().instabuild) {
|
||||||
|
|||||||
+7
@@ -158,6 +158,13 @@ public abstract class BaseAntEntity extends Animal implements GeoEntity {
|
|||||||
super(entityType, level);
|
super(entityType, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, this.configuredMaxHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
super.defineSynchedData(builder);
|
super.defineSynchedData(builder);
|
||||||
|
|||||||
+5
@@ -77,6 +77,11 @@ public class RainbowAntEntity extends BaseAntEntity implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionResult mobInteract(Player player, InteractionHand hand) {
|
public InteractionResult mobInteract(Player player, InteractionHand hand) {
|
||||||
|
if (!AntTeleportHelper.isRightClickDimensionEnabled(this)) {
|
||||||
|
ItemStack heldItem = player.getItemInHand(hand);
|
||||||
|
return this.isFood(heldItem) ? super.mobInteract(player, hand) : InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
if (!AntarchySettings.rainbowAntsLeadToInfinityDimensions() || !InfinityCompat.get().isAvailable()) {
|
if (!AntarchySettings.rainbowAntsLeadToInfinityDimensions() || !InfinityCompat.get().isAvailable()) {
|
||||||
return super.mobInteract(player, hand);
|
return super.mobInteract(player, hand);
|
||||||
}
|
}
|
||||||
|
|||||||
+157
-41
@@ -7,6 +7,7 @@ import com.craisinlord.antarchy.content.AntarchyTags;
|
|||||||
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
|
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
@@ -63,6 +64,8 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
SynchedEntityData.defineId(BasiliskEntity.class, EntityDataSerializers.INT);
|
SynchedEntityData.defineId(BasiliskEntity.class, EntityDataSerializers.INT);
|
||||||
private static final byte ATTACK_ENTITY_EVENT = 4;
|
private static final byte ATTACK_ENTITY_EVENT = 4;
|
||||||
private static final int DEATH_TICKS = 25;
|
private static final int DEATH_TICKS = 25;
|
||||||
|
private static final String TAG_HISS_COOLDOWN = "BasiliskHissCooldown";
|
||||||
|
private static final String TAG_PREY_PETRIFY_COOLDOWN = "BasiliskPreyPetrifyCooldown";
|
||||||
|
|
||||||
private static final int ANIM_IDLE = 0;
|
private static final int ANIM_IDLE = 0;
|
||||||
private static final int ANIM_WALK = 1;
|
private static final int ANIM_WALK = 1;
|
||||||
@@ -74,13 +77,15 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
private static final RawAnimation ATTACK_ANIM = RawAnimation.begin().thenPlay("attack");
|
private static final RawAnimation ATTACK_ANIM = RawAnimation.begin().thenPlay("attack");
|
||||||
private static final RawAnimation DEATH_ANIM = RawAnimation.begin().thenPlay("death");
|
private static final RawAnimation DEATH_ANIM = RawAnimation.begin().thenPlay("death");
|
||||||
|
|
||||||
private static final float TURN_RATE_DEG_PER_TICK = 10.0F;
|
private static final float MIN_TURN_RATE_DEG_PER_TICK = 5.5F;
|
||||||
|
private static final float MAX_TURN_RATE_DEG_PER_TICK = 13.5F;
|
||||||
|
|
||||||
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||||
|
|
||||||
private int attackAnimTicks = 0;
|
private int attackAnimTicks = 0;
|
||||||
private boolean attackDamagePending = false;
|
private boolean attackDamagePending = false;
|
||||||
private int attackCooldown = 0;
|
private int attackCooldown = 0;
|
||||||
|
private float committedAttackYaw = Float.NaN;
|
||||||
|
|
||||||
private int hissCooldown = AntarchySettings.basiliskHissCooldownTicks();
|
private int hissCooldown = AntarchySettings.basiliskHissCooldownTicks();
|
||||||
private int hissChargeTimer = 0;
|
private int hissChargeTimer = 0;
|
||||||
@@ -110,6 +115,12 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.FOLLOW_RANGE, AntarchySettings.basiliskFollowRange());
|
.add(Attributes.FOLLOW_RANGE, AntarchySettings.basiliskFollowRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.basiliskHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<BasiliskEntity> entityType, ServerLevelAccessor level,
|
public static boolean canSpawn(EntityType<BasiliskEntity> entityType, ServerLevelAccessor level,
|
||||||
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
if (spawnReason == MobSpawnType.SPAWN_EGG
|
if (spawnReason == MobSpawnType.SPAWN_EGG
|
||||||
@@ -160,9 +171,12 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
private void performAoeAttack() {
|
private void performAoeAttack() {
|
||||||
if (this.level().isClientSide) return;
|
if (this.level().isClientSide) return;
|
||||||
// Start the animation; damage fires later in tick() when attackAnimTicks reaches the damage threshold
|
this.committedAttackYaw = this.resolveCommittedAttackYaw();
|
||||||
this.attackAnimTicks = AntarchySettings.basiliskAttackAnimTicks();
|
this.attackAnimTicks = AntarchySettings.basiliskAttackAnimTicks();
|
||||||
this.attackDamagePending = true;
|
this.attackDamagePending = true;
|
||||||
|
this.stopActiveMovement();
|
||||||
|
this.lockBodyYaw(this.committedAttackYaw);
|
||||||
|
this.setAnimationState(ANIM_ATTACK);
|
||||||
this.level().broadcastEntityEvent(this, ATTACK_ENTITY_EVENT);
|
this.level().broadcastEntityEvent(this, ATTACK_ENTITY_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,33 +187,42 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
this.attackDamagePending = false;
|
this.attackDamagePending = false;
|
||||||
|
|
||||||
Vec3 forward = Vec3.directionFromRotation(0, this.yBodyRot);
|
float attackYaw = Float.isNaN(this.committedAttackYaw) ? this.yBodyRot : this.committedAttackYaw;
|
||||||
|
Vec3 forward = Vec3.directionFromRotation(0, attackYaw);
|
||||||
Vec3 right = new Vec3(-forward.z, 0, forward.x);
|
Vec3 right = new Vec3(-forward.z, 0, forward.x);
|
||||||
Vec3 origin = this.position();
|
Vec3 attackOrigin = this.position();
|
||||||
double attackReach = AntarchySettings.basiliskAttackReach();
|
double attackReach = AntarchySettings.basiliskAttackReach() + 4.0D;
|
||||||
|
double verticalMin = attackOrigin.y - 0.9D;
|
||||||
|
double verticalMax = attackOrigin.y + 2.6D;
|
||||||
|
|
||||||
List<LivingEntity> candidates = this.level().getEntitiesOfClass(
|
List<LivingEntity> candidates = this.level().getEntitiesOfClass(
|
||||||
LivingEntity.class,
|
LivingEntity.class,
|
||||||
this.getBoundingBox().inflate(Math.max(8.0D, attackReach + 3.5D)),
|
new AABB(attackOrigin, attackOrigin).inflate(attackReach + 1.5D, 3.0D, attackReach + 1.5D),
|
||||||
e -> e != this && e.isAlive()
|
e -> e != this && e.isAlive()
|
||||||
);
|
);
|
||||||
|
|
||||||
boolean hitAnything = false;
|
|
||||||
for (LivingEntity entity : candidates) {
|
for (LivingEntity entity : candidates) {
|
||||||
Vec3 toEntity = entity.position().subtract(origin);
|
if (!this.canAttack(entity) || this.isAlliedTo(entity) || !this.hasLineOfSight(entity)) {
|
||||||
double fwdDist = toEntity.dot(forward);
|
continue;
|
||||||
double sideDist = toEntity.dot(right);
|
|
||||||
double upDist = toEntity.y;
|
|
||||||
if (fwdDist >= 2.0 && fwdDist <= 7.0 && Math.abs(sideDist) <= 2.25 && upDist >= -1.0 && upDist <= 3.0) {
|
|
||||||
if (entity.hurt(AntarchyDamageSources.basiliskBite(serverLevel, this),
|
|
||||||
(float) this.getAttributeValue(Attributes.ATTACK_DAMAGE))) {
|
|
||||||
hitAnything = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hitAnything) {
|
AABB entityBox = entity.getBoundingBox();
|
||||||
this.playSound(AntarchySoundEvents.BASILISK_BITE.get(), 1.1F, 0.95F + this.random.nextFloat() * 0.08F);
|
if (entityBox.maxY < verticalMin || entityBox.minY > verticalMax) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 toEntity = entityBox.getCenter().subtract(attackOrigin);
|
||||||
|
double fwdDist = toEntity.dot(forward);
|
||||||
|
double sideDist = toEntity.dot(right);
|
||||||
|
double sideAllowance = 1.35D + entity.getBbWidth() * 0.5D + Math.max(0.0D, fwdDist * 0.2D);
|
||||||
|
if (fwdDist < 1.0D || fwdDist > attackReach || Math.abs(sideDist) > sideAllowance) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.hurt(
|
||||||
|
AntarchyDamageSources.basiliskBite(serverLevel, this),
|
||||||
|
(float) this.getAttributeValue(Attributes.ATTACK_DAMAGE)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +233,12 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
if (this.attackAnimTicks > 0) {
|
if (this.attackAnimTicks > 0) {
|
||||||
this.attackAnimTicks--;
|
this.attackAnimTicks--;
|
||||||
}
|
}
|
||||||
|
if (this.level() instanceof ServerLevel && this.attackAnimTicks > 0 && !Float.isNaN(this.committedAttackYaw)) {
|
||||||
|
this.lockBodyYaw(this.committedAttackYaw);
|
||||||
|
}
|
||||||
|
if (this.attackAnimTicks <= 0) {
|
||||||
|
this.committedAttackYaw = Float.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isDeadOrDying()) {
|
if (this.isDeadOrDying()) {
|
||||||
this.updateAnimationState();
|
this.updateAnimationState();
|
||||||
@@ -228,6 +257,10 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void tickPlayerPetrification() {
|
private void tickPlayerPetrification() {
|
||||||
|
if (this.isCommittedAttackActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.hissChargeTimer > 0) {
|
if (this.hissChargeTimer > 0) {
|
||||||
Player target = this.getPendingPlayerTarget();
|
Player target = this.getPendingPlayerTarget();
|
||||||
if (!this.canMaintainGazeOn(target)) {
|
if (!this.canMaintainGazeOn(target)) {
|
||||||
@@ -236,7 +269,7 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getNavigation().stop();
|
this.stopActiveMovement();
|
||||||
this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
||||||
this.hissChargeTimer--;
|
this.hissChargeTimer--;
|
||||||
if (this.hissChargeTimer == 0) {
|
if (this.hissChargeTimer == 0) {
|
||||||
@@ -274,7 +307,7 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
this.pendingTargetId = target.getUUID();
|
this.pendingTargetId = target.getUUID();
|
||||||
this.hissChargeTimer = AntarchySettings.basiliskHissChargeTicks();
|
this.hissChargeTimer = AntarchySettings.basiliskHissChargeTicks();
|
||||||
this.hissCooldown = AntarchySettings.basiliskHissCooldownTicks();
|
this.hissCooldown = AntarchySettings.basiliskHissCooldownTicks();
|
||||||
this.getNavigation().stop();
|
this.stopActiveMovement();
|
||||||
this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +317,7 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getTarget() != null || this.hissChargeTimer > 0) {
|
if (this.getTarget() != null || this.hissChargeTimer > 0 || this.isCommittedAttackActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,17 +480,34 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
public void die(DamageSource damageSource) {
|
public void die(DamageSource damageSource) {
|
||||||
if (!this.level().isClientSide) {
|
if (!this.level().isClientSide) {
|
||||||
this.setAnimationState(ANIM_DEATH);
|
this.setAnimationState(ANIM_DEATH);
|
||||||
this.attackAnimTicks = 0;
|
this.resetTransientCombatState();
|
||||||
this.attackDamagePending = false;
|
this.hissCooldown = AntarchySettings.basiliskHissCooldownTicks();
|
||||||
this.attackCooldown = 0;
|
this.preyPetrifyCooldown = AntarchySettings.basiliskPreyPetrifyCooldownTicks();
|
||||||
this.hissChargeTimer = 0;
|
|
||||||
this.pendingTargetId = null;
|
|
||||||
this.getNavigation().stop();
|
|
||||||
this.setDeltaMovement(Vec3.ZERO);
|
this.setDeltaMovement(Vec3.ZERO);
|
||||||
}
|
}
|
||||||
super.die(damageSource);
|
super.die(damageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAdditionalSaveData(CompoundTag tag) {
|
||||||
|
super.addAdditionalSaveData(tag);
|
||||||
|
tag.putInt(TAG_HISS_COOLDOWN, this.hissCooldown);
|
||||||
|
tag.putInt(TAG_PREY_PETRIFY_COOLDOWN, this.preyPetrifyCooldown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readAdditionalSaveData(CompoundTag tag) {
|
||||||
|
super.readAdditionalSaveData(tag);
|
||||||
|
this.hissCooldown = tag.contains(TAG_HISS_COOLDOWN)
|
||||||
|
? Math.max(0, tag.getInt(TAG_HISS_COOLDOWN))
|
||||||
|
: AntarchySettings.basiliskHissCooldownTicks();
|
||||||
|
this.preyPetrifyCooldown = tag.contains(TAG_PREY_PETRIFY_COOLDOWN)
|
||||||
|
? Math.max(0, tag.getInt(TAG_PREY_PETRIFY_COOLDOWN))
|
||||||
|
: AntarchySettings.basiliskPreyPetrifyCooldownTicks();
|
||||||
|
this.resetTransientCombatState();
|
||||||
|
this.setAnimationState(ANIM_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tickDeath() {
|
protected void tickDeath() {
|
||||||
this.deathTime++;
|
this.deathTime++;
|
||||||
@@ -555,7 +605,54 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
return 0.7F;
|
return 0.7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Limits body rotation to TURN_RATE_DEG_PER_TICK so the long snake turns gradually. */
|
private boolean isCommittedAttackActive() {
|
||||||
|
return this.attackAnimTicks > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBusyWithAction() {
|
||||||
|
return this.hissChargeTimer > 0 || this.isCommittedAttackActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
private float resolveCommittedAttackYaw() {
|
||||||
|
LivingEntity target = this.getTarget();
|
||||||
|
if (target != null) {
|
||||||
|
Vec3 toTarget = target.position().subtract(this.position());
|
||||||
|
if (toTarget.horizontalDistanceSqr() > 1.0E-6D) {
|
||||||
|
return (float)(Mth.atan2(toTarget.z, toTarget.x) * (180.0D / Math.PI)) - 90.0F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.yBodyRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lockBodyYaw(float yaw) {
|
||||||
|
this.setYRot(yaw);
|
||||||
|
this.yRotO = yaw;
|
||||||
|
this.yBodyRot = yaw;
|
||||||
|
this.yBodyRotO = yaw;
|
||||||
|
this.yHeadRot = yaw;
|
||||||
|
this.yHeadRotO = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopActiveMovement() {
|
||||||
|
this.getNavigation().stop();
|
||||||
|
if (this.getMoveControl() instanceof BasiliskMoveControl moveControl) {
|
||||||
|
moveControl.halt();
|
||||||
|
}
|
||||||
|
this.setSpeed(0.0F);
|
||||||
|
this.setZza(0.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetTransientCombatState() {
|
||||||
|
this.attackAnimTicks = 0;
|
||||||
|
this.attackDamagePending = false;
|
||||||
|
this.attackCooldown = 0;
|
||||||
|
this.committedAttackYaw = Float.NaN;
|
||||||
|
this.hissChargeTimer = 0;
|
||||||
|
this.pendingTargetId = null;
|
||||||
|
this.stopActiveMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Scales turn rate by intended movement speed so the long body pivots tighter when slow and wider when fast. */
|
||||||
private static final class BasiliskMoveControl extends MoveControl {
|
private static final class BasiliskMoveControl extends MoveControl {
|
||||||
private BasiliskMoveControl(Mob mob) {
|
private BasiliskMoveControl(Mob mob) {
|
||||||
super(mob);
|
super(mob);
|
||||||
@@ -568,6 +665,10 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (((BasiliskEntity) this.mob).isBusyWithAction()) {
|
||||||
|
this.mob.setZza(0.0F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.operation == MoveControl.Operation.MOVE_TO) {
|
if (this.operation == MoveControl.Operation.MOVE_TO) {
|
||||||
this.operation = MoveControl.Operation.WAIT;
|
this.operation = MoveControl.Operation.WAIT;
|
||||||
double dx = this.wantedX - this.mob.getX();
|
double dx = this.wantedX - this.mob.getX();
|
||||||
@@ -577,12 +678,20 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
this.mob.setZza(0.0F);
|
this.mob.setZza(0.0F);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
float turnRate = this.getDynamicTurnRate();
|
||||||
float targetYaw = (float)(Mth.atan2(dz, dx) * (180.0 / Math.PI)) - 90.0F;
|
float targetYaw = (float)(Mth.atan2(dz, dx) * (180.0 / Math.PI)) - 90.0F;
|
||||||
this.mob.setYRot(this.rotlerp(this.mob.getYRot(), targetYaw, TURN_RATE_DEG_PER_TICK));
|
this.mob.setYRot(this.rotlerp(this.mob.getYRot(), targetYaw, turnRate));
|
||||||
this.mob.setSpeed((float)(this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED)));
|
this.mob.setSpeed((float)(this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED)));
|
||||||
this.mob.setZza(1.0F);
|
this.mob.setZza(1.0F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float getDynamicTurnRate() {
|
||||||
|
double baseSpeed = Math.max(0.01D, this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
||||||
|
double intendedSpeed = Math.max(0.0D, this.speedModifier * baseSpeed);
|
||||||
|
double normalizedSpeed = Mth.clamp(intendedSpeed / (baseSpeed * 1.2D), 0.0D, 1.0D);
|
||||||
|
return Mth.lerp((float) normalizedSpeed, MAX_TURN_RATE_DEG_PER_TICK, MIN_TURN_RATE_DEG_PER_TICK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class PersistentNearestAttackableTargetGoal<T extends LivingEntity> extends NearestAttackableTargetGoal<T> {
|
private final class PersistentNearestAttackableTargetGoal<T extends LivingEntity> extends NearestAttackableTargetGoal<T> {
|
||||||
@@ -599,6 +708,11 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (BasiliskEntity.this.hissChargeTimer > 0 || BasiliskEntity.this.attackAnimTicks > 0) {
|
||||||
|
this.stopMovement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LivingEntity target = BasiliskEntity.this.getTarget();
|
LivingEntity target = BasiliskEntity.this.getTarget();
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
BasiliskEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
BasiliskEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
||||||
@@ -607,11 +721,6 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
// super handles path recalc and cooldown timer
|
// super handles path recalc and cooldown timer
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (BasiliskEntity.this.hissChargeTimer > 0 || BasiliskEntity.this.attackAnimTicks > 0) {
|
|
||||||
this.stopMovement();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target != null && BasiliskEntity.this.isWithinMeleeAttackRange(target)) {
|
if (target != null && BasiliskEntity.this.isWithinMeleeAttackRange(target)) {
|
||||||
this.stopMovement();
|
this.stopMovement();
|
||||||
this.checkAndPerformAttack(target);
|
this.checkAndPerformAttack(target);
|
||||||
@@ -619,14 +728,14 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void stopMovement() {
|
private void stopMovement() {
|
||||||
BasiliskEntity.this.getNavigation().stop();
|
BasiliskEntity.this.stopActiveMovement();
|
||||||
((BasiliskMoveControl) BasiliskEntity.this.getMoveControl()).halt();
|
|
||||||
BasiliskEntity.this.setSpeed(0.0F);
|
|
||||||
BasiliskEntity.this.setZza(0.0F);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUse() {
|
public boolean canUse() {
|
||||||
|
if (BasiliskEntity.this.isBusyWithAction()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
LivingEntity target = BasiliskEntity.this.getTarget();
|
LivingEntity target = BasiliskEntity.this.getTarget();
|
||||||
if (target == null || !target.isAlive()) return false;
|
if (target == null || !target.isAlive()) return false;
|
||||||
if (target instanceof Player p && (p.isCreative() || p.isSpectator())) return false;
|
if (target instanceof Player p && (p.isCreative() || p.isSpectator())) return false;
|
||||||
@@ -636,7 +745,7 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
LivingEntity target = BasiliskEntity.this.getTarget();
|
LivingEntity target = BasiliskEntity.this.getTarget();
|
||||||
if (target != null) {
|
if (target != null && !BasiliskEntity.this.isBusyWithAction()) {
|
||||||
BasiliskEntity.this.getNavigation().moveTo(target, 1.2D);
|
BasiliskEntity.this.getNavigation().moveTo(target, 1.2D);
|
||||||
}
|
}
|
||||||
BasiliskEntity.this.setAggressive(true);
|
BasiliskEntity.this.setAggressive(true);
|
||||||
@@ -644,7 +753,14 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canContinueToUse() {
|
public boolean canContinueToUse() {
|
||||||
return BasiliskEntity.this.attackAnimTicks > 0 || super.canContinueToUse();
|
return BasiliskEntity.this.isBusyWithAction() || super.canContinueToUse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
super.stop();
|
||||||
|
BasiliskEntity.this.setAggressive(false);
|
||||||
|
this.stopMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+6
@@ -111,6 +111,12 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.KNOCKBACK_RESISTANCE, AntarchySettings.cloudSharkKnockbackResistance());
|
.add(Attributes.KNOCKBACK_RESISTANCE, AntarchySettings.cloudSharkKnockbackResistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.cloudSharkHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<CloudSharkEntity> entityType, ServerLevelAccessor level,
|
public static boolean canSpawn(EntityType<CloudSharkEntity> entityType, ServerLevelAccessor level,
|
||||||
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
return level.getDifficulty() != Difficulty.PEACEFUL
|
return level.getDifficulty() != Difficulty.PEACEFUL
|
||||||
|
|||||||
+51
-6
@@ -6,6 +6,7 @@ import com.craisinlord.antarchy.content.AntarchyTags;
|
|||||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||||
import com.craisinlord.antarchy.content.block.OuranwoodAcornBlock;
|
import com.craisinlord.antarchy.content.block.OuranwoodAcornBlock;
|
||||||
import com.craisinlord.antarchy.content.block.OuranwoodLeavesBlock;
|
import com.craisinlord.antarchy.content.block.OuranwoodLeavesBlock;
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.particles.ItemParticleOption;
|
import net.minecraft.core.particles.ItemParticleOption;
|
||||||
@@ -54,12 +55,14 @@ import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
|||||||
import software.bernie.geckolib.animation.*;
|
import software.bernie.geckolib.animation.*;
|
||||||
import software.bernie.geckolib.animation.AnimationState;
|
import software.bernie.geckolib.animation.AnimationState;
|
||||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
private static final ResourceKey<Level> ELYTHIA_DIMENSION = ResourceKey.create(
|
private static final ResourceKey<Level> ELYTHIA_DIMENSION = ResourceKey.create(
|
||||||
Registries.DIMENSION,
|
Registries.DIMENSION,
|
||||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia")
|
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia")
|
||||||
@@ -81,6 +84,8 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
SynchedEntityData.defineId(FlyingSquirrelEntity.class, EntityDataSerializers.OPTIONAL_UUID);
|
SynchedEntityData.defineId(FlyingSquirrelEntity.class, EntityDataSerializers.OPTIONAL_UUID);
|
||||||
|
|
||||||
private static final String PICKUP_ANIM_TICKS_KEY = "PickupAnimTicks";
|
private static final String PICKUP_ANIM_TICKS_KEY = "PickupAnimTicks";
|
||||||
|
private static final String QUIRK_TICKS_KEY = "QuirkTicks";
|
||||||
|
private static final String QUIRK_VARIANT_KEY = "QuirkVariant";
|
||||||
private static final String TEXTURE_VARIANT_KEY = "TextureVariant";
|
private static final String TEXTURE_VARIANT_KEY = "TextureVariant";
|
||||||
private static final String GLIDE_DIR_X_KEY = "GlideDirX";
|
private static final String GLIDE_DIR_X_KEY = "GlideDirX";
|
||||||
private static final String GLIDE_DIR_Y_KEY = "GlideDirY";
|
private static final String GLIDE_DIR_Y_KEY = "GlideDirY";
|
||||||
@@ -129,6 +134,9 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
private static final RawAnimation CLIMB_ANIM = RawAnimation.begin().thenLoop("climbing");
|
private static final RawAnimation CLIMB_ANIM = RawAnimation.begin().thenLoop("climbing");
|
||||||
private static final RawAnimation GLIDE_ANIM = RawAnimation.begin().thenLoop("gliding");
|
private static final RawAnimation GLIDE_ANIM = RawAnimation.begin().thenLoop("gliding");
|
||||||
private static final RawAnimation PICKUP_ANIM = RawAnimation.begin().thenPlay("item_pickup");
|
private static final RawAnimation PICKUP_ANIM = RawAnimation.begin().thenPlay("item_pickup");
|
||||||
|
private static final String QUIRK_CONTROLLER = "quirk_controller";
|
||||||
|
private static final String QUIRK_1_TRIGGER = "quirk1";
|
||||||
|
private static final String QUIRK_2_TRIGGER = "quirk2";
|
||||||
private static final RawAnimation QUIRK_1_ANIM = RawAnimation.begin().thenPlay("quirk1");
|
private static final RawAnimation QUIRK_1_ANIM = RawAnimation.begin().thenPlay("quirk1");
|
||||||
private static final RawAnimation QUIRK_2_ANIM = RawAnimation.begin().thenPlay("quirk2");
|
private static final RawAnimation QUIRK_2_ANIM = RawAnimation.begin().thenPlay("quirk2");
|
||||||
|
|
||||||
@@ -178,11 +186,13 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
private ItemEntity cachedNutItem;
|
private ItemEntity cachedNutItem;
|
||||||
@Nullable
|
@Nullable
|
||||||
private BlockPos cachedHarvestableAcorn;
|
private BlockPos cachedHarvestableAcorn;
|
||||||
private int quirkCooldownTicks = MIN_QUIRK_COOLDOWN_TICKS;
|
private int quirkCooldownTicks;
|
||||||
|
private int lastTriggeredQuirkVariant = QUIRK_NONE;
|
||||||
|
|
||||||
public FlyingSquirrelEntity(EntityType<? extends FlyingSquirrelEntity> entityType, Level level) {
|
public FlyingSquirrelEntity(EntityType<? extends FlyingSquirrelEntity> entityType, Level level) {
|
||||||
super(entityType, level);
|
super(entityType, level);
|
||||||
this.setPathfindingMalus(PathType.LEAVES, -2.0F);
|
this.setPathfindingMalus(PathType.LEAVES, -2.0F);
|
||||||
|
this.quirkCooldownTicks = this.nextQuirkCooldown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -253,9 +263,16 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
@Override
|
@Override
|
||||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||||
controllers.add(new AnimationController<>(this, "main_controller", 5, this::mainAnimController));
|
controllers.add(new AnimationController<>(this, "main_controller", 5, this::mainAnimController));
|
||||||
|
controllers.add(new AnimationController<>(this, QUIRK_CONTROLLER, 0, state -> PlayState.STOP)
|
||||||
|
.triggerableAnim(QUIRK_1_TRIGGER, QUIRK_1_ANIM)
|
||||||
|
.triggerableAnim(QUIRK_2_TRIGGER, QUIRK_2_ANIM));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayState mainAnimController(AnimationState<FlyingSquirrelEntity> state) {
|
private PlayState mainAnimController(AnimationState<FlyingSquirrelEntity> state) {
|
||||||
|
if (this.hasActiveQuirkAnimation()) {
|
||||||
|
return PlayState.STOP;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isPickingUpNut()) {
|
if (this.isPickingUpNut()) {
|
||||||
return state.setAndContinue(PICKUP_ANIM);
|
return state.setAndContinue(PICKUP_ANIM);
|
||||||
}
|
}
|
||||||
@@ -273,11 +290,6 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
return state.setAndContinue(CLIMB_ANIM);
|
return state.setAndContinue(CLIMB_ANIM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getQuirkTicks() > 0) {
|
|
||||||
state.getController().setAnimationSpeed(1.0D);
|
|
||||||
return state.setAndContinue(this.getQuirkVariant() == QUIRK_2 ? QUIRK_2_ANIM : QUIRK_1_ANIM);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 motion = this.getDeltaMovement();
|
Vec3 motion = this.getDeltaMovement();
|
||||||
double horizontalSpeed = motion.horizontalDistanceSqr();
|
double horizontalSpeed = motion.horizontalDistanceSqr();
|
||||||
if (!this.isGliding() && !this.isClimbingTrunk() && motion.horizontalDistanceSqr() > 1.0E-4D) {
|
if (!this.isGliding() && !this.isClimbingTrunk() && motion.horizontalDistanceSqr() > 1.0E-4D) {
|
||||||
@@ -303,6 +315,8 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
public void addAdditionalSaveData(CompoundTag tag) {
|
public void addAdditionalSaveData(CompoundTag tag) {
|
||||||
super.addAdditionalSaveData(tag);
|
super.addAdditionalSaveData(tag);
|
||||||
tag.putInt(PICKUP_ANIM_TICKS_KEY, this.pickupAnimTicks);
|
tag.putInt(PICKUP_ANIM_TICKS_KEY, this.pickupAnimTicks);
|
||||||
|
tag.putInt(QUIRK_TICKS_KEY, this.getQuirkTicks());
|
||||||
|
tag.putInt(QUIRK_VARIANT_KEY, this.getQuirkVariant());
|
||||||
tag.putInt(TEXTURE_VARIANT_KEY, this.getTextureVariant());
|
tag.putInt(TEXTURE_VARIANT_KEY, this.getTextureVariant());
|
||||||
if (this.glideDirection != null) {
|
if (this.glideDirection != null) {
|
||||||
tag.putDouble(GLIDE_DIR_X_KEY, this.glideDirection.x);
|
tag.putDouble(GLIDE_DIR_X_KEY, this.glideDirection.x);
|
||||||
@@ -316,6 +330,8 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
super.readAdditionalSaveData(tag);
|
super.readAdditionalSaveData(tag);
|
||||||
this.pickupAnimTicks = Math.max(0, tag.getInt(PICKUP_ANIM_TICKS_KEY));
|
this.pickupAnimTicks = Math.max(0, tag.getInt(PICKUP_ANIM_TICKS_KEY));
|
||||||
this.setPickingUpNut(this.pickupAnimTicks > 0);
|
this.setPickingUpNut(this.pickupAnimTicks > 0);
|
||||||
|
this.setQuirkTicks(Math.max(0, tag.getInt(QUIRK_TICKS_KEY)));
|
||||||
|
this.setQuirkVariant(tag.contains(QUIRK_VARIANT_KEY) ? tag.getInt(QUIRK_VARIANT_KEY) : QUIRK_NONE);
|
||||||
if (tag.contains(TEXTURE_VARIANT_KEY)) {
|
if (tag.contains(TEXTURE_VARIANT_KEY)) {
|
||||||
this.setTextureVariant(tag.getInt(TEXTURE_VARIANT_KEY));
|
this.setTextureVariant(tag.getInt(TEXTURE_VARIANT_KEY));
|
||||||
} else {
|
} else {
|
||||||
@@ -388,6 +404,7 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
if (!this.level().isClientSide) {
|
if (!this.level().isClientSide) {
|
||||||
this.tickPickupAnimation();
|
this.tickPickupAnimation();
|
||||||
this.tickQuirkAnimation();
|
this.tickQuirkAnimation();
|
||||||
|
this.syncQuirkAnimationTrigger();
|
||||||
|
|
||||||
if (this.isClimbingToShoulder()) {
|
if (this.isClimbingToShoulder()) {
|
||||||
Player shoulderPlayer = this.shoulderPlayerId != null
|
Player shoulderPlayer = this.shoulderPlayerId != null
|
||||||
@@ -467,6 +484,9 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
|
|
||||||
this.tickIdleStallLogging(horizontalSpeed);
|
this.tickIdleStallLogging(horizontalSpeed);
|
||||||
}
|
}
|
||||||
|
if (this.level().isClientSide) {
|
||||||
|
this.syncQuirkAnimationTrigger();
|
||||||
|
}
|
||||||
if (this.isOnShoulder() && this.level().isClientSide) {
|
if (this.isOnShoulder() && this.level().isClientSide) {
|
||||||
Player shoulderPlayer = this.getShoulderPlayer();
|
Player shoulderPlayer = this.getShoulderPlayer();
|
||||||
if (shoulderPlayer != null) {
|
if (shoulderPlayer != null) {
|
||||||
@@ -647,6 +667,7 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
||||||
SpawnGroupData finalized = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
SpawnGroupData finalized = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
||||||
|
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.flyingSquirrelHealth());
|
||||||
this.assignRandomTextureVariant();
|
this.assignRandomTextureVariant();
|
||||||
this.stopGliding("spawn_initialized");
|
this.stopGliding("spawn_initialized");
|
||||||
this.wanderCooldown = 40 + this.random.nextInt(60);
|
this.wanderCooldown = 40 + this.random.nextInt(60);
|
||||||
@@ -791,14 +812,38 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
|
|||||||
int variant = this.random.nextBoolean() ? QUIRK_1 : QUIRK_2;
|
int variant = this.random.nextBoolean() ? QUIRK_1 : QUIRK_2;
|
||||||
this.setQuirkVariant(variant);
|
this.setQuirkVariant(variant);
|
||||||
this.setQuirkTicks(variant == QUIRK_1 ? QUIRK_1_DURATION_TICKS : QUIRK_2_DURATION_TICKS);
|
this.setQuirkTicks(variant == QUIRK_1 ? QUIRK_1_DURATION_TICKS : QUIRK_2_DURATION_TICKS);
|
||||||
|
LOGGER.info("FlyingSquirrel animation selected={} tick={}", variant == QUIRK_2 ? QUIRK_2_TRIGGER : QUIRK_1_TRIGGER, this.tickCount);
|
||||||
this.quirkCooldownTicks = this.nextQuirkCooldown();
|
this.quirkCooldownTicks = this.nextQuirkCooldown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopQuirkAnimation() {
|
private void stopQuirkAnimation() {
|
||||||
|
if (this.getQuirkVariant() != QUIRK_NONE || this.getQuirkTicks() > 0) {
|
||||||
|
LOGGER.info("FlyingSquirrel animation state cleared variant={} tick={}", this.getQuirkVariant(), this.tickCount);
|
||||||
|
}
|
||||||
this.setQuirkTicks(0);
|
this.setQuirkTicks(0);
|
||||||
this.setQuirkVariant(QUIRK_NONE);
|
this.setQuirkVariant(QUIRK_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncQuirkAnimationTrigger() {
|
||||||
|
int quirkVariant = this.getQuirkVariant();
|
||||||
|
if (quirkVariant != QUIRK_NONE && this.getQuirkTicks() > 0 && this.lastTriggeredQuirkVariant != quirkVariant) {
|
||||||
|
String triggerName = quirkVariant == QUIRK_2 ? QUIRK_2_TRIGGER : QUIRK_1_TRIGGER;
|
||||||
|
if (!this.level().isClientSide) {
|
||||||
|
LOGGER.info("FlyingSquirrel triggerAnim called={} tick={}", triggerName, this.tickCount);
|
||||||
|
}
|
||||||
|
this.triggerAnim(QUIRK_CONTROLLER, triggerName);
|
||||||
|
this.lastTriggeredQuirkVariant = quirkVariant;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (quirkVariant == QUIRK_NONE) {
|
||||||
|
this.lastTriggeredQuirkVariant = QUIRK_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasActiveQuirkAnimation() {
|
||||||
|
return this.getQuirkVariant() != QUIRK_NONE && this.getQuirkTicks() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
private int nextQuirkCooldown() {
|
private int nextQuirkCooldown() {
|
||||||
return MIN_QUIRK_COOLDOWN_TICKS + this.random.nextInt(MAX_QUIRK_COOLDOWN_TICKS - MIN_QUIRK_COOLDOWN_TICKS + 1);
|
return MIN_QUIRK_COOLDOWN_TICKS + this.random.nextInt(MAX_QUIRK_COOLDOWN_TICKS - MIN_QUIRK_COOLDOWN_TICKS + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -4,6 +4,7 @@ import com.craisinlord.antarchy.config.AntarchySettings;
|
|||||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||||
import com.craisinlord.antarchy.content.advancement.AntarchyAdvancements;
|
import com.craisinlord.antarchy.content.advancement.AntarchyAdvancements;
|
||||||
import com.craisinlord.antarchy.content.client.particle.GlimmerParticles;
|
import com.craisinlord.antarchy.content.client.particle.GlimmerParticles;
|
||||||
|
import com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil;
|
||||||
import com.craisinlord.antarchy.Antarchy;
|
import com.craisinlord.antarchy.Antarchy;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
@@ -133,6 +134,7 @@ public class GlimmerEntity extends TamableAnimal implements GeoEntity {
|
|||||||
public static AttributeSupplier.Builder createAttributes() {
|
public static AttributeSupplier.Builder createAttributes() {
|
||||||
return TamableAnimal.createMobAttributes()
|
return TamableAnimal.createMobAttributes()
|
||||||
.add(Attributes.MAX_HEALTH, AntarchySettings.glimmerHealth())
|
.add(Attributes.MAX_HEALTH, AntarchySettings.glimmerHealth())
|
||||||
|
.add(Attributes.ATTACK_DAMAGE, 1.0D)
|
||||||
.add(Attributes.MOVEMENT_SPEED, 0.3D)
|
.add(Attributes.MOVEMENT_SPEED, 0.3D)
|
||||||
.add(Attributes.FOLLOW_RANGE, 24.0D);
|
.add(Attributes.FOLLOW_RANGE, 24.0D);
|
||||||
}
|
}
|
||||||
@@ -443,7 +445,8 @@ public class GlimmerEntity extends TamableAnimal implements GeoEntity {
|
|||||||
return InteractionResult.CONSUME;
|
return InteractionResult.CONSUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack filled = com.craisinlord.antarchy.content.item.GlimmerBottleItem.create(this.getVariant(), this.entityData.get(ABILITY_COOLDOWN));
|
ItemStack filled = com.craisinlord.antarchy.content.item.GlimmerBottleItem.create(
|
||||||
|
this.getVariant(), this.entityData.get(ABILITY_COOLDOWN), this.entityData.get(SHEAR_COOLDOWN));
|
||||||
ItemStack result = net.minecraft.world.item.ItemUtils.createFilledResult(stack, player, filled);
|
ItemStack result = net.minecraft.world.item.ItemUtils.createFilledResult(stack, player, filled);
|
||||||
player.setItemInHand(hand, result);
|
player.setItemInHand(hand, result);
|
||||||
this.playSound(net.minecraft.sounds.SoundEvents.BOTTLE_FILL, 1.0F, 1.0F);
|
this.playSound(net.minecraft.sounds.SoundEvents.BOTTLE_FILL, 1.0F, 1.0F);
|
||||||
@@ -460,6 +463,7 @@ public class GlimmerEntity extends TamableAnimal implements GeoEntity {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData spawnGroupData) {
|
||||||
SpawnGroupData result = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
SpawnGroupData result = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
||||||
|
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.glimmerHealth());
|
||||||
if (!this.variantLocked) {
|
if (!this.variantLocked) {
|
||||||
this.setVariant(selectNaturalVariant(level, this.blockPosition()));
|
this.setVariant(selectNaturalVariant(level, this.blockPosition()));
|
||||||
this.variantLocked = true;
|
this.variantLocked = true;
|
||||||
|
|||||||
+2
-1
@@ -31,6 +31,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class TentacleEntity extends Mob implements GeoEntity {
|
public class TentacleEntity extends Mob implements GeoEntity {
|
||||||
private static final RawAnimation GRASP_ANIM = RawAnimation.begin().thenLoop("animation");
|
private static final RawAnimation GRASP_ANIM = RawAnimation.begin().thenLoop("animation");
|
||||||
|
private static final float SPAWN_SOUND_VOLUME = 0.35F;
|
||||||
|
|
||||||
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||||
private int lifetimeTicks;
|
private int lifetimeTicks;
|
||||||
@@ -82,7 +83,7 @@ public class TentacleEntity extends Mob implements GeoEntity {
|
|||||||
tentacle.ownerId = owner.getUUID();
|
tentacle.ownerId = owner.getUUID();
|
||||||
}
|
}
|
||||||
level.addFreshEntity(tentacle);
|
level.addFreshEntity(tentacle);
|
||||||
level.playSound(null, pos.x, pos.y, pos.z, AntarchySoundEvents.KRAKEN_ATTACK.get(), SoundSource.HOSTILE, 1.0F, 1.0F);
|
level.playSound(null, pos.x, pos.y, pos.z, AntarchySoundEvents.KRAKEN_ATTACK.get(), SoundSource.HOSTILE, SPAWN_SOUND_VOLUME, 1.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+7
-1
@@ -104,6 +104,13 @@ public class LucidEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.KNOCKBACK_RESISTANCE, AntarchySettings.lucidKnockbackResistance());
|
.add(Attributes.KNOCKBACK_RESISTANCE, AntarchySettings.lucidKnockbackResistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.lucidHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<LucidEntity> entityType, ServerLevelAccessor level,
|
public static boolean canSpawn(EntityType<LucidEntity> entityType, ServerLevelAccessor level,
|
||||||
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
return level.getDifficulty() != Difficulty.PEACEFUL
|
return level.getDifficulty() != Difficulty.PEACEFUL
|
||||||
@@ -552,4 +559,3 @@ public class LucidEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
package com.craisinlord.antarchy.content.entity.nightmare;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||||
|
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.world.damagesource.DamageSource;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.EntityType;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class NightmareBiteEntity extends Entity implements GeoEntity {
|
||||||
|
private static final EntityDataAccessor<Boolean> PHASE_TWO = SynchedEntityData.defineId(NightmareBiteEntity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
private static final RawAnimation BITE_ANIM = RawAnimation.begin().thenPlay("bite");
|
||||||
|
|
||||||
|
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||||
|
private int ageTicks;
|
||||||
|
|
||||||
|
public NightmareBiteEntity(EntityType<? extends NightmareBiteEntity> entityType, Level level) {
|
||||||
|
super(entityType, level);
|
||||||
|
this.setInvulnerable(true);
|
||||||
|
this.noPhysics = true;
|
||||||
|
this.noCulling = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NightmareBiteEntity spawnAt(ServerLevel level, Vec3 pos, float yaw, boolean phaseTwo) {
|
||||||
|
NightmareBiteEntity bite = new NightmareBiteEntity(AntarchyObjects.NIGHTMARE_BITE.get(), level);
|
||||||
|
bite.moveTo(pos.x, pos.y, pos.z, yaw, 0.0F);
|
||||||
|
bite.setPhaseTwo(phaseTwo);
|
||||||
|
level.addFreshEntity(bite);
|
||||||
|
return bite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
|
builder.define(PHASE_TWO, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvulnerableTo(DamageSource damageSource) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fireImmune() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lavaHurt() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPushable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeCollidedWith() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPickable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPhaseTwo() {
|
||||||
|
return this.entityData.get(PHASE_TWO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPhaseTwo(boolean phaseTwo) {
|
||||||
|
this.getEntityData().set(PHASE_TWO, phaseTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
if (this.level().isClientSide) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (++this.ageTicks >= 12) {
|
||||||
|
this.discard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAdditionalSaveData(CompoundTag tag) {
|
||||||
|
tag.putBoolean("PhaseTwo", this.isPhaseTwo());
|
||||||
|
tag.putInt("AgeTicks", this.ageTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readAdditionalSaveData(CompoundTag tag) {
|
||||||
|
this.setPhaseTwo(tag.getBoolean("PhaseTwo"));
|
||||||
|
this.ageTicks = tag.getInt("AgeTicks");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||||
|
controllers.add(new AnimationController<>(this, "bite_controller", 0, this::biteController));
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayState biteController(AnimationState<NightmareBiteEntity> state) {
|
||||||
|
return state.setAndContinue(BITE_ANIM);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||||
|
return this.geoCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
+613
-63
@@ -5,7 +5,7 @@ import com.craisinlord.antarchy.content.AntarchyObjects;
|
|||||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||||
import com.craisinlord.antarchy.content.AntarchyTags;
|
import com.craisinlord.antarchy.content.AntarchyTags;
|
||||||
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
|
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.particles.ParticleTypes;
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
@@ -22,6 +22,7 @@ import net.minecraft.world.damagesource.DamageSource;
|
|||||||
import net.minecraft.world.effect.MobEffectInstance;
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.world.effect.MobEffects;
|
import net.minecraft.world.effect.MobEffects;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.EntityDimensions;
|
||||||
import net.minecraft.world.entity.EntityType;
|
import net.minecraft.world.entity.EntityType;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.entity.Mob;
|
import net.minecraft.world.entity.Mob;
|
||||||
@@ -53,14 +54,19 @@ import software.bernie.geckolib.animation.AnimationState;
|
|||||||
import software.bernie.geckolib.animation.PlayState;
|
import software.bernie.geckolib.animation.PlayState;
|
||||||
import software.bernie.geckolib.animation.RawAnimation;
|
import software.bernie.geckolib.animation.RawAnimation;
|
||||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NightmareEntity extends Monster implements GeoEntity {
|
public class NightmareEntity extends Monster implements GeoEntity {
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
private static final EntityDataAccessor<Integer> ANIMATION_STATE = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.INT);
|
private static final EntityDataAccessor<Integer> ANIMATION_STATE = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.INT);
|
||||||
|
private static final EntityDataAccessor<Integer> ACTIVE_SPECIAL_ANIMATION = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.INT);
|
||||||
private static final EntityDataAccessor<Boolean> ROARING = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.BOOLEAN);
|
private static final EntityDataAccessor<Boolean> ROARING = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
private static final EntityDataAccessor<Boolean> PHASE_TWO = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
private static final EntityDataAccessor<Boolean> PHASE_TWO_TEXTURE = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
private static final EntityDataAccessor<Boolean> PHASE_TRANSITIONING = SynchedEntityData.defineId(NightmareEntity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
|
||||||
private static final String ATTACK_COOLDOWN_KEY = "AttackCooldown";
|
private static final String ATTACK_COOLDOWN_KEY = "AttackCooldown";
|
||||||
private static final String ATTACK_ANIMATION_TICKS_KEY = "AttackAnimationTicks";
|
private static final String ATTACK_ANIMATION_TICKS_KEY = "AttackAnimationTicks";
|
||||||
@@ -70,13 +76,33 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
private static final String INTRO_ROAR_USED_KEY = "IntroRoarUsed";
|
private static final String INTRO_ROAR_USED_KEY = "IntroRoarUsed";
|
||||||
private static final String TARGETLESS_TICKS_KEY = "TargetlessTicks";
|
private static final String TARGETLESS_TICKS_KEY = "TargetlessTicks";
|
||||||
private static final String ANIMATION_STATE_KEY = "AnimationState";
|
private static final String ANIMATION_STATE_KEY = "AnimationState";
|
||||||
|
private static final String ACTIVE_SPECIAL_ANIMATION_KEY = "ActiveSpecialAnimation";
|
||||||
|
private static final String PHASE_TWO_KEY = "PhaseTwo";
|
||||||
|
private static final String PHASE_TWO_TEXTURE_KEY = "PhaseTwoTexture";
|
||||||
|
private static final String PHASE_TRANSITIONING_KEY = "PhaseTransitioning";
|
||||||
|
private static final String PHASE_TRANSITION_TICKS_KEY = "PhaseTransitionTicks";
|
||||||
|
private static final String PORTAL_COOLDOWN_KEY = "PortalCooldown";
|
||||||
|
private static final String PORTAL_ATTACK_TICKS_KEY = "PortalAttackTicks";
|
||||||
|
private static final String PORTAL_ATTACK_HIT_KEY = "PortalAttackHitApplied";
|
||||||
|
private static final String PORTAL_TRAVEL_TICKS_KEY = "PortalTravelTicks";
|
||||||
|
private static final String PORTAL_ENTRY_ID_KEY = "PortalEntryId";
|
||||||
|
private static final String PORTAL_EXIT_ID_KEY = "PortalExitId";
|
||||||
|
private static final String PORTAL_EXIT_X_KEY = "PortalExitX";
|
||||||
|
private static final String PORTAL_EXIT_Y_KEY = "PortalExitY";
|
||||||
|
private static final String PORTAL_EXIT_Z_KEY = "PortalExitZ";
|
||||||
|
|
||||||
private static final int ANIM_IDLE = 0;
|
private static final int ANIM_IDLE = 0;
|
||||||
private static final int ANIM_WALK = 1;
|
private static final int ANIM_WALK = 1;
|
||||||
private static final int ANIM_FLY = 2;
|
private static final int ANIM_FLY = 2;
|
||||||
private static final int ANIM_ATTACK = 3;
|
private static final int SPECIAL_NONE = 0;
|
||||||
private static final int ANIM_FLY_ATTACK = 4;
|
private static final int SPECIAL_ATTACK = 1;
|
||||||
private static final int ANIM_ROAR = 5;
|
private static final int SPECIAL_ATTACK_P2 = 2;
|
||||||
|
private static final int SPECIAL_FLY_ATTACK = 3;
|
||||||
|
private static final int SPECIAL_FLY_ATTACK_P2 = 4;
|
||||||
|
private static final int SPECIAL_ROAR = 5;
|
||||||
|
private static final int SPECIAL_ROAR_P2 = 6;
|
||||||
|
private static final int SPECIAL_PHASE_TWO = 7;
|
||||||
|
private static final int SPECIAL_PORTAL = 8;
|
||||||
private static final int ATTACK_TOTAL_TICKS = 20;
|
private static final int ATTACK_TOTAL_TICKS = 20;
|
||||||
private static final int ATTACK_DAMAGE_TICK = 10;
|
private static final int ATTACK_DAMAGE_TICK = 10;
|
||||||
private static final int INTRO_ROAR_TICKS = 30;
|
private static final int INTRO_ROAR_TICKS = 30;
|
||||||
@@ -88,6 +114,13 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
private static final int WEAKNESS_TICKS = 100;
|
private static final int WEAKNESS_TICKS = 100;
|
||||||
private static final int BLOCK_BREAK_TICKS = 10;
|
private static final int BLOCK_BREAK_TICKS = 10;
|
||||||
private static final int FLIGHT_CEILING_CLEARANCE_BLOCKS = 4;
|
private static final int FLIGHT_CEILING_CLEARANCE_BLOCKS = 4;
|
||||||
|
private static final int PHASE_TWO_TRANSITION_TICKS = 80;
|
||||||
|
private static final int PHASE_TWO_TEXTURE_SWAP_TICKS = 53;
|
||||||
|
private static final int PORTAL_TOTAL_TICKS = 28;
|
||||||
|
private static final int PORTAL_TELEPORT_TICK = 12;
|
||||||
|
private static final int PORTAL_DAMAGE_TICK = 18;
|
||||||
|
private static final int PORTAL_TRAVEL_INVULNERABLE_TICKS = 8;
|
||||||
|
private static final int PORTAL_LIFETIME_TICKS = 60;
|
||||||
|
|
||||||
private static final double PATROL_SPEED = 0.34D;
|
private static final double PATROL_SPEED = 0.34D;
|
||||||
private static final double COMBAT_FLIGHT_SPEED = 0.725D;
|
private static final double COMBAT_FLIGHT_SPEED = 0.725D;
|
||||||
@@ -95,16 +128,47 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
private static final double ATTACK_START_RANGE_SQR = 42.25D;
|
private static final double ATTACK_START_RANGE_SQR = 42.25D;
|
||||||
private static final double ATTACK_REACH_RADIUS = 2.65D;
|
private static final double ATTACK_REACH_RADIUS = 2.65D;
|
||||||
private static final double ATTACK_COMMIT_HORIZONTAL_RANGE = 4.2D;
|
private static final double ATTACK_COMMIT_HORIZONTAL_RANGE = 4.2D;
|
||||||
private static final double FLIGHT_ENGAGE_RANGE_SQR = 100.0D;
|
private static final double ATTACK_COMMIT_HORIZONTAL_RANGE_SQR = ATTACK_COMMIT_HORIZONTAL_RANGE * ATTACK_COMMIT_HORIZONTAL_RANGE;
|
||||||
private static final double FLIGHT_DISENGAGE_RANGE_SQR = 36.0D;
|
private static final double FLIGHT_ENGAGE_RANGE_SQR = 42.25D;
|
||||||
|
private static final double FLIGHT_DISENGAGE_RANGE_SQR = 20.25D;
|
||||||
|
private static final double FLIGHT_ATTACK_RANGE_SQR = 49.0D;
|
||||||
private static final double ROAR_RETRY_DISTANCE_SQR = 400.0D;
|
private static final double ROAR_RETRY_DISTANCE_SQR = 400.0D;
|
||||||
|
private static final double PHASE_TWO_HEALTH_FRACTION = 0.5D;
|
||||||
|
private static final double PORTAL_RANGE = 32.0D;
|
||||||
|
private static final double PORTAL_MIN_RANGE_SQR = 49.0D;
|
||||||
|
private static final double PORTAL_EXIT_OFFSET = 2.35D;
|
||||||
|
private static final double PORTAL_TRANSPORT_RADIUS = 1.25D;
|
||||||
|
private static final double FLYING_APPROACH_STRAFE_OFFSET = 2.1D;
|
||||||
|
private static final double FLYING_APPROACH_HEIGHT = 0.45D;
|
||||||
|
private static final double FLYING_APPROACH_HEIGHT_PHASE_TWO = 0.8D;
|
||||||
|
private static final double FLYING_APPROACH_TOO_CLOSE_RANGE_SQR = 9.0D;
|
||||||
|
private static final double ANIMATION_MOVEMENT_THRESHOLD_SQR = 0.01D;
|
||||||
|
|
||||||
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
||||||
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
|
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
|
||||||
private static final RawAnimation FLY_ANIM = RawAnimation.begin().thenLoop("fly");
|
private static final RawAnimation FLY_ANIM = RawAnimation.begin().thenLoop("fly");
|
||||||
private static final RawAnimation ATTACK_ANIM = RawAnimation.begin().thenPlay("attack").thenLoop("idle");
|
private static final RawAnimation PHASE_TWO_IDLE_ANIM = RawAnimation.begin().thenLoop("idle_P2");
|
||||||
private static final RawAnimation FLY_ATTACK_ANIM = RawAnimation.begin().thenPlay("attack2").thenLoop("fly");
|
private static final RawAnimation PHASE_TWO_WALK_ANIM = RawAnimation.begin().thenLoop("walk_P2");
|
||||||
private static final RawAnimation ROAR_ANIM = RawAnimation.begin().thenPlay("roar").thenLoop("idle");
|
private static final RawAnimation PHASE_TWO_FLY_ANIM = RawAnimation.begin().thenLoop("fly_P2");
|
||||||
|
private static final String LOCOMOTION_CONTROLLER = "main_controller";
|
||||||
|
private static final String SPECIAL_CONTROLLER = "special_controller";
|
||||||
|
private static final String SPECIAL_ATTACK_TRIGGER = "attack";
|
||||||
|
private static final String SPECIAL_ATTACK_P2_TRIGGER = "attack_P2";
|
||||||
|
private static final String SPECIAL_FLY_ATTACK_TRIGGER = "attack2";
|
||||||
|
private static final String SPECIAL_FLY_ATTACK_P2_TRIGGER = "attack2_P2";
|
||||||
|
private static final String SPECIAL_ROAR_TRIGGER = "roar";
|
||||||
|
private static final String SPECIAL_ROAR_P2_TRIGGER = "roar_P2";
|
||||||
|
private static final String SPECIAL_PHASE_TWO_TRIGGER = "phase2";
|
||||||
|
private static final String SPECIAL_PORTAL_TRIGGER = "portal_out";
|
||||||
|
private static final RawAnimation ATTACK_ANIM = RawAnimation.begin().thenPlayAndHold("attack");
|
||||||
|
private static final RawAnimation ATTACK_P2_ANIM = RawAnimation.begin().thenPlayAndHold("attack_P2");
|
||||||
|
private static final RawAnimation FLY_ATTACK_ANIM = RawAnimation.begin().thenPlayAndHold("attack2");
|
||||||
|
private static final RawAnimation FLY_ATTACK_P2_ANIM = RawAnimation.begin().thenPlayAndHold("attack2_P2");
|
||||||
|
private static final RawAnimation ROAR_ANIM = RawAnimation.begin().thenPlayAndHold("roar");
|
||||||
|
private static final RawAnimation ROAR_P2_ANIM = RawAnimation.begin().thenPlayAndHold("roar_P2");
|
||||||
|
private static final RawAnimation PHASE_TWO_TRANSITION_ANIM = RawAnimation.begin().thenPlayAndHold("phase2");
|
||||||
|
private static final RawAnimation PORTAL_ATTACK_ANIM = RawAnimation.begin().thenPlayAndHold("portal_out");
|
||||||
|
|
||||||
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||||
|
|
||||||
private int attackCooldown;
|
private int attackCooldown;
|
||||||
@@ -117,9 +181,20 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
private int groundMoveTicks;
|
private int groundMoveTicks;
|
||||||
private int wingFlapCooldown;
|
private int wingFlapCooldown;
|
||||||
private int blockBreakCooldown;
|
private int blockBreakCooldown;
|
||||||
|
private int phaseTransitionTicks;
|
||||||
|
private int portalCooldown;
|
||||||
|
private int portalAttackTicks;
|
||||||
|
private int portalTravelTicks;
|
||||||
private boolean attackHitApplied;
|
private boolean attackHitApplied;
|
||||||
private boolean introRoarUsed;
|
private boolean introRoarUsed;
|
||||||
private boolean flyingToTarget;
|
private boolean flyingToTarget;
|
||||||
|
private boolean portalAttackHitApplied;
|
||||||
|
private int lastTriggeredSpecialAnimation = SPECIAL_NONE;
|
||||||
|
private Vec3 portalExitPos;
|
||||||
|
@Nullable
|
||||||
|
private NightmarePortalEntity entryPortal;
|
||||||
|
@Nullable
|
||||||
|
private NightmarePortalEntity exitPortal;
|
||||||
|
|
||||||
public NightmareEntity(EntityType<? extends NightmareEntity> entityType, Level level) {
|
public NightmareEntity(EntityType<? extends NightmareEntity> entityType, Level level) {
|
||||||
super(entityType, level);
|
super(entityType, level);
|
||||||
@@ -138,6 +213,13 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
.add(Attributes.ARMOR, 8.0D);
|
.add(Attributes.ARMOR, 8.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(ServerLevelAccessor level, net.minecraft.world.DifficultyInstance difficulty,
|
||||||
|
MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData spawnData) {
|
||||||
|
com.craisinlord.antarchy.content.entity.ConfiguredMobSpawnUtil.applyConfiguredHealth(this, AntarchySettings.nightmareHealth());
|
||||||
|
return super.finalizeSpawn(level, difficulty, spawnReason, spawnData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canSpawn(EntityType<NightmareEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
public static boolean canSpawn(EntityType<NightmareEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||||
boolean sturdy = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP);
|
boolean sturdy = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP);
|
||||||
boolean posEmpty = level.isEmptyBlock(pos);
|
boolean posEmpty = level.isEmptyBlock(pos);
|
||||||
@@ -149,17 +231,23 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
super.defineSynchedData(builder);
|
super.defineSynchedData(builder);
|
||||||
builder.define(ANIMATION_STATE, ANIM_IDLE);
|
builder.define(ANIMATION_STATE, ANIM_IDLE);
|
||||||
|
builder.define(ACTIVE_SPECIAL_ANIMATION, SPECIAL_NONE);
|
||||||
builder.define(ROARING, false);
|
builder.define(ROARING, false);
|
||||||
|
builder.define(PHASE_TWO, false);
|
||||||
|
builder.define(PHASE_TWO_TEXTURE, false);
|
||||||
|
builder.define(PHASE_TRANSITIONING, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerGoals() {
|
protected void registerGoals() {
|
||||||
this.goalSelector.addGoal(1, new NightmareRoarGoal());
|
this.goalSelector.addGoal(1, new NightmarePhaseTransitionGoal());
|
||||||
this.goalSelector.addGoal(2, new NightmareFlyToTargetGoal());
|
this.goalSelector.addGoal(2, new NightmarePortalGoal());
|
||||||
this.goalSelector.addGoal(3, new NightmareMeleeGoal());
|
this.goalSelector.addGoal(3, new NightmareRoarGoal());
|
||||||
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 16.0F));
|
this.goalSelector.addGoal(4, new NightmareFlyToTargetGoal());
|
||||||
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
this.goalSelector.addGoal(5, new NightmareMeleeGoal());
|
||||||
this.goalSelector.addGoal(7, new NightmareWanderGoal());
|
this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 16.0F));
|
||||||
|
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
||||||
|
this.goalSelector.addGoal(9, new NightmareWanderGoal());
|
||||||
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
|
||||||
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::canTargetEntity));
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::canTargetEntity));
|
||||||
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, this::canTargetEntity));
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, this::canTargetEntity));
|
||||||
@@ -167,22 +255,29 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||||
controllers.add(new AnimationController<>(this, "main_controller", 0, this::mainAnimController));
|
controllers.add(new AnimationController<>(this, LOCOMOTION_CONTROLLER, 0, this::mainAnimController));
|
||||||
|
controllers.add(new AnimationController<>(this, SPECIAL_CONTROLLER, 0, state -> PlayState.STOP)
|
||||||
|
.triggerableAnim(SPECIAL_ATTACK_TRIGGER, ATTACK_ANIM)
|
||||||
|
.triggerableAnim(SPECIAL_ATTACK_P2_TRIGGER, ATTACK_P2_ANIM)
|
||||||
|
.triggerableAnim(SPECIAL_FLY_ATTACK_TRIGGER, FLY_ATTACK_ANIM)
|
||||||
|
.triggerableAnim(SPECIAL_FLY_ATTACK_P2_TRIGGER, FLY_ATTACK_P2_ANIM)
|
||||||
|
.triggerableAnim(SPECIAL_ROAR_TRIGGER, ROAR_ANIM)
|
||||||
|
.triggerableAnim(SPECIAL_ROAR_P2_TRIGGER, ROAR_P2_ANIM)
|
||||||
|
.triggerableAnim(SPECIAL_PHASE_TWO_TRIGGER, PHASE_TWO_TRANSITION_ANIM)
|
||||||
|
.triggerableAnim(SPECIAL_PORTAL_TRIGGER, PORTAL_ATTACK_ANIM));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayState mainAnimController(AnimationState<NightmareEntity> state) {
|
private PlayState mainAnimController(AnimationState<NightmareEntity> state) {
|
||||||
|
if (this.hasActiveSpecialAnimation()) {
|
||||||
|
return PlayState.STOP;
|
||||||
|
}
|
||||||
int animState = this.getAnimationState();
|
int animState = this.getAnimationState();
|
||||||
state.getController().setAnimationSpeed(switch (animState) {
|
state.getController().setAnimationSpeed(animState == ANIM_FLY ? 0.45D : 1.0D);
|
||||||
case ANIM_FLY -> 0.45D;
|
boolean phaseTwo = this.isPhaseTwo();
|
||||||
default -> 1.0D;
|
|
||||||
});
|
|
||||||
return switch (animState) {
|
return switch (animState) {
|
||||||
case ANIM_WALK -> state.setAndContinue(WALK_ANIM);
|
case ANIM_WALK -> state.setAndContinue(phaseTwo ? PHASE_TWO_WALK_ANIM : WALK_ANIM);
|
||||||
case ANIM_FLY -> state.setAndContinue(FLY_ANIM);
|
case ANIM_FLY -> state.setAndContinue(phaseTwo ? PHASE_TWO_FLY_ANIM : FLY_ANIM);
|
||||||
case ANIM_ATTACK -> state.setAndContinue(ATTACK_ANIM);
|
default -> state.setAndContinue(phaseTwo ? PHASE_TWO_IDLE_ANIM : IDLE_ANIM);
|
||||||
case ANIM_FLY_ATTACK -> state.setAndContinue(FLY_ATTACK_ANIM);
|
|
||||||
case ANIM_ROAR -> state.setAndContinue(ROAR_ANIM);
|
|
||||||
default -> state.setAndContinue(IDLE_ANIM);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,6 +300,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (this.level().isClientSide) {
|
if (this.level().isClientSide) {
|
||||||
|
this.syncSpecialAnimationTrigger();
|
||||||
this.tickClientParticles();
|
this.tickClientParticles();
|
||||||
this.updateFlightRotation();
|
this.updateFlightRotation();
|
||||||
if (this.isRoaring()) {
|
if (this.isRoaring()) {
|
||||||
@@ -218,18 +314,20 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setNoGravity(this.flyingToTarget && !this.isTooCloseToCeiling());
|
this.setNoGravity((this.flyingToTarget || this.portalAttackTicks > 0 || this.portalTravelTicks > 0) && !this.isTooCloseToCeiling());
|
||||||
|
|
||||||
int prevAirborneTicks = this.airborneTicks;
|
int prevAirborneTicks = this.airborneTicks;
|
||||||
this.airborneTicks = this.onGround() ? 0 : this.airborneTicks + 1;
|
this.airborneTicks = this.onGround() ? 0 : this.airborneTicks + 1;
|
||||||
if (this.onGround() && prevAirborneTicks > 5) {
|
if (this.onGround() && prevAirborneTicks > 5) {
|
||||||
this.landingCooldown = 100;
|
this.landingCooldown = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.attackCooldown > 0) this.attackCooldown--;
|
if (this.attackCooldown > 0) this.attackCooldown--;
|
||||||
if (this.roarCooldown > 0) this.roarCooldown--;
|
if (this.roarCooldown > 0) this.roarCooldown--;
|
||||||
if (this.blockBreakCooldown > 0) this.blockBreakCooldown--;
|
if (this.blockBreakCooldown > 0) this.blockBreakCooldown--;
|
||||||
if (this.landingCooldown > 0) this.landingCooldown--;
|
if (this.landingCooldown > 0) this.landingCooldown--;
|
||||||
|
if (this.portalCooldown > 0) this.portalCooldown--;
|
||||||
|
if (this.portalTravelTicks > 0) this.portalTravelTicks--;
|
||||||
|
|
||||||
LivingEntity target = this.getTarget();
|
LivingEntity target = this.getTarget();
|
||||||
if (!this.canTargetEntity(target)) {
|
if (!this.canTargetEntity(target)) {
|
||||||
@@ -248,15 +346,21 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.isDeadOrDying()) {
|
if (this.isDeadOrDying()) {
|
||||||
|
this.clearNightmarePortals();
|
||||||
this.updateFlightRotation();
|
this.updateFlightRotation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.attackAnimationTicks > 0) {
|
if (this.isPhaseTransitioning()) {
|
||||||
|
this.tickPhaseTransition(target);
|
||||||
|
} else if (this.portalAttackTicks > 0) {
|
||||||
|
this.tickPortalAttack(target);
|
||||||
|
} else if (this.attackAnimationTicks > 0) {
|
||||||
this.tickAttack(target);
|
this.tickAttack(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateAnimationState();
|
this.updateAnimationState();
|
||||||
|
this.syncSpecialAnimationTrigger();
|
||||||
this.updateFlightRotation();
|
this.updateFlightRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,6 +375,27 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
super.travel(travelVector);
|
super.travel(travelVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hurt(DamageSource source, float amount) {
|
||||||
|
if (this.isPhaseTransitioning() || this.portalTravelTicks > 0 || this.portalAttackTicks > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.isPhaseTwo() && amount > 0.0F) {
|
||||||
|
float threshold = (float) (this.getMaxHealth() * PHASE_TWO_HEALTH_FRACTION);
|
||||||
|
if (this.getHealth() > threshold && this.getHealth() - amount <= threshold) {
|
||||||
|
float clampedAmount = this.getHealth() - threshold;
|
||||||
|
boolean hurt = clampedAmount > 0.0F && super.hurt(source, clampedAmount);
|
||||||
|
if (hurt || clampedAmount <= 0.0F) {
|
||||||
|
this.setHealth(threshold);
|
||||||
|
this.startPhaseTransition();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.hurt(source, amount);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean doHurtTarget(Entity target) {
|
public boolean doHurtTarget(Entity target) {
|
||||||
if (!(target instanceof LivingEntity livingTarget)) return false;
|
if (!(target instanceof LivingEntity livingTarget)) return false;
|
||||||
@@ -358,6 +483,26 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
tag.putInt("AirborneTicks", this.airborneTicks);
|
tag.putInt("AirborneTicks", this.airborneTicks);
|
||||||
tag.putBoolean("Roaring", this.isRoaring());
|
tag.putBoolean("Roaring", this.isRoaring());
|
||||||
tag.putInt(ANIMATION_STATE_KEY, this.getAnimationState());
|
tag.putInt(ANIMATION_STATE_KEY, this.getAnimationState());
|
||||||
|
tag.putInt(ACTIVE_SPECIAL_ANIMATION_KEY, this.getActiveSpecialAnimation());
|
||||||
|
tag.putBoolean(PHASE_TWO_KEY, this.isPhaseTwo());
|
||||||
|
tag.putBoolean(PHASE_TWO_TEXTURE_KEY, this.hasPhaseTwoTexture());
|
||||||
|
tag.putBoolean(PHASE_TRANSITIONING_KEY, this.isPhaseTransitioning());
|
||||||
|
tag.putInt(PHASE_TRANSITION_TICKS_KEY, this.phaseTransitionTicks);
|
||||||
|
tag.putInt(PORTAL_COOLDOWN_KEY, this.portalCooldown);
|
||||||
|
tag.putInt(PORTAL_ATTACK_TICKS_KEY, this.portalAttackTicks);
|
||||||
|
tag.putBoolean(PORTAL_ATTACK_HIT_KEY, this.portalAttackHitApplied);
|
||||||
|
tag.putInt(PORTAL_TRAVEL_TICKS_KEY, this.portalTravelTicks);
|
||||||
|
if (this.portalExitPos != null) {
|
||||||
|
tag.putDouble(PORTAL_EXIT_X_KEY, this.portalExitPos.x);
|
||||||
|
tag.putDouble(PORTAL_EXIT_Y_KEY, this.portalExitPos.y);
|
||||||
|
tag.putDouble(PORTAL_EXIT_Z_KEY, this.portalExitPos.z);
|
||||||
|
}
|
||||||
|
if (this.entryPortal != null) {
|
||||||
|
tag.putUUID(PORTAL_ENTRY_ID_KEY, this.entryPortal.getUUID());
|
||||||
|
}
|
||||||
|
if (this.exitPortal != null) {
|
||||||
|
tag.putUUID(PORTAL_EXIT_ID_KEY, this.exitPortal.getUUID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -371,8 +516,22 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
this.introRoarUsed = tag.getBoolean(INTRO_ROAR_USED_KEY);
|
this.introRoarUsed = tag.getBoolean(INTRO_ROAR_USED_KEY);
|
||||||
this.targetlessTicks = tag.getInt(TARGETLESS_TICKS_KEY);
|
this.targetlessTicks = tag.getInt(TARGETLESS_TICKS_KEY);
|
||||||
this.airborneTicks = tag.getInt("AirborneTicks");
|
this.airborneTicks = tag.getInt("AirborneTicks");
|
||||||
|
this.portalCooldown = tag.getInt(PORTAL_COOLDOWN_KEY);
|
||||||
|
this.portalAttackTicks = tag.getInt(PORTAL_ATTACK_TICKS_KEY);
|
||||||
|
this.portalAttackHitApplied = tag.getBoolean(PORTAL_ATTACK_HIT_KEY);
|
||||||
|
this.portalTravelTicks = tag.getInt(PORTAL_TRAVEL_TICKS_KEY);
|
||||||
this.entityData.set(ROARING, tag.getBoolean("Roaring"));
|
this.entityData.set(ROARING, tag.getBoolean("Roaring"));
|
||||||
this.entityData.set(ANIMATION_STATE, tag.contains(ANIMATION_STATE_KEY) ? tag.getInt(ANIMATION_STATE_KEY) : ANIM_IDLE);
|
this.entityData.set(ANIMATION_STATE, tag.contains(ANIMATION_STATE_KEY) ? tag.getInt(ANIMATION_STATE_KEY) : ANIM_IDLE);
|
||||||
|
this.entityData.set(ACTIVE_SPECIAL_ANIMATION, tag.contains(ACTIVE_SPECIAL_ANIMATION_KEY) ? tag.getInt(ACTIVE_SPECIAL_ANIMATION_KEY) : SPECIAL_NONE);
|
||||||
|
this.setPhaseTwo(tag.getBoolean(PHASE_TWO_KEY));
|
||||||
|
this.setPhaseTwoTexture(tag.contains(PHASE_TWO_TEXTURE_KEY) ? tag.getBoolean(PHASE_TWO_TEXTURE_KEY) : this.isPhaseTwo() && !this.isPhaseTransitioning());
|
||||||
|
this.setPhaseTransitioning(tag.getBoolean(PHASE_TRANSITIONING_KEY));
|
||||||
|
this.phaseTransitionTicks = tag.getInt(PHASE_TRANSITION_TICKS_KEY);
|
||||||
|
if (tag.contains(PORTAL_EXIT_X_KEY)) {
|
||||||
|
this.portalExitPos = new Vec3(tag.getDouble(PORTAL_EXIT_X_KEY), tag.getDouble(PORTAL_EXIT_Y_KEY), tag.getDouble(PORTAL_EXIT_Z_KEY));
|
||||||
|
} else {
|
||||||
|
this.portalExitPos = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -381,9 +540,14 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
this.attackAnimationTicks = 0;
|
this.attackAnimationTicks = 0;
|
||||||
this.attackCooldown = 0;
|
this.attackCooldown = 0;
|
||||||
this.roarTicks = 0;
|
this.roarTicks = 0;
|
||||||
|
this.portalAttackTicks = 0;
|
||||||
|
this.portalTravelTicks = 0;
|
||||||
|
this.phaseTransitionTicks = 0;
|
||||||
|
this.clearActiveSpecialAnimation();
|
||||||
this.setRoaring(false);
|
this.setRoaring(false);
|
||||||
this.setDeltaMovement(Vec3.ZERO);
|
this.setDeltaMovement(Vec3.ZERO);
|
||||||
this.getNavigation().stop();
|
this.getNavigation().stop();
|
||||||
|
this.clearNightmarePortals();
|
||||||
}
|
}
|
||||||
super.die(damageSource);
|
super.die(damageSource);
|
||||||
}
|
}
|
||||||
@@ -405,6 +569,22 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
return this.entityData.get(ANIMATION_STATE);
|
return this.entityData.get(ANIMATION_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getActiveSpecialAnimation() {
|
||||||
|
return this.entityData.get(ACTIVE_SPECIAL_ANIMATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPhaseTwo() {
|
||||||
|
return this.entityData.get(PHASE_TWO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPhaseTwoTexture() {
|
||||||
|
return this.entityData.get(PHASE_TWO_TEXTURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPhaseTransitioning() {
|
||||||
|
return this.entityData.get(PHASE_TRANSITIONING);
|
||||||
|
}
|
||||||
|
|
||||||
private void setRoaring(boolean roaring) {
|
private void setRoaring(boolean roaring) {
|
||||||
this.entityData.set(ROARING, roaring);
|
this.entityData.set(ROARING, roaring);
|
||||||
}
|
}
|
||||||
@@ -415,13 +595,29 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setActiveSpecialAnimation(int specialAnimation) {
|
||||||
|
if (this.entityData.get(ACTIVE_SPECIAL_ANIMATION) != specialAnimation) {
|
||||||
|
this.entityData.set(ACTIVE_SPECIAL_ANIMATION, specialAnimation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPhaseTwo(boolean phaseTwo) {
|
||||||
|
this.entityData.set(PHASE_TWO, phaseTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPhaseTwoTexture(boolean phaseTwoTexture) {
|
||||||
|
this.entityData.set(PHASE_TWO_TEXTURE, phaseTwoTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPhaseTransitioning(boolean phaseTransitioning) {
|
||||||
|
this.entityData.set(PHASE_TRANSITIONING, phaseTransitioning);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean shouldStartRoar(LivingEntity target) {
|
private boolean shouldStartRoar(LivingEntity target) {
|
||||||
if (!this.onGround() || this.roarCooldown > 0 || !this.hasLineOfSight(target)) return false;
|
if (!this.onGround() || this.roarCooldown > 0 || !this.hasLineOfSight(target)) return false;
|
||||||
double distanceSqr = this.distanceToSqr(target);
|
double distanceSqr = this.distanceToSqr(target);
|
||||||
if (distanceSqr > ROAR_RETRY_DISTANCE_SQR || !this.isInFront(target.position(), -0.1D)) return false;
|
if (distanceSqr > ROAR_RETRY_DISTANCE_SQR || !this.isInFront(target.position(), -0.1D)) return false;
|
||||||
boolean pressureWindow = distanceSqr > ATTACK_START_RANGE_SQR;
|
return distanceSqr > ATTACK_START_RANGE_SQR || this.isPhaseTwo();
|
||||||
boolean wounded = this.getHealth() <= this.getMaxHealth() * 0.5F;
|
|
||||||
return pressureWindow || wounded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startRoar() {
|
private void startRoar() {
|
||||||
@@ -431,6 +627,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
this.attackAnimationTicks = 0;
|
this.attackAnimationTicks = 0;
|
||||||
this.attackHitApplied = false;
|
this.attackHitApplied = false;
|
||||||
this.setRoaring(true);
|
this.setRoaring(true);
|
||||||
|
this.selectSpecialAnimation(this.isPhaseTwo() ? SPECIAL_ROAR_P2 : SPECIAL_ROAR);
|
||||||
this.getNavigation().stop();
|
this.getNavigation().stop();
|
||||||
this.setDeltaMovement(this.getDeltaMovement().scale(0.18D));
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.18D));
|
||||||
this.playSound(AntarchySoundEvents.NIGHTMARE_ROAR.get(), 2.2F, 0.7F + this.random.nextFloat() * 0.06F);
|
this.playSound(AntarchySoundEvents.NIGHTMARE_ROAR.get(), 2.2F, 0.7F + this.random.nextFloat() * 0.06F);
|
||||||
@@ -451,6 +648,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
if (--this.roarTicks <= 0) {
|
if (--this.roarTicks <= 0) {
|
||||||
this.roarTicks = 0;
|
this.roarTicks = 0;
|
||||||
this.setRoaring(false);
|
this.setRoaring(false);
|
||||||
|
this.clearActiveSpecialAnimation();
|
||||||
this.attackCooldown = Math.max(this.attackCooldown, 18);
|
this.attackCooldown = Math.max(this.attackCooldown, 18);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,6 +657,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
this.attackAnimationTicks = ATTACK_TOTAL_TICKS;
|
this.attackAnimationTicks = ATTACK_TOTAL_TICKS;
|
||||||
this.attackHitApplied = false;
|
this.attackHitApplied = false;
|
||||||
this.attackCooldown = ATTACK_TOTAL_TICKS + 12;
|
this.attackCooldown = ATTACK_TOTAL_TICKS + 12;
|
||||||
|
this.selectSpecialAnimation(this.selectAttackSpecialAnimation());
|
||||||
this.getNavigation().stop();
|
this.getNavigation().stop();
|
||||||
Vec3 lunge = target.getEyePosition().subtract(this.getEyePosition());
|
Vec3 lunge = target.getEyePosition().subtract(this.getEyePosition());
|
||||||
if (lunge.lengthSqr() > 1.0E-4D) {
|
if (lunge.lengthSqr() > 1.0E-4D) {
|
||||||
@@ -479,13 +678,122 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
if (!this.attackHitApplied && elapsed >= ATTACK_DAMAGE_TICK) {
|
if (!this.attackHitApplied && elapsed >= ATTACK_DAMAGE_TICK) {
|
||||||
this.attackHitApplied = true;
|
this.attackHitApplied = true;
|
||||||
this.playNightmareBiteSound();
|
this.playNightmareBiteSound();
|
||||||
|
this.spawnBiteEffect();
|
||||||
this.performAttackHit();
|
this.performAttackHit();
|
||||||
}
|
}
|
||||||
if (--this.attackAnimationTicks <= 0) {
|
if (--this.attackAnimationTicks <= 0) {
|
||||||
this.attackAnimationTicks = 0;
|
this.attackAnimationTicks = 0;
|
||||||
|
this.clearActiveSpecialAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startPhaseTransition() {
|
||||||
|
this.setPhaseTwo(true);
|
||||||
|
this.setPhaseTwoTexture(false);
|
||||||
|
this.setPhaseTransitioning(true);
|
||||||
|
this.selectSpecialAnimation(SPECIAL_PHASE_TWO);
|
||||||
|
this.phaseTransitionTicks = PHASE_TWO_TRANSITION_TICKS;
|
||||||
|
this.attackAnimationTicks = 0;
|
||||||
|
this.portalAttackTicks = 0;
|
||||||
|
this.portalTravelTicks = 0;
|
||||||
|
this.attackHitApplied = false;
|
||||||
|
this.portalAttackHitApplied = false;
|
||||||
|
this.portalExitPos = null;
|
||||||
|
this.clearNightmarePortals();
|
||||||
|
this.getNavigation().stop();
|
||||||
|
this.setRoaring(false);
|
||||||
|
this.setDeltaMovement(Vec3.ZERO);
|
||||||
|
this.roarCooldown = Math.max(this.roarCooldown, 80);
|
||||||
|
this.portalCooldown = Math.max(this.portalCooldown, 140);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickPhaseTransition(@Nullable LivingEntity target) {
|
||||||
|
this.getNavigation().stop();
|
||||||
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.45D));
|
||||||
|
this.getMoveControl().setWantedPosition(this.getX(), this.getY(), this.getZ(), 0.0D);
|
||||||
|
if (target != null) {
|
||||||
|
this.getLookControl().setLookAt(target, 35.0F, 20.0F);
|
||||||
|
}
|
||||||
|
if (this.phaseTransitionTicks % 8 == 0 && this.level() instanceof ServerLevel serverLevel) {
|
||||||
|
serverLevel.sendParticles(ParticleTypes.SOUL_FIRE_FLAME, this.getX(), this.getY() + 1.9D, this.getZ(), 12, 1.0D, 0.7D, 1.0D, 0.01D);
|
||||||
|
serverLevel.sendParticles(ParticleTypes.SMOKE, this.getX(), this.getY() + 1.9D, this.getZ(), 10, 0.8D, 0.5D, 0.8D, 0.02D);
|
||||||
|
}
|
||||||
|
if (!this.hasPhaseTwoTexture() && PHASE_TWO_TRANSITION_TICKS - this.phaseTransitionTicks >= PHASE_TWO_TEXTURE_SWAP_TICKS) {
|
||||||
|
this.setPhaseTwoTexture(true);
|
||||||
|
}
|
||||||
|
if (--this.phaseTransitionTicks <= 0) {
|
||||||
|
this.phaseTransitionTicks = 0;
|
||||||
|
this.setPhaseTwoTexture(true);
|
||||||
|
this.setPhaseTransitioning(false);
|
||||||
|
this.clearActiveSpecialAnimation();
|
||||||
|
this.attackCooldown = Math.max(this.attackCooldown, 18);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canStartPortalAttack(LivingEntity target) {
|
||||||
|
if (!this.isPhaseTwo() || this.isPhaseTransitioning() || this.portalCooldown > 0 || this.attackAnimationTicks > 0 || this.roarTicks > 0) return false;
|
||||||
|
if (!this.hasLineOfSight(target) || this.distanceToSqr(target) > PORTAL_RANGE * PORTAL_RANGE) return false;
|
||||||
|
if (this.horizontalDistanceToSqr(target) < PORTAL_MIN_RANGE_SQR) return false;
|
||||||
|
return this.portalAttackTicks <= 0 && this.findPortalExitPos(target) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startPortalAttack(LivingEntity target) {
|
||||||
|
Vec3 exitPos = this.findPortalExitPos(target);
|
||||||
|
if (exitPos == null || !(this.level() instanceof ServerLevel serverLevel)) return;
|
||||||
|
this.clearNightmarePortals();
|
||||||
|
this.portalExitPos = exitPos;
|
||||||
|
this.portalAttackTicks = PORTAL_TOTAL_TICKS;
|
||||||
|
this.portalTravelTicks = 0;
|
||||||
|
this.portalAttackHitApplied = false;
|
||||||
|
this.attackAnimationTicks = 0;
|
||||||
|
this.attackHitApplied = false;
|
||||||
|
this.attackCooldown = 24;
|
||||||
|
this.portalCooldown = 180 + this.random.nextInt(100);
|
||||||
|
this.selectSpecialAnimation(SPECIAL_PORTAL);
|
||||||
|
this.getNavigation().stop();
|
||||||
|
this.entryPortal = NightmarePortalEntity.spawnAt(serverLevel, this.position().add(this.getViewVector(1.0F).multiply(1.6D, 0.0D, 1.6D)), this, this.position(), PORTAL_LIFETIME_TICKS);
|
||||||
|
this.exitPortal = NightmarePortalEntity.spawnAt(serverLevel, exitPos, this, this.position(), PORTAL_LIFETIME_TICKS);
|
||||||
|
if (this.entryPortal != null && this.exitPortal != null) {
|
||||||
|
this.entryPortal.linkTo(this.exitPortal);
|
||||||
|
this.exitPortal.linkTo(this.entryPortal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickPortalAttack(@Nullable LivingEntity target) {
|
||||||
|
this.getNavigation().stop();
|
||||||
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.55D));
|
||||||
|
if (target != null) {
|
||||||
|
this.getLookControl().setLookAt(target, 35.0F, 20.0F);
|
||||||
|
}
|
||||||
|
int elapsed = PORTAL_TOTAL_TICKS - this.portalAttackTicks;
|
||||||
|
if (elapsed == PORTAL_TELEPORT_TICK && this.portalExitPos != null) {
|
||||||
|
this.executePortalTeleport(target);
|
||||||
|
}
|
||||||
|
if (!this.portalAttackHitApplied && elapsed >= PORTAL_DAMAGE_TICK) {
|
||||||
|
this.portalAttackHitApplied = true;
|
||||||
|
this.spawnBiteEffect();
|
||||||
|
this.performPortalExitHit();
|
||||||
|
}
|
||||||
|
if (--this.portalAttackTicks <= 0) {
|
||||||
|
this.portalAttackTicks = 0;
|
||||||
|
this.portalExitPos = null;
|
||||||
|
this.clearNightmarePortals();
|
||||||
|
this.clearActiveSpecialAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executePortalTeleport(@Nullable LivingEntity target) {
|
||||||
|
if (this.portalExitPos == null) return;
|
||||||
|
this.portalTravelTicks = PORTAL_TRAVEL_INVULNERABLE_TICKS;
|
||||||
|
this.setPortalCooldown();
|
||||||
|
this.teleportTo(this.portalExitPos.x, this.portalExitPos.y, this.portalExitPos.z);
|
||||||
|
if (target != null) {
|
||||||
|
this.faceTowardTarget(target, 180.0F);
|
||||||
|
}
|
||||||
|
this.setDeltaMovement(Vec3.ZERO);
|
||||||
|
this.hasImpulse = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void performAttackHit() {
|
private void performAttackHit() {
|
||||||
AABB hitBox = this.getBoundingBox()
|
AABB hitBox = this.getBoundingBox()
|
||||||
.inflate(ATTACK_REACH_RADIUS, 1.5D, ATTACK_REACH_RADIUS)
|
.inflate(ATTACK_REACH_RADIUS, 1.5D, ATTACK_REACH_RADIUS)
|
||||||
@@ -505,6 +813,38 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void performPortalExitHit() {
|
||||||
|
if (this.portalExitPos == null) return;
|
||||||
|
AABB hitBox = this.getBoundingBox().move(this.portalExitPos.subtract(this.position())).inflate(1.7D, 1.2D, 1.7D);
|
||||||
|
float damage = (float) (this.getAttributeValue(Attributes.ATTACK_DAMAGE) * 1.15F);
|
||||||
|
List<LivingEntity> victims = this.level().getEntitiesOfClass(LivingEntity.class, hitBox, this::canTargetEntity);
|
||||||
|
for (LivingEntity victim : victims) {
|
||||||
|
if (victim.hurt(this.nightmareDamageSource(), damage)) {
|
||||||
|
this.spawnBiteEffectAt(victim);
|
||||||
|
this.applyNightmareStrikeEffects(victim);
|
||||||
|
this.knockAway(victim, 1.35D, 0.35D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.level() instanceof ServerLevel serverLevel) {
|
||||||
|
serverLevel.sendParticles(ParticleTypes.SOUL_FIRE_FLAME, this.portalExitPos.x, this.portalExitPos.y + 1.0D, this.portalExitPos.z, 18, 0.9D, 0.45D, 0.9D, 0.02D);
|
||||||
|
serverLevel.sendParticles(ParticleTypes.SMOKE, this.portalExitPos.x, this.portalExitPos.y + 1.0D, this.portalExitPos.z, 14, 0.8D, 0.3D, 0.8D, 0.03D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spawnBiteEffect() {
|
||||||
|
if (!(this.level() instanceof ServerLevel serverLevel)) return;
|
||||||
|
Vec3 forward = this.getViewVector(1.0F).normalize();
|
||||||
|
Vec3 spawnPos = this.getEyePosition().add(forward.scale(this.getBbWidth() * 0.65D)).add(0.0D, -0.45D, 0.0D);
|
||||||
|
NightmareBiteEntity.spawnAt(serverLevel, spawnPos, this.getYRot(), this.isPhaseTwo());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spawnBiteEffectAt(LivingEntity target) {
|
||||||
|
if (!(this.level() instanceof ServerLevel serverLevel)) return;
|
||||||
|
float yaw = target.getYRot() + 180.0F;
|
||||||
|
Vec3 spawnPos = target.getEyePosition().add(0.0D, -0.35D, 0.0D);
|
||||||
|
NightmareBiteEntity.spawnAt(serverLevel, spawnPos, yaw, this.isPhaseTwo());
|
||||||
|
}
|
||||||
|
|
||||||
private void playNightmareBiteSound() {
|
private void playNightmareBiteSound() {
|
||||||
this.playSound(AntarchySoundEvents.NIGHTMARE_BITE.get(), 1.3F, 0.72F + this.random.nextFloat() * 0.08F);
|
this.playSound(AntarchySoundEvents.NIGHTMARE_BITE.get(), 1.3F, 0.72F + this.random.nextFloat() * 0.08F);
|
||||||
}
|
}
|
||||||
@@ -564,19 +904,48 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
return entity instanceof Mob && entity.isAttackable();
|
return entity instanceof Mob && entity.isAttackable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldUseFlight() {
|
|
||||||
if (this.landingCooldown > 0) return false;
|
|
||||||
LivingEntity target = this.getTarget();
|
|
||||||
return target != null
|
|
||||||
&& this.distanceToSqr(target) > FLIGHT_ENGAGE_RANGE_SQR
|
|
||||||
&& !this.isTooCloseToCeiling();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canStartAttackOn(LivingEntity target) {
|
private boolean canStartAttackOn(LivingEntity target) {
|
||||||
if (!this.hasLineOfSight(target) || this.distanceToSqr(target) > ATTACK_START_RANGE_SQR) return false;
|
if (!this.hasLineOfSight(target) || this.distanceToSqr(target) > ATTACK_START_RANGE_SQR) return false;
|
||||||
double hdSqr = this.horizontalDistanceToSqr(target);
|
double hdSqr = this.horizontalDistanceToSqr(target);
|
||||||
double verticalDistance = Math.abs(target.getEyeY() - this.getEyeY());
|
double verticalDistance = Math.abs(target.getEyeY() - this.getEyeY());
|
||||||
return hdSqr <= ATTACK_COMMIT_HORIZONTAL_RANGE * ATTACK_COMMIT_HORIZONTAL_RANGE && verticalDistance <= 4.0D;
|
return hdSqr <= ATTACK_COMMIT_HORIZONTAL_RANGE_SQR && verticalDistance <= 4.0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldUseFlightPressure(LivingEntity target) {
|
||||||
|
if (target == null || this.isTooCloseToCeiling()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double distanceSqr = this.distanceToSqr(target);
|
||||||
|
double verticalDistance = Math.abs(target.getEyeY() - this.getEyeY());
|
||||||
|
if (this.flyingToTarget) {
|
||||||
|
return distanceSqr > ATTACK_COMMIT_HORIZONTAL_RANGE_SQR || verticalDistance > 1.25D;
|
||||||
|
}
|
||||||
|
if (distanceSqr >= FLIGHT_ENGAGE_RANGE_SQR) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.isPhaseTwo() && (distanceSqr >= FLIGHT_DISENGAGE_RANGE_SQR || verticalDistance > 1.5D);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vec3 getFlightApproachPosition(LivingEntity target) {
|
||||||
|
Vec3 toTarget = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D);
|
||||||
|
if (toTarget.lengthSqr() < 1.0E-4D) {
|
||||||
|
toTarget = target.getLookAngle().multiply(1.0D, 0.0D, 1.0D);
|
||||||
|
}
|
||||||
|
if (toTarget.lengthSqr() < 1.0E-4D) {
|
||||||
|
toTarget = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D);
|
||||||
|
}
|
||||||
|
if (toTarget.lengthSqr() < 1.0E-4D) {
|
||||||
|
toTarget = new Vec3(0.0D, 0.0D, 1.0D);
|
||||||
|
}
|
||||||
|
Vec3 forward = toTarget.normalize();
|
||||||
|
Vec3 right = new Vec3(-forward.z, 0.0D, forward.x);
|
||||||
|
double strafe = this.tickCount % 32 < 16 ? FLYING_APPROACH_STRAFE_OFFSET : -FLYING_APPROACH_STRAFE_OFFSET;
|
||||||
|
double height = this.isPhaseTwo() ? FLYING_APPROACH_HEIGHT_PHASE_TWO : FLYING_APPROACH_HEIGHT;
|
||||||
|
Vec3 anchor = target.position().subtract(forward.scale(1.4D)).add(right.scale(strafe));
|
||||||
|
if (this.horizontalDistanceToSqr(target) <= FLYING_APPROACH_TOO_CLOSE_RANGE_SQR) {
|
||||||
|
anchor = target.position().subtract(forward.scale(2.4D));
|
||||||
|
}
|
||||||
|
return new Vec3(anchor.x, target.getEyeY() + height, anchor.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double horizontalDistanceToSqr(LivingEntity target) {
|
private double horizontalDistanceToSqr(LivingEntity target) {
|
||||||
@@ -608,7 +977,6 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean isTooCloseToCeiling() {
|
private boolean isTooCloseToCeiling() {
|
||||||
BlockPos current = BlockPos.containing(this.getX(), this.getY(), this.getZ());
|
BlockPos current = BlockPos.containing(this.getX(), this.getY(), this.getZ());
|
||||||
for (int i = 1; i <= FLIGHT_CEILING_CLEARANCE_BLOCKS; i++) {
|
for (int i = 1; i <= FLIGHT_CEILING_CLEARANCE_BLOCKS; i++) {
|
||||||
@@ -617,8 +985,58 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Vec3 findPortalExitPos(LivingEntity target) {
|
||||||
|
Vec3 forward = target.getLookAngle().multiply(1.0D, 0.0D, 1.0D);
|
||||||
|
if (forward.lengthSqr() < 1.0E-4D) {
|
||||||
|
forward = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D);
|
||||||
|
}
|
||||||
|
if (forward.lengthSqr() < 1.0E-4D) {
|
||||||
|
forward = new Vec3(0.0D, 0.0D, 1.0D);
|
||||||
|
}
|
||||||
|
forward = forward.normalize();
|
||||||
|
Vec3 right = new Vec3(-forward.z, 0.0D, forward.x);
|
||||||
|
Vec3[] candidates = new Vec3[] {
|
||||||
|
target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)),
|
||||||
|
target.position().subtract(forward.scale(1.4D)).add(right.scale(2.25D)),
|
||||||
|
target.position().subtract(forward.scale(1.4D)).subtract(right.scale(2.25D)),
|
||||||
|
target.position().add(forward.scale(2.4D))
|
||||||
|
};
|
||||||
|
for (Vec3 candidate : candidates) {
|
||||||
|
Vec3 adjusted = this.findValidPortalPosition(candidate);
|
||||||
|
if (adjusted != null && adjusted.distanceToSqr(this.position()) <= PORTAL_RANGE * PORTAL_RANGE) {
|
||||||
|
return adjusted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Vec3 findValidPortalPosition(Vec3 base) {
|
||||||
|
EntityDimensions dimensions = this.getType().getDimensions();
|
||||||
|
for (int yOffset = 1; yOffset >= -1; yOffset--) {
|
||||||
|
Vec3 candidate = new Vec3(base.x, base.y + yOffset, base.z);
|
||||||
|
AABB box = dimensions.makeBoundingBox(candidate);
|
||||||
|
if (this.level().noCollision(this, box)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearNightmarePortals() {
|
||||||
|
if (this.entryPortal != null && this.entryPortal.isAlive()) {
|
||||||
|
this.entryPortal.discard();
|
||||||
|
}
|
||||||
|
if (this.exitPortal != null && this.exitPortal.isAlive()) {
|
||||||
|
this.exitPortal.discard();
|
||||||
|
}
|
||||||
|
this.entryPortal = null;
|
||||||
|
this.exitPortal = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void tickClientParticles() {
|
private void tickClientParticles() {
|
||||||
if ((this.isRoaring() || this.attackAnimationTicks > 0) && this.tickCount % 3 == 0) {
|
if ((this.isRoaring() || this.attackAnimationTicks > 0 || this.portalAttackTicks > 0 || this.isPhaseTransitioning()) && this.tickCount % 3 == 0) {
|
||||||
this.level().addParticle(
|
this.level().addParticle(
|
||||||
ParticleTypes.SOUL_FIRE_FLAME,
|
ParticleTypes.SOUL_FIRE_FLAME,
|
||||||
this.getX() + (this.random.nextDouble() - 0.5D) * this.getBbWidth(),
|
this.getX() + (this.random.nextDouble() - 0.5D) * this.getBbWidth(),
|
||||||
@@ -652,14 +1070,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
this.wingFlapCooldown = 0;
|
this.wingFlapCooldown = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.isRoaring()) {
|
if (this.hasActiveSpecialAnimation()) {
|
||||||
this.setAnimationState(ANIM_ROAR);
|
|
||||||
this.groundMoveTicks = 0;
|
|
||||||
this.wingFlapCooldown = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.attackAnimationTicks > 0) {
|
|
||||||
this.setAnimationState(this.isNoGravity() || this.airborneTicks >= MIN_AIRBORNE_TICKS_FOR_FLY_ANIM ? ANIM_FLY_ATTACK : ANIM_ATTACK);
|
|
||||||
this.groundMoveTicks = 0;
|
this.groundMoveTicks = 0;
|
||||||
this.tickWingFlapSound();
|
this.tickWingFlapSound();
|
||||||
return;
|
return;
|
||||||
@@ -676,7 +1087,8 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
this.tickWingFlapSound();
|
this.tickWingFlapSound();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.walkDist - this.walkDistO > 0.005F) {
|
Vec3 horizontalVelocity = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D);
|
||||||
|
if (horizontalVelocity.lengthSqr() > ANIMATION_MOVEMENT_THRESHOLD_SQR) {
|
||||||
this.groundMoveTicks = 6;
|
this.groundMoveTicks = 6;
|
||||||
}
|
}
|
||||||
if (this.groundMoveTicks > 0) {
|
if (this.groundMoveTicks > 0) {
|
||||||
@@ -705,6 +1117,112 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
this.wingFlapCooldown = 5 + this.random.nextInt(4);
|
this.wingFlapCooldown = 5 + this.random.nextInt(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasActiveSpecialAnimation() {
|
||||||
|
return this.getActiveSpecialAnimation() != SPECIAL_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int selectAttackSpecialAnimation() {
|
||||||
|
boolean flyingAttack = this.isNoGravity() || this.airborneTicks >= MIN_AIRBORNE_TICKS_FOR_FLY_ANIM || this.flyingToTarget;
|
||||||
|
if (flyingAttack) {
|
||||||
|
return this.isPhaseTwo() ? SPECIAL_FLY_ATTACK_P2 : SPECIAL_FLY_ATTACK;
|
||||||
|
}
|
||||||
|
return this.isPhaseTwo() ? SPECIAL_ATTACK_P2 : SPECIAL_ATTACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectSpecialAnimation(int specialAnimation) {
|
||||||
|
this.setActiveSpecialAnimation(specialAnimation);
|
||||||
|
if (!this.level().isClientSide) {
|
||||||
|
LOGGER.info("Nightmare animation selected={} tick={}", this.specialAnimationName(specialAnimation), this.tickCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearActiveSpecialAnimation() {
|
||||||
|
int specialAnimation = this.getActiveSpecialAnimation();
|
||||||
|
if (specialAnimation != SPECIAL_NONE && !this.level().isClientSide) {
|
||||||
|
LOGGER.info("Nightmare animation state cleared={} tick={}", this.specialAnimationName(specialAnimation), this.tickCount);
|
||||||
|
}
|
||||||
|
this.setActiveSpecialAnimation(SPECIAL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncSpecialAnimationTrigger() {
|
||||||
|
int activeSpecialAnimation = this.getActiveSpecialAnimation();
|
||||||
|
if (activeSpecialAnimation != SPECIAL_NONE && this.lastTriggeredSpecialAnimation != activeSpecialAnimation) {
|
||||||
|
String triggerName = this.specialAnimationTrigger(activeSpecialAnimation);
|
||||||
|
if (triggerName != null) {
|
||||||
|
if (!this.level().isClientSide) {
|
||||||
|
LOGGER.info("Nightmare triggerAnim called={} tick={}", triggerName, this.tickCount);
|
||||||
|
}
|
||||||
|
this.triggerAnim(SPECIAL_CONTROLLER, triggerName);
|
||||||
|
}
|
||||||
|
this.lastTriggeredSpecialAnimation = activeSpecialAnimation;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (activeSpecialAnimation == SPECIAL_NONE) {
|
||||||
|
this.lastTriggeredSpecialAnimation = SPECIAL_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String specialAnimationTrigger(int specialAnimation) {
|
||||||
|
return switch (specialAnimation) {
|
||||||
|
case SPECIAL_ATTACK -> SPECIAL_ATTACK_TRIGGER;
|
||||||
|
case SPECIAL_ATTACK_P2 -> SPECIAL_ATTACK_P2_TRIGGER;
|
||||||
|
case SPECIAL_FLY_ATTACK -> SPECIAL_FLY_ATTACK_TRIGGER;
|
||||||
|
case SPECIAL_FLY_ATTACK_P2 -> SPECIAL_FLY_ATTACK_P2_TRIGGER;
|
||||||
|
case SPECIAL_ROAR -> SPECIAL_ROAR_TRIGGER;
|
||||||
|
case SPECIAL_ROAR_P2 -> SPECIAL_ROAR_P2_TRIGGER;
|
||||||
|
case SPECIAL_PHASE_TWO -> SPECIAL_PHASE_TWO_TRIGGER;
|
||||||
|
case SPECIAL_PORTAL -> SPECIAL_PORTAL_TRIGGER;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String specialAnimationName(int specialAnimation) {
|
||||||
|
String triggerName = this.specialAnimationTrigger(specialAnimation);
|
||||||
|
return triggerName != null ? triggerName : "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class NightmarePhaseTransitionGoal extends Goal {
|
||||||
|
NightmarePhaseTransitionGoal() {
|
||||||
|
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK, Flag.JUMP));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse() {
|
||||||
|
return NightmareEntity.this.isPhaseTransitioning();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canContinueToUse() {
|
||||||
|
return NightmareEntity.this.isPhaseTransitioning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class NightmarePortalGoal extends Goal {
|
||||||
|
NightmarePortalGoal() {
|
||||||
|
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse() {
|
||||||
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
|
return target != null && NightmareEntity.this.canStartPortalAttack(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canContinueToUse() {
|
||||||
|
return NightmareEntity.this.portalAttackTicks > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
|
if (target != null) {
|
||||||
|
NightmareEntity.this.startPortalAttack(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class NightmareRoarGoal extends Goal {
|
private final class NightmareRoarGoal extends Goal {
|
||||||
NightmareRoarGoal() {
|
NightmareRoarGoal() {
|
||||||
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
|
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
|
||||||
@@ -713,7 +1231,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean canUse() {
|
public boolean canUse() {
|
||||||
LivingEntity target = NightmareEntity.this.getTarget();
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
return target instanceof Player && NightmareEntity.this.shouldStartRoar(target);
|
return target instanceof Player && NightmareEntity.this.shouldStartRoar(target) && !NightmareEntity.this.isPhaseTransitioning() && NightmareEntity.this.portalAttackTicks <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -748,14 +1266,17 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
LivingEntity target = NightmareEntity.this.getTarget();
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
return target != null
|
return target != null
|
||||||
&& NightmareEntity.this.landingCooldown <= 0
|
&& NightmareEntity.this.landingCooldown <= 0
|
||||||
&& NightmareEntity.this.distanceToSqr(target) > FLIGHT_ENGAGE_RANGE_SQR
|
&& NightmareEntity.this.shouldUseFlightPressure(target)
|
||||||
&& !NightmareEntity.this.isTooCloseToCeiling();
|
&& !NightmareEntity.this.isPhaseTransitioning()
|
||||||
|
&& NightmareEntity.this.portalAttackTicks <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canContinueToUse() {
|
public boolean canContinueToUse() {
|
||||||
LivingEntity target = NightmareEntity.this.getTarget();
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
return target != null && NightmareEntity.this.distanceToSqr(target) > FLIGHT_DISENGAGE_RANGE_SQR;
|
return target != null
|
||||||
|
&& NightmareEntity.this.shouldUseFlightPressure(target)
|
||||||
|
&& NightmareEntity.this.portalAttackTicks <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -766,7 +1287,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
NightmareEntity.this.flyingToTarget = false;
|
NightmareEntity.this.flyingToTarget = false;
|
||||||
NightmareEntity.this.landingCooldown = 80;
|
NightmareEntity.this.landingCooldown = 18;
|
||||||
NightmareEntity.this.getNavigation().stop();
|
NightmareEntity.this.getNavigation().stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,13 +1300,17 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
NightmareEntity.this.getNavigation().stop();
|
NightmareEntity.this.getNavigation().stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (NightmareEntity.this.onGround() && NightmareEntity.this.distanceToSqr(target) >= FLIGHT_DISENGAGE_RANGE_SQR) {
|
||||||
|
NightmareEntity.this.setDeltaMovement(NightmareEntity.this.getDeltaMovement().add(0.0D, 0.38D, 0.0D));
|
||||||
|
NightmareEntity.this.hasImpulse = true;
|
||||||
|
}
|
||||||
if (NightmareEntity.this.attackCooldown <= 0 && NightmareEntity.this.canStartAttackOn(target)) {
|
if (NightmareEntity.this.attackCooldown <= 0 && NightmareEntity.this.canStartAttackOn(target)) {
|
||||||
NightmareEntity.this.startAttack(target);
|
NightmareEntity.this.startAttack(target);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NightmareEntity.this.getMoveControl().setWantedPosition(
|
Vec3 approachPos = NightmareEntity.this.getFlightApproachPosition(target);
|
||||||
target.getX(), target.getEyeY() + 0.5D, target.getZ(), COMBAT_FLIGHT_SPEED
|
NightmareEntity.this.faceTowardTarget(target, 10.0F);
|
||||||
);
|
NightmareEntity.this.getMoveControl().setWantedPosition(approachPos.x, approachPos.y, approachPos.z, COMBAT_FLIGHT_SPEED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -794,6 +1319,26 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
super(NightmareEntity.this, GROUND_APPROACH_SPEED, true);
|
super(NightmareEntity.this, GROUND_APPROACH_SPEED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse() {
|
||||||
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
|
return !NightmareEntity.this.isPhaseTransitioning()
|
||||||
|
&& NightmareEntity.this.portalAttackTicks <= 0
|
||||||
|
&& target != null
|
||||||
|
&& !NightmareEntity.this.shouldUseFlightPressure(target)
|
||||||
|
&& super.canUse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canContinueToUse() {
|
||||||
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
|
return !NightmareEntity.this.isPhaseTransitioning()
|
||||||
|
&& NightmareEntity.this.portalAttackTicks <= 0
|
||||||
|
&& target != null
|
||||||
|
&& !NightmareEntity.this.shouldUseFlightPressure(target)
|
||||||
|
&& super.canContinueToUse();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
LivingEntity target = NightmareEntity.this.getTarget();
|
LivingEntity target = NightmareEntity.this.getTarget();
|
||||||
@@ -809,6 +1354,9 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void checkAndPerformAttack(LivingEntity target) {
|
protected void checkAndPerformAttack(LivingEntity target) {
|
||||||
|
if (NightmareEntity.this.shouldUseFlightPressure(target) && NightmareEntity.this.distanceToSqr(target) >= FLIGHT_ATTACK_RANGE_SQR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (NightmareEntity.this.attackCooldown <= 0 && NightmareEntity.this.canStartAttackOn(target)) {
|
if (NightmareEntity.this.attackCooldown <= 0 && NightmareEntity.this.canStartAttackOn(target)) {
|
||||||
NightmareEntity.this.startAttack(target);
|
NightmareEntity.this.startAttack(target);
|
||||||
}
|
}
|
||||||
@@ -816,7 +1364,9 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class NightmareWanderGoal extends Goal {
|
private final class NightmareWanderGoal extends Goal {
|
||||||
private double x, y, z;
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
private int wanderTicks;
|
private int wanderTicks;
|
||||||
|
|
||||||
NightmareWanderGoal() {
|
NightmareWanderGoal() {
|
||||||
@@ -825,7 +1375,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUse() {
|
public boolean canUse() {
|
||||||
if (NightmareEntity.this.getTarget() != null || NightmareEntity.this.isDeadOrDying()) return false;
|
if (NightmareEntity.this.getTarget() != null || NightmareEntity.this.isDeadOrDying() || NightmareEntity.this.isPhaseTransitioning() || NightmareEntity.this.portalAttackTicks > 0) return false;
|
||||||
if (NightmareEntity.this.random.nextInt(40) != 0) return false;
|
if (NightmareEntity.this.random.nextInt(40) != 0) return false;
|
||||||
double angle = NightmareEntity.this.random.nextDouble() * Math.PI * 2;
|
double angle = NightmareEntity.this.random.nextDouble() * Math.PI * 2;
|
||||||
double dist = 4 + NightmareEntity.this.random.nextDouble() * 10;
|
double dist = 4 + NightmareEntity.this.random.nextDouble() * 10;
|
||||||
|
|||||||
+186
@@ -0,0 +1,186 @@
|
|||||||
|
package com.craisinlord.antarchy.content.entity.nightmare;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||||
|
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.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.level.Level;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
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.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class NightmarePortalEntity extends Entity implements GeoEntity {
|
||||||
|
private static final EntityDataAccessor<Boolean> CLOSING = SynchedEntityData.defineId(NightmarePortalEntity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
private static final RawAnimation OPEN_ANIM = RawAnimation.begin().thenPlay("open").thenLoop("idle");
|
||||||
|
private static final RawAnimation CLOSE_ANIM = RawAnimation.begin().thenPlay("close");
|
||||||
|
|
||||||
|
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||||
|
private int lifetimeTicks;
|
||||||
|
private int ageTicks;
|
||||||
|
private UUID ownerId;
|
||||||
|
private UUID linkedPortalId;
|
||||||
|
private Vec3 fallbackDestination = Vec3.ZERO;
|
||||||
|
|
||||||
|
public NightmarePortalEntity(EntityType<? extends NightmarePortalEntity> entityType, Level level) {
|
||||||
|
super(entityType, level);
|
||||||
|
this.setInvulnerable(true);
|
||||||
|
this.noPhysics = true;
|
||||||
|
this.noCulling = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NightmarePortalEntity spawnAt(ServerLevel level, Vec3 pos, NightmareEntity owner, Vec3 fallbackDestination, int lifetimeTicks) {
|
||||||
|
NightmarePortalEntity portal = new NightmarePortalEntity(AntarchyObjects.NIGHTMARE_PORTAL.get(), level);
|
||||||
|
portal.moveTo(pos.x, pos.y, pos.z, owner.getYRot(), 0.0F);
|
||||||
|
portal.ownerId = owner.getUUID();
|
||||||
|
portal.fallbackDestination = fallbackDestination;
|
||||||
|
portal.lifetimeTicks = lifetimeTicks;
|
||||||
|
level.addFreshEntity(portal);
|
||||||
|
return portal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
|
builder.define(CLOSING, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvulnerableTo(DamageSource damageSource) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fireImmune() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lavaHurt() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPushable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeCollidedWith() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPickable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
if (this.level().isClientSide) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ageTicks++;
|
||||||
|
if (this.ageTicks >= this.lifetimeTicks - 10) {
|
||||||
|
this.entityData.set(CLOSING, true);
|
||||||
|
}
|
||||||
|
if (this.ageTicks >= this.lifetimeTicks) {
|
||||||
|
this.discard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.transportEntities();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transportEntities() {
|
||||||
|
NightmarePortalEntity other = this.getLinkedPortal();
|
||||||
|
Vec3 destination = other != null ? other.position() : this.fallbackDestination;
|
||||||
|
AABB area = this.getBoundingBox().inflate(1.05D, 0.75D, 1.05D);
|
||||||
|
List<LivingEntity> entities = this.level().getEntitiesOfClass(LivingEntity.class, area, entity -> entity.isAlive() && !entity.isSpectator());
|
||||||
|
for (LivingEntity entity : entities) {
|
||||||
|
if (entity.getUUID().equals(this.ownerId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (entity.isOnPortalCooldown()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entity.teleportTo(destination.x, destination.y, destination.z);
|
||||||
|
entity.setPortalCooldown();
|
||||||
|
entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D));
|
||||||
|
entity.hurtMarked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void linkTo(NightmarePortalEntity other) {
|
||||||
|
this.linkedPortalId = other.getUUID();
|
||||||
|
this.fallbackDestination = other.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NightmarePortalEntity getLinkedPortal() {
|
||||||
|
if (!(this.level() instanceof ServerLevel serverLevel) || this.linkedPortalId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Entity entity = serverLevel.getEntity(this.linkedPortalId);
|
||||||
|
return entity instanceof NightmarePortalEntity portal ? portal : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isClosing() {
|
||||||
|
return this.getEntityData().get(CLOSING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAdditionalSaveData(CompoundTag tag) {
|
||||||
|
tag.putInt("LifetimeTicks", this.lifetimeTicks);
|
||||||
|
tag.putInt("AgeTicks", this.ageTicks);
|
||||||
|
if (this.ownerId != null) {
|
||||||
|
tag.putUUID("OwnerId", this.ownerId);
|
||||||
|
}
|
||||||
|
if (this.linkedPortalId != null) {
|
||||||
|
tag.putUUID("LinkedPortalId", this.linkedPortalId);
|
||||||
|
}
|
||||||
|
tag.putDouble("FallbackX", this.fallbackDestination.x);
|
||||||
|
tag.putDouble("FallbackY", this.fallbackDestination.y);
|
||||||
|
tag.putDouble("FallbackZ", this.fallbackDestination.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readAdditionalSaveData(CompoundTag tag) {
|
||||||
|
this.lifetimeTicks = tag.getInt("LifetimeTicks");
|
||||||
|
this.ageTicks = tag.getInt("AgeTicks");
|
||||||
|
if (tag.hasUUID("OwnerId")) {
|
||||||
|
this.ownerId = tag.getUUID("OwnerId");
|
||||||
|
}
|
||||||
|
if (tag.hasUUID("LinkedPortalId")) {
|
||||||
|
this.linkedPortalId = tag.getUUID("LinkedPortalId");
|
||||||
|
}
|
||||||
|
this.fallbackDestination = new Vec3(tag.getDouble("FallbackX"), tag.getDouble("FallbackY"), tag.getDouble("FallbackZ"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||||
|
controllers.add(new AnimationController<>(this, "portal_controller", 0, this::portalController));
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayState portalController(AnimationState<NightmarePortalEntity> state) {
|
||||||
|
return state.setAndContinue(this.isClosing() ? CLOSE_ANIM : OPEN_ANIM);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||||
|
return this.geoCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -55,6 +55,10 @@ public final class CavarynHordeManager {
|
|||||||
Registries.BIOME,
|
Registries.BIOME,
|
||||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "biowart_caves")
|
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "biowart_caves")
|
||||||
);
|
);
|
||||||
|
private static final ResourceKey<Biome> CAVARYN_MOLEWORM_CAVES = ResourceKey.create(
|
||||||
|
Registries.BIOME,
|
||||||
|
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "cavaryn_moleworm_caves")
|
||||||
|
);
|
||||||
private static final ResourceLocation DORMANT_HORDE = hordeId("dormant");
|
private static final ResourceLocation DORMANT_HORDE = hordeId("dormant");
|
||||||
private static final ResourceLocation AWAKENING_HORDE = hordeId("awakening");
|
private static final ResourceLocation AWAKENING_HORDE = hordeId("awakening");
|
||||||
private static final ResourceLocation WAVE_ONE_HORDE = hordeId("wave_1");
|
private static final ResourceLocation WAVE_ONE_HORDE = hordeId("wave_1");
|
||||||
@@ -542,6 +546,9 @@ public final class CavarynHordeManager {
|
|||||||
if (level.getBiome(pos).is(BIOWART_CAVES)) {
|
if (level.getBiome(pos).is(BIOWART_CAVES)) {
|
||||||
return ResourceLocation.fromNamespaceAndPath(horde.getNamespace(), "biowart_caves/" + horde.getPath());
|
return ResourceLocation.fromNamespaceAndPath(horde.getNamespace(), "biowart_caves/" + horde.getPath());
|
||||||
}
|
}
|
||||||
|
if (level.getBiome(pos).is(CAVARYN_MOLEWORM_CAVES)) {
|
||||||
|
return ResourceLocation.fromNamespaceAndPath(horde.getNamespace(), "cavaryn_moleworm_caves/" + horde.getPath());
|
||||||
|
}
|
||||||
return horde;
|
return horde;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-2
@@ -26,20 +26,32 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
public class GlimmerBottleItem extends Item {
|
public class GlimmerBottleItem extends Item {
|
||||||
private static final String ABILITY_COOLDOWN_TAG = "AbilityCooldown";
|
private static final String ABILITY_COOLDOWN_TAG = "AbilityCooldown";
|
||||||
|
private static final String SHEAR_COOLDOWN_TAG = "ShearCooldown";
|
||||||
|
|
||||||
public GlimmerBottleItem() {
|
public GlimmerBottleItem() {
|
||||||
super(new Item.Properties().stacksTo(1));
|
super(new Item.Properties().stacksTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack create(GlimmerVariant variant) {
|
public static ItemStack create(GlimmerVariant variant) {
|
||||||
return create(variant, 0);
|
return create(variant, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack create(GlimmerVariant variant, int abilityCooldown) {
|
public static ItemStack create(GlimmerVariant variant, int abilityCooldown) {
|
||||||
|
return create(variant, abilityCooldown, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack create(GlimmerVariant variant, int abilityCooldown, int shearCooldown) {
|
||||||
ItemStack stack = new ItemStack(AntarchyObjects.GLIMMER_BOTTLE.get());
|
ItemStack stack = new ItemStack(AntarchyObjects.GLIMMER_BOTTLE.get());
|
||||||
stack.set(AntarchyObjects.GLIMMER_VARIANT_COMPONENT.get(), variant);
|
stack.set(AntarchyObjects.GLIMMER_VARIANT_COMPONENT.get(), variant);
|
||||||
|
if (abilityCooldown > 0 || shearCooldown > 0) {
|
||||||
|
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> {
|
||||||
if (abilityCooldown > 0) {
|
if (abilityCooldown > 0) {
|
||||||
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putInt(ABILITY_COOLDOWN_TAG, abilityCooldown));
|
tag.putInt(ABILITY_COOLDOWN_TAG, abilityCooldown);
|
||||||
|
}
|
||||||
|
if (shearCooldown > 0) {
|
||||||
|
tag.putInt(SHEAR_COOLDOWN_TAG, shearCooldown);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
@@ -53,6 +65,10 @@ public class GlimmerBottleItem extends Item {
|
|||||||
return stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag().getInt(ABILITY_COOLDOWN_TAG);
|
return stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag().getInt(ABILITY_COOLDOWN_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getStoredShearCooldown(ItemStack stack) {
|
||||||
|
return stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag().getInt(SHEAR_COOLDOWN_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
|
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
|
||||||
ItemStack stack = player.getItemInHand(hand);
|
ItemStack stack = player.getItemInHand(hand);
|
||||||
@@ -75,6 +91,7 @@ public class GlimmerBottleItem extends Item {
|
|||||||
glimmer.tame(player);
|
glimmer.tame(player);
|
||||||
glimmer.setOrderedToSit(false);
|
glimmer.setOrderedToSit(false);
|
||||||
glimmer.setAbilityCooldown(getStoredAbilityCooldown(stack));
|
glimmer.setAbilityCooldown(getStoredAbilityCooldown(stack));
|
||||||
|
glimmer.startShearCooldown(getStoredShearCooldown(stack));
|
||||||
level.addFreshEntity(glimmer);
|
level.addFreshEntity(glimmer);
|
||||||
GlimmerCompanionSavedData.replaceCompanion(((ServerLevel) level).getServer(), player.getUUID(), glimmer.getUUID());
|
GlimmerCompanionSavedData.replaceCompanion(((ServerLevel) level).getServer(), player.getUUID(), glimmer.getUUID());
|
||||||
GlimmerParticles.tickBurst(glimmer);
|
GlimmerParticles.tickBurst(glimmer);
|
||||||
|
|||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
package com.craisinlord.antarchy.content.item;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||||
|
import com.craisinlord.antarchy.content.item.ultimate.UltimateArmorItem;
|
||||||
|
import com.craisinlord.antarchy.content.item.ultimate.UltimateBowItem;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.tags.EnchantmentTags;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.enchantment.Enchantment;
|
||||||
|
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.world.item.enchantment.Enchantments;
|
||||||
|
import net.minecraft.world.item.enchantment.ItemEnchantments;
|
||||||
|
|
||||||
|
public final class InnateEnchantmentHelper {
|
||||||
|
private InnateEnchantmentHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasInnateNonCurseEnchantments(ItemStack stack) {
|
||||||
|
for (Object2IntMap.Entry<Holder<Enchantment>> entry : EnchantmentHelper.getEnchantmentsForCrafting(stack).entrySet()) {
|
||||||
|
Holder<Enchantment> enchantment = entry.getKey();
|
||||||
|
if (!enchantment.is(EnchantmentTags.CURSE) && isInnateEnchantment(stack, enchantment, entry.getIntValue())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasRemovableNonCurseEnchantments(ItemStack stack) {
|
||||||
|
for (Object2IntMap.Entry<Holder<Enchantment>> entry : EnchantmentHelper.getEnchantmentsForCrafting(stack).entrySet()) {
|
||||||
|
Holder<Enchantment> enchantment = entry.getKey();
|
||||||
|
if (!enchantment.is(EnchantmentTags.CURSE) && !isInnateEnchantment(stack, enchantment, entry.getIntValue())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack stripOnlyRemovableNonCurseEnchantments(ItemStack stack) {
|
||||||
|
EnchantmentHelper.updateEnchantments(stack, mutable ->
|
||||||
|
mutable.removeIf(enchantment ->
|
||||||
|
!enchantment.is(EnchantmentTags.CURSE)
|
||||||
|
&& !isInnateEnchantment(stack, enchantment, mutable.getLevel(enchantment))));
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInnateEnchantment(ItemStack stack, Holder<Enchantment> enchantment, int level) {
|
||||||
|
if (level <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.getItem() instanceof UltimateArmorItem) {
|
||||||
|
return AntarchySettings.ultimateArmorComesEnchanted()
|
||||||
|
&& level == 5
|
||||||
|
&& (enchantment.is(Enchantments.PROTECTION)
|
||||||
|
|| enchantment.is(Enchantments.FIRE_PROTECTION)
|
||||||
|
|| enchantment.is(Enchantments.PROJECTILE_PROTECTION)
|
||||||
|
|| enchantment.is(Enchantments.BLAST_PROTECTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.getItem() instanceof UltimateBowItem) {
|
||||||
|
return AntarchySettings.ultimateBowComesEnchantedWithFlame()
|
||||||
|
&& level == 1
|
||||||
|
&& enchantment.is(Enchantments.FLAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.getItem() instanceof KrakensGraspItem) {
|
||||||
|
int desiredLevel = Mth.clamp(AntarchySettings.krakensGraspInnateLoyaltyLevel(), 1, 3);
|
||||||
|
return AntarchySettings.krakensGraspInnateLoyalty()
|
||||||
|
&& level == desiredLevel
|
||||||
|
&& enchantment.is(Enchantments.LOYALTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package com.craisinlord.antarchy.content.item;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.item.BlockItem;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.TooltipFlag;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
|
||||||
|
public class LucidAnchorBlockItem extends BlockItem {
|
||||||
|
public LucidAnchorBlockItem(Block block, Properties properties) {
|
||||||
|
super(block, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||||
|
tooltipComponents.add(Component.translatable("tooltip.antarchy.lucid_anchor.pyramid").withStyle(ChatFormatting.DARK_RED));
|
||||||
|
tooltipComponents.add(Component.translatable("tooltip.antarchy.lucid_anchor.path").withStyle(ChatFormatting.GRAY));
|
||||||
|
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-1
@@ -19,10 +19,11 @@ import net.minecraft.world.item.TooltipFlag;
|
|||||||
import net.minecraft.world.item.component.ItemAttributeModifiers;
|
import net.minecraft.world.item.component.ItemAttributeModifiers;
|
||||||
|
|
||||||
public class NightmareArmorItem extends ArmorItem {
|
public class NightmareArmorItem extends ArmorItem {
|
||||||
|
private static final int BASE_DURABILITY_MULTIPLIER = 33;
|
||||||
private final Type armorType;
|
private final Type armorType;
|
||||||
|
|
||||||
public NightmareArmorItem(Holder<ArmorMaterial> material, Type type, Properties properties) {
|
public NightmareArmorItem(Holder<ArmorMaterial> material, Type type, Properties properties) {
|
||||||
super(material, type, properties);
|
super(material, type, properties.stacksTo(1).durability(resolveDurability(type)));
|
||||||
this.armorType = type;
|
this.armorType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,4 +120,13 @@ public class NightmareArmorItem extends ArmorItem {
|
|||||||
tooltipComponents.add(Component.translatable("tooltip.antarchy.nightmare_armor_set_bonus").withStyle(ChatFormatting.DARK_RED));
|
tooltipComponents.add(Component.translatable("tooltip.antarchy.nightmare_armor_set_bonus").withStyle(ChatFormatting.DARK_RED));
|
||||||
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int resolveDurability(Type armorType) {
|
||||||
|
return switch (armorType) {
|
||||||
|
case HELMET -> Type.HELMET.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
case CHESTPLATE, BODY -> Type.CHESTPLATE.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
case LEGGINGS -> Type.LEGGINGS.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
case BOOTS -> Type.BOOTS.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+5
-4
@@ -24,6 +24,7 @@ import net.minecraft.world.item.component.ItemAttributeModifiers;
|
|||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class PrimordialArmorItem extends ArmorItem {
|
public class PrimordialArmorItem extends ArmorItem {
|
||||||
|
private static final int BASE_DURABILITY_MULTIPLIER = 33;
|
||||||
private final Type armorType;
|
private final Type armorType;
|
||||||
|
|
||||||
public PrimordialArmorItem(Holder<ArmorMaterial> material, Type type, Properties properties) {
|
public PrimordialArmorItem(Holder<ArmorMaterial> material, Type type, Properties properties) {
|
||||||
@@ -144,10 +145,10 @@ public class PrimordialArmorItem extends ArmorItem {
|
|||||||
|
|
||||||
private static int resolveDurability(Type armorType) {
|
private static int resolveDurability(Type armorType) {
|
||||||
return switch (armorType) {
|
return switch (armorType) {
|
||||||
case HELMET -> Type.HELMET.getDurability(37);
|
case HELMET -> Type.HELMET.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
case CHESTPLATE, BODY -> Type.CHESTPLATE.getDurability(37);
|
case CHESTPLATE, BODY -> Type.CHESTPLATE.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
case LEGGINGS -> Type.LEGGINGS.getDurability(37);
|
case LEGGINGS -> Type.LEGGINGS.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
case BOOTS -> Type.BOOTS.getDurability(37);
|
case BOOTS -> Type.BOOTS.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+16
@@ -1,21 +1,37 @@
|
|||||||
package com.craisinlord.antarchy.content.item;
|
package com.craisinlord.antarchy.content.item;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.TooltipFlag;
|
import net.minecraft.world.item.TooltipFlag;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SpiritAppleItem extends Item {
|
public class SpiritAppleItem extends Item {
|
||||||
|
public static final int GLIMMERING_DURATION_TICKS = 20 * 8;
|
||||||
|
|
||||||
public SpiritAppleItem(Properties properties) {
|
public SpiritAppleItem(Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity livingEntity) {
|
||||||
|
ItemStack result = super.finishUsingItem(stack, level, livingEntity);
|
||||||
|
if (!level.isClientSide()) {
|
||||||
|
livingEntity.addEffect(new MobEffectInstance(AntarchyObjects.GLIMMERING_EFFECT.get(), GLIMMERING_DURATION_TICKS, 0, false, false, true));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||||
tooltipComponents.add(Component.translatable("tooltip.antarchy.spirit_apple").withStyle(ChatFormatting.GRAY));
|
tooltipComponents.add(Component.translatable("tooltip.antarchy.spirit_apple").withStyle(ChatFormatting.GRAY));
|
||||||
|
tooltipComponents.add(Component.translatable("tooltip.antarchy.spirit_apple.eaten").withStyle(ChatFormatting.GRAY));
|
||||||
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package com.craisinlord.antarchy.content.item;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.client.TigerEyeClientHooks;
|
||||||
|
import java.util.List;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.item.ArmorItem;
|
||||||
|
import net.minecraft.world.item.ArmorMaterial;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.TooltipFlag;
|
||||||
|
|
||||||
|
public final class TigerEyeArmorItem extends ArmorItem {
|
||||||
|
private static final int BASE_DURABILITY_MULTIPLIER = 33;
|
||||||
|
|
||||||
|
public TigerEyeArmorItem(Holder<ArmorMaterial> material, Type type, Properties properties) {
|
||||||
|
super(material, type, properties.stacksTo(1).durability(resolveDurability(type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||||
|
tooltipComponents.add(Component.translatable("item.antarchy.tigers_eye_armor.passive").withStyle(ChatFormatting.GOLD));
|
||||||
|
tooltipComponents.add(Component.translatable("item.antarchy.tigers_eye_armor.full_set").withStyle(ChatFormatting.YELLOW));
|
||||||
|
tooltipComponents.add(Component.translatable("item.antarchy.tigers_eye_armor.activate", TigerEyeClientHooks.camouflageKeyText()).withStyle(ChatFormatting.GRAY));
|
||||||
|
tooltipComponents.add(Component.translatable("item.antarchy.tigers_eye_armor.active_bonus").withStyle(ChatFormatting.DARK_AQUA));
|
||||||
|
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int resolveDurability(Type armorType) {
|
||||||
|
return switch (armorType) {
|
||||||
|
case HELMET -> Type.HELMET.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
case CHESTPLATE, BODY -> Type.CHESTPLATE.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
case LEGGINGS -> Type.LEGGINGS.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
case BOOTS -> Type.BOOTS.getDurability(BASE_DURABILITY_MULTIPLIER);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+126
@@ -0,0 +1,126 @@
|
|||||||
|
package com.craisinlord.antarchy.content.item;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.AntarchyTags;
|
||||||
|
import com.craisinlord.antarchy.content.tigereye.TigerEyeCamouflageAccess;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.world.entity.Mob;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.EmptyBlockGetter;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.RenderShape;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
public final class TigerEyeArmorUtil {
|
||||||
|
public static final double DETECTION_REDUCTION_PER_PIECE = 0.10D;
|
||||||
|
public static final double MAX_PASSIVE_REDUCTION = 0.40D;
|
||||||
|
public static final double WALKING_MULTIPLIER = 0.50D;
|
||||||
|
public static final double SPRINTING_MULTIPLIER = 0.25D;
|
||||||
|
public static final double ACTIVE_CAMOUFLAGE_MULTIPLIER = 2.0D;
|
||||||
|
public static final double MAX_ACTIVE_REDUCTION = 0.80D;
|
||||||
|
private static final double STATIONARY_HORIZONTAL_SPEED_SQR = 0.0009D;
|
||||||
|
|
||||||
|
private TigerEyeArmorUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int countEquippedPieces(Player player) {
|
||||||
|
int count = 0;
|
||||||
|
for (EquipmentSlot slot : new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}) {
|
||||||
|
if (player.getItemBySlot(slot).is(AntarchyTags.Items.TIGER_EYE_ARMOR)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasFullSet(Player player) {
|
||||||
|
return player.getItemBySlot(EquipmentSlot.HEAD).is(AntarchyTags.Items.TIGER_EYE_ARMOR)
|
||||||
|
&& player.getItemBySlot(EquipmentSlot.CHEST).is(AntarchyTags.Items.TIGER_EYE_ARMOR)
|
||||||
|
&& player.getItemBySlot(EquipmentSlot.LEGS).is(AntarchyTags.Items.TIGER_EYE_ARMOR)
|
||||||
|
&& player.getItemBySlot(EquipmentSlot.FEET).is(AntarchyTags.Items.TIGER_EYE_ARMOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getPassiveMaximumReduction(Player player) {
|
||||||
|
return Math.min(MAX_PASSIVE_REDUCTION, countEquippedPieces(player) * DETECTION_REDUCTION_PER_PIECE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getMovementMultiplier(Player player) {
|
||||||
|
if (player.isCrouching()) {
|
||||||
|
return 1.0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 delta = player.getDeltaMovement();
|
||||||
|
double horizontalSpeedSqr = delta.x * delta.x + delta.z * delta.z;
|
||||||
|
if (horizontalSpeedSqr < STATIONARY_HORIZONTAL_SPEED_SQR) {
|
||||||
|
return 1.0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isSprinting()) {
|
||||||
|
return SPRINTING_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WALKING_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDetectionReduction(Player player) {
|
||||||
|
double reduction = getPassiveMaximumReduction(player) * getMovementMultiplier(player);
|
||||||
|
if (isAdaptiveCamouflageActive(player)) {
|
||||||
|
reduction = Math.min(MAX_ACTIVE_REDUCTION, reduction * ACTIVE_CAMOUFLAGE_MULTIPLIER);
|
||||||
|
}
|
||||||
|
return reduction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean mayActivateAdaptiveCamouflage(Player player) {
|
||||||
|
return hasFullSet(player) && !player.isSpectator() && player.isAlive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAdaptiveCamouflageActive(Player player) {
|
||||||
|
return player instanceof TigerEyeCamouflageAccess access && access.antarchy$isTigerEyeCamouflageActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValidCamouflageBlock(BlockState state) {
|
||||||
|
if (state.isAir() || state.is(AntarchyTags.Blocks.TIGER_EYE_CAMOUFLAGE_BLACKLIST)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (state.getRenderShape() == RenderShape.INVISIBLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (state.is(Blocks.BARRIER) || state.is(Blocks.STRUCTURE_VOID) || state.is(Blocks.LIGHT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (state.is(Blocks.NETHER_PORTAL) || state.is(Blocks.END_PORTAL) || state.is(Blocks.END_GATEWAY)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Block.isShapeFullBlock(state.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FluidState fluidState = state.getFluidState();
|
||||||
|
return fluidState == null || fluidState.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldReduceDetection(Mob observer, Player player) {
|
||||||
|
if (countEquippedPieces(player) <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (observer.getType().is(AntarchyTags.Entities.TIGER_EYE_DETECTION_IMMUNE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (observer.getTarget() == player || observer.getLastHurtByMob() == player) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (observer instanceof net.minecraft.world.entity.NeutralMob neutralMob && neutralMob.isAngryAt(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return observer.canAttack(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockPos getCamouflageSamplePos(Player player) {
|
||||||
|
double centerX = (player.getBoundingBox().minX + player.getBoundingBox().maxX) * 0.5D;
|
||||||
|
double centerZ = (player.getBoundingBox().minZ + player.getBoundingBox().maxZ) * 0.5D;
|
||||||
|
return BlockPos.containing(centerX, player.getBoundingBox().minY - 0.05D, centerZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.craisinlord.antarchy.content.network;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.Antarchy;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraft.network.codec.ByteBufCodecs;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public record TigerEyeCamouflageStatePayload(int entityId, boolean active, int blockStateId) implements CustomPacketPayload {
|
||||||
|
public static final Type<TigerEyeCamouflageStatePayload> TYPE =
|
||||||
|
new Type<>(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "tiger_eye_camouflage_state"));
|
||||||
|
public static final StreamCodec<ByteBuf, TigerEyeCamouflageStatePayload> STREAM_CODEC = StreamCodec.composite(
|
||||||
|
ByteBufCodecs.VAR_INT, TigerEyeCamouflageStatePayload::entityId,
|
||||||
|
ByteBufCodecs.BOOL, TigerEyeCamouflageStatePayload::active,
|
||||||
|
ByteBufCodecs.VAR_INT, TigerEyeCamouflageStatePayload::blockStateId,
|
||||||
|
TigerEyeCamouflageStatePayload::new
|
||||||
|
);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type<TigerEyeCamouflageStatePayload> type() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.craisinlord.antarchy.content.network;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.Antarchy;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public record ToggleTigerEyeCamouflagePayload() implements CustomPacketPayload {
|
||||||
|
public static final Type<ToggleTigerEyeCamouflagePayload> TYPE =
|
||||||
|
new Type<>(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "toggle_tiger_eye_camouflage"));
|
||||||
|
public static final StreamCodec<ByteBuf, ToggleTigerEyeCamouflagePayload> STREAM_CODEC = StreamCodec.unit(new ToggleTigerEyeCamouflagePayload());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type<ToggleTigerEyeCamouflagePayload> type() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package com.craisinlord.antarchy.content.tigereye;
|
||||||
|
|
||||||
|
public interface TigerEyeCamouflageAccess {
|
||||||
|
boolean antarchy$isTigerEyeCamouflageActive();
|
||||||
|
|
||||||
|
void antarchy$setTigerEyeCamouflageActive(boolean active);
|
||||||
|
|
||||||
|
int antarchy$getTigerEyeCamouflageBlockStateId();
|
||||||
|
|
||||||
|
void antarchy$setTigerEyeCamouflageBlockStateId(int blockStateId);
|
||||||
|
}
|
||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
package com.craisinlord.antarchy.content.tigereye;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.item.TigerEyeArmorUtil;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.particles.BlockParticleOption;
|
||||||
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
public final class TigerEyeCamouflageController {
|
||||||
|
public enum ToggleResult {
|
||||||
|
ACTIVATED,
|
||||||
|
DEACTIVATED,
|
||||||
|
FULL_SET_REQUIRED,
|
||||||
|
INVALID_BLOCK,
|
||||||
|
NO_CHANGE
|
||||||
|
}
|
||||||
|
|
||||||
|
private TigerEyeCamouflageController() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ToggleResult toggle(ServerPlayer player) {
|
||||||
|
if (!(player instanceof TigerEyeCamouflageAccess access)) {
|
||||||
|
return ToggleResult.NO_CHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access.antarchy$isTigerEyeCamouflageActive()) {
|
||||||
|
deactivate(player, true);
|
||||||
|
return ToggleResult.DEACTIVATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TigerEyeArmorUtil.mayActivateAdaptiveCamouflage(player)) {
|
||||||
|
return ToggleResult.FULL_SET_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos samplePos = TigerEyeArmorUtil.getCamouflageSamplePos(player);
|
||||||
|
BlockState state = player.level().getBlockState(samplePos);
|
||||||
|
if (!TigerEyeArmorUtil.isValidCamouflageBlock(state)) {
|
||||||
|
return ToggleResult.INVALID_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
access.antarchy$setTigerEyeCamouflageBlockStateId(Block.getId(state));
|
||||||
|
access.antarchy$setTigerEyeCamouflageActive(true);
|
||||||
|
spawnEffects(player, state, true);
|
||||||
|
return ToggleResult.ACTIVATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean validateOrDeactivate(ServerPlayer player) {
|
||||||
|
if (!(player instanceof TigerEyeCamouflageAccess access) || !access.antarchy$isTigerEyeCamouflageActive()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (TigerEyeArmorUtil.hasFullSet(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
deactivate(player, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deactivate(ServerPlayer player, boolean spawnEffects) {
|
||||||
|
if (!(player instanceof TigerEyeCamouflageAccess access)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean wasActive = access.antarchy$isTigerEyeCamouflageActive();
|
||||||
|
int blockStateId = access.antarchy$getTigerEyeCamouflageBlockStateId();
|
||||||
|
access.antarchy$setTigerEyeCamouflageActive(false);
|
||||||
|
access.antarchy$setTigerEyeCamouflageBlockStateId(0);
|
||||||
|
if (spawnEffects && wasActive) {
|
||||||
|
spawnEffects(player, Block.stateById(blockStateId), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void spawnEffects(ServerPlayer player, BlockState state, boolean activate) {
|
||||||
|
if (!(player.level() instanceof ServerLevel serverLevel)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int count = activate ? 18 : 8;
|
||||||
|
serverLevel.sendParticles(
|
||||||
|
new BlockParticleOption(ParticleTypes.BLOCK, state),
|
||||||
|
player.getX(),
|
||||||
|
player.getY() + 1.0D,
|
||||||
|
player.getZ(),
|
||||||
|
count,
|
||||||
|
0.35D,
|
||||||
|
0.6D,
|
||||||
|
0.35D,
|
||||||
|
0.03D
|
||||||
|
);
|
||||||
|
serverLevel.playSound(
|
||||||
|
null,
|
||||||
|
player.blockPosition(),
|
||||||
|
activate ? SoundEvents.AMETHYST_BLOCK_CHIME : SoundEvents.AMETHYST_BLOCK_HIT,
|
||||||
|
SoundSource.PLAYERS,
|
||||||
|
0.8F,
|
||||||
|
activate ? 0.9F : 0.7F
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package com.craisinlord.antarchy.content.tigereye;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.network.TigerEyeCamouflageStatePayload;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
public final class TigerEyeCamouflageSync {
|
||||||
|
private static BiConsumer<ServerPlayer, TigerEyeCamouflageStatePayload> sendToPlayer = (player, payload) -> {};
|
||||||
|
private static Consumer<ServerPlayer> syncSelfAndTracking = player -> {};
|
||||||
|
|
||||||
|
private TigerEyeCamouflageSync() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendToPlayer(BiConsumer<ServerPlayer, TigerEyeCamouflageStatePayload> sender) {
|
||||||
|
sendToPlayer = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSyncSelfAndTracking(Consumer<ServerPlayer> syncer) {
|
||||||
|
syncSelfAndTracking = syncer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sync(ServerPlayer player) {
|
||||||
|
syncSelfAndTracking.accept(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void syncTo(ServerPlayer viewer, ServerPlayer target) {
|
||||||
|
sendToPlayer.accept(viewer, payload(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TigerEyeCamouflageStatePayload payload(ServerPlayer player) {
|
||||||
|
if (player instanceof TigerEyeCamouflageAccess access) {
|
||||||
|
return new TigerEyeCamouflageStatePayload(
|
||||||
|
player.getId(),
|
||||||
|
access.antarchy$isTigerEyeCamouflageActive(),
|
||||||
|
access.antarchy$getTigerEyeCamouflageBlockStateId()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new TigerEyeCamouflageStatePayload(player.getId(), false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-16
@@ -4,7 +4,7 @@ import com.mojang.serialization.Codec;
|
|||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||||
|
|
||||||
public record ChitenSpikeConfiguration(
|
public record ChitinSpikeConfiguration(
|
||||||
int floorToCeilingSearchRange,
|
int floorToCeilingSearchRange,
|
||||||
int radius,
|
int radius,
|
||||||
int maxColumnHeight,
|
int maxColumnHeight,
|
||||||
@@ -19,19 +19,19 @@ public record ChitenSpikeConfiguration(
|
|||||||
int largeVariantExtraHeightDeviation,
|
int largeVariantExtraHeightDeviation,
|
||||||
float largeVariantSurfaceSpikeMultiplier
|
float largeVariantSurfaceSpikeMultiplier
|
||||||
) implements FeatureConfiguration {
|
) implements FeatureConfiguration {
|
||||||
public static final Codec<ChitenSpikeConfiguration> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
public static final Codec<ChitinSpikeConfiguration> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
Codec.intRange(1, 128).fieldOf("floor_to_ceiling_search_range").forGetter(ChitenSpikeConfiguration::floorToCeilingSearchRange),
|
Codec.intRange(1, 128).fieldOf("floor_to_ceiling_search_range").forGetter(ChitinSpikeConfiguration::floorToCeilingSearchRange),
|
||||||
Codec.intRange(1, 32).fieldOf("radius").forGetter(ChitenSpikeConfiguration::radius),
|
Codec.intRange(1, 32).fieldOf("radius").forGetter(ChitinSpikeConfiguration::radius),
|
||||||
Codec.intRange(1, 32).fieldOf("max_column_height").forGetter(ChitenSpikeConfiguration::maxColumnHeight),
|
Codec.intRange(1, 32).fieldOf("max_column_height").forGetter(ChitinSpikeConfiguration::maxColumnHeight),
|
||||||
Codec.intRange(1, 16).fieldOf("height_deviation").forGetter(ChitenSpikeConfiguration::heightDeviation),
|
Codec.intRange(1, 16).fieldOf("height_deviation").forGetter(ChitinSpikeConfiguration::heightDeviation),
|
||||||
Codec.floatRange(0.0F, 1.0F).fieldOf("chance_of_column_at_max_distance_from_center").forGetter(ChitenSpikeConfiguration::chanceOfColumnAtMaxDistanceFromCenter),
|
Codec.floatRange(0.0F, 1.0F).fieldOf("chance_of_column_at_max_distance_from_center").forGetter(ChitinSpikeConfiguration::chanceOfColumnAtMaxDistanceFromCenter),
|
||||||
Codec.intRange(1, 64).fieldOf("max_distance_from_center_affecting_chance_of_column").forGetter(ChitenSpikeConfiguration::maxDistanceFromCenterAffectingChanceOfColumn),
|
Codec.intRange(1, 64).fieldOf("max_distance_from_center_affecting_chance_of_column").forGetter(ChitinSpikeConfiguration::maxDistanceFromCenterAffectingChanceOfColumn),
|
||||||
Codec.intRange(1, 64).fieldOf("max_distance_from_center_affecting_height_bias").forGetter(ChitenSpikeConfiguration::maxDistanceFromCenterAffectingHeightBias),
|
Codec.intRange(1, 64).fieldOf("max_distance_from_center_affecting_height_bias").forGetter(ChitinSpikeConfiguration::maxDistanceFromCenterAffectingHeightBias),
|
||||||
Codec.intRange(0, 32).fieldOf("max_height_difference").forGetter(ChitenSpikeConfiguration::maxHeightDifference),
|
Codec.intRange(0, 32).fieldOf("max_height_difference").forGetter(ChitinSpikeConfiguration::maxHeightDifference),
|
||||||
Codec.floatRange(0.0F, 1.0F).optionalFieldOf("large_variant_chance", 0.0F).forGetter(ChitenSpikeConfiguration::largeVariantChance),
|
Codec.floatRange(0.0F, 1.0F).optionalFieldOf("large_variant_chance", 0.0F).forGetter(ChitinSpikeConfiguration::largeVariantChance),
|
||||||
Codec.intRange(0, 24).optionalFieldOf("large_variant_extra_radius", 0).forGetter(ChitenSpikeConfiguration::largeVariantExtraRadius),
|
Codec.intRange(0, 24).optionalFieldOf("large_variant_extra_radius", 0).forGetter(ChitinSpikeConfiguration::largeVariantExtraRadius),
|
||||||
Codec.intRange(0, 32).optionalFieldOf("large_variant_extra_height", 0).forGetter(ChitenSpikeConfiguration::largeVariantExtraHeight),
|
Codec.intRange(0, 32).optionalFieldOf("large_variant_extra_height", 0).forGetter(ChitinSpikeConfiguration::largeVariantExtraHeight),
|
||||||
Codec.intRange(0, 16).optionalFieldOf("large_variant_extra_height_deviation", 0).forGetter(ChitenSpikeConfiguration::largeVariantExtraHeightDeviation),
|
Codec.intRange(0, 16).optionalFieldOf("large_variant_extra_height_deviation", 0).forGetter(ChitinSpikeConfiguration::largeVariantExtraHeightDeviation),
|
||||||
Codec.floatRange(1.0F, 8.0F).optionalFieldOf("large_variant_surface_spike_multiplier", 1.0F).forGetter(ChitenSpikeConfiguration::largeVariantSurfaceSpikeMultiplier)
|
Codec.floatRange(1.0F, 8.0F).optionalFieldOf("large_variant_surface_spike_multiplier", 1.0F).forGetter(ChitinSpikeConfiguration::largeVariantSurfaceSpikeMultiplier)
|
||||||
).apply(instance, ChitenSpikeConfiguration::new));
|
).apply(instance, ChitinSpikeConfiguration::new));
|
||||||
}
|
}
|
||||||
+14
-14
@@ -18,19 +18,19 @@ import net.minecraft.world.level.levelgen.Column;
|
|||||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||||
|
|
||||||
public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration> {
|
public final class ChitinSpikeFeature extends Feature<ChitinSpikeConfiguration> {
|
||||||
private record ResolvedVariant(int radius, int maxColumnHeight, int heightDeviation, int surfaceSpikeAttempts) {
|
private record ResolvedVariant(int radius, int maxColumnHeight, int heightDeviation, int surfaceSpikeAttempts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChitenSpikeFeature(Codec<ChitenSpikeConfiguration> codec) {
|
public ChitinSpikeFeature(Codec<ChitinSpikeConfiguration> codec) {
|
||||||
super(codec);
|
super(codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean place(FeaturePlaceContext<ChitenSpikeConfiguration> context) {
|
public boolean place(FeaturePlaceContext<ChitinSpikeConfiguration> context) {
|
||||||
WorldGenLevel level = context.level();
|
WorldGenLevel level = context.level();
|
||||||
BlockPos origin = context.origin();
|
BlockPos origin = context.origin();
|
||||||
ChitenSpikeConfiguration config = context.config();
|
ChitinSpikeConfiguration config = context.config();
|
||||||
RandomSource random = context.random();
|
RandomSource random = context.random();
|
||||||
|
|
||||||
if (!level.getBlockState(origin).isAir()) {
|
if (!level.getBlockState(origin).isAir()) {
|
||||||
@@ -59,7 +59,7 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
return placedAny;
|
return placedAny;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResolvedVariant resolveVariant(ChitenSpikeConfiguration config, RandomSource random) {
|
private ResolvedVariant resolveVariant(ChitinSpikeConfiguration config, RandomSource random) {
|
||||||
if (config.largeVariantChance() > 0.0F && random.nextFloat() < config.largeVariantChance()) {
|
if (config.largeVariantChance() > 0.0F && random.nextFloat() < config.largeVariantChance()) {
|
||||||
int radius = config.radius() + config.largeVariantExtraRadius();
|
int radius = config.radius() + config.largeVariantExtraRadius();
|
||||||
int maxColumnHeight = config.maxColumnHeight() + config.largeVariantExtraHeight();
|
int maxColumnHeight = config.maxColumnHeight() + config.largeVariantExtraHeight();
|
||||||
@@ -81,7 +81,7 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
int dx,
|
int dx,
|
||||||
int dz,
|
int dz,
|
||||||
double chance,
|
double chance,
|
||||||
ChitenSpikeConfiguration config,
|
ChitinSpikeConfiguration config,
|
||||||
ResolvedVariant variant,
|
ResolvedVariant variant,
|
||||||
List<BlockPos> placedBlocks
|
List<BlockPos> placedBlocks
|
||||||
) {
|
) {
|
||||||
@@ -114,10 +114,10 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
|
|
||||||
boolean placedAny = false;
|
boolean placedAny = false;
|
||||||
if (ceiling.isPresent() && downLength > 0) {
|
if (ceiling.isPresent() && downLength > 0) {
|
||||||
placedAny |= this.growChitenColumn(level, pos.atY(ceiling.getAsInt() - 1), Direction.DOWN, downLength, placedBlocks);
|
placedAny |= this.growChitinColumn(level, pos.atY(ceiling.getAsInt() - 1), Direction.DOWN, downLength, placedBlocks);
|
||||||
}
|
}
|
||||||
if (floor.isPresent() && upLength > 0) {
|
if (floor.isPresent() && upLength > 0) {
|
||||||
placedAny |= this.growChitenColumn(level, pos.atY(floor.getAsInt() + 1), Direction.UP, upLength, placedBlocks);
|
placedAny |= this.growChitinColumn(level, pos.atY(floor.getAsInt() + 1), Direction.UP, upLength, placedBlocks);
|
||||||
}
|
}
|
||||||
return placedAny;
|
return placedAny;
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
return variant.maxColumnHeight();
|
return variant.maxColumnHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean growChitenColumn(WorldGenLevel level, BlockPos rootStart, Direction direction, int length, List<BlockPos> placedBlocks) {
|
private boolean growChitinColumn(WorldGenLevel level, BlockPos rootStart, Direction direction, int length, List<BlockPos> placedBlocks) {
|
||||||
boolean placedAny = false;
|
boolean placedAny = false;
|
||||||
for (int offset = 0; offset < length; offset++) {
|
for (int offset = 0; offset < length; offset++) {
|
||||||
BlockPos spikePos = rootStart.relative(direction, offset);
|
BlockPos spikePos = rootStart.relative(direction, offset);
|
||||||
@@ -142,8 +142,8 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockState chitenState = AntarchyObjects.CHITEN_BLOCK.get().defaultBlockState();
|
BlockState chitinState = AntarchyObjects.CHITIN_BLOCK.get().defaultBlockState();
|
||||||
level.setBlock(spikePos, chitenState, 3);
|
level.setBlock(spikePos, chitinState, 3);
|
||||||
placedBlocks.add(spikePos.immutable());
|
placedBlocks.add(spikePos.immutable());
|
||||||
placedAny = true;
|
placedAny = true;
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
WorldGenLevel level,
|
WorldGenLevel level,
|
||||||
RandomSource random,
|
RandomSource random,
|
||||||
List<BlockPos> placedBlocks,
|
List<BlockPos> placedBlocks,
|
||||||
ChitenSpikeConfiguration config,
|
ChitinSpikeConfiguration config,
|
||||||
ResolvedVariant variant
|
ResolvedVariant variant
|
||||||
) {
|
) {
|
||||||
boolean placedAny = false;
|
boolean placedAny = false;
|
||||||
@@ -186,7 +186,7 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockState spikeState = AntarchyObjects.CHITEN_SPIKE.get().defaultBlockState()
|
BlockState spikeState = AntarchyObjects.CHITIN_SPIKE.get().defaultBlockState()
|
||||||
.setValue(PointedDripstoneBlock.TIP_DIRECTION, direction)
|
.setValue(PointedDripstoneBlock.TIP_DIRECTION, direction)
|
||||||
.setValue(PointedDripstoneBlock.THICKNESS, getThicknessForRootOffset(offset, length))
|
.setValue(PointedDripstoneBlock.THICKNESS, getThicknessForRootOffset(offset, length))
|
||||||
.setValue(PointedDripstoneBlock.WATERLOGGED, false);
|
.setValue(PointedDripstoneBlock.WATERLOGGED, false);
|
||||||
@@ -238,7 +238,7 @@ public final class ChitenSpikeFeature extends Feature<ChitenSpikeConfiguration>
|
|||||||
return Mth.clamp(sampled, 1, maxHeight);
|
return Mth.clamp(sampled, 1, maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getChanceOfColumn(int radius, int dx, int dz, ChitenSpikeConfiguration config) {
|
private double getChanceOfColumn(int radius, int dx, int dz, ChitinSpikeConfiguration config) {
|
||||||
int remainingX = radius - Math.abs(dx);
|
int remainingX = radius - Math.abs(dx);
|
||||||
int remainingZ = radius - Math.abs(dz);
|
int remainingZ = radius - Math.abs(dz);
|
||||||
int edgeDistance = Math.min(remainingX, remainingZ);
|
int edgeDistance = Math.min(remainingX, remainingZ);
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.craisinlord.antarchy.mixins;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.item.InnateEnchantmentHelper;
|
||||||
|
import net.minecraft.world.inventory.GrindstoneMenu;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
@Mixin(GrindstoneMenu.class)
|
||||||
|
public abstract class GrindstoneMenuMixin {
|
||||||
|
@Inject(method = "removeNonCursesFrom", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void antarchy$preserveInnateEnchantments(ItemStack stack, CallbackInfoReturnable<ItemStack> cir) {
|
||||||
|
if (InnateEnchantmentHelper.hasInnateNonCurseEnchantments(stack)) {
|
||||||
|
cir.setReturnValue(InnateEnchantmentHelper.stripOnlyRemovableNonCurseEnchantments(stack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "computeResult", at = @At("RETURN"), cancellable = true)
|
||||||
|
private void antarchy$blockInnateOnlyNoOp(ItemStack firstInput, ItemStack secondInput, CallbackInfoReturnable<ItemStack> cir) {
|
||||||
|
if (!firstInput.isEmpty() && secondInput.isEmpty()
|
||||||
|
&& InnateEnchantmentHelper.hasInnateNonCurseEnchantments(firstInput)
|
||||||
|
&& !InnateEnchantmentHelper.hasRemovableNonCurseEnchantments(firstInput)) {
|
||||||
|
cir.setReturnValue(ItemStack.EMPTY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstInput.isEmpty() && !secondInput.isEmpty()
|
||||||
|
&& InnateEnchantmentHelper.hasInnateNonCurseEnchantments(secondInput)
|
||||||
|
&& !InnateEnchantmentHelper.hasRemovableNonCurseEnchantments(secondInput)) {
|
||||||
|
cir.setReturnValue(ItemStack.EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.craisinlord.antarchy.mixins;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.tigereye.TigerEyeCamouflageAccess;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
|
||||||
|
@Mixin(Player.class)
|
||||||
|
public abstract class TigerEyeCamouflageMixin implements TigerEyeCamouflageAccess {
|
||||||
|
@Unique private boolean antarchy$tigerEyeCamouflageActive;
|
||||||
|
@Unique private int antarchy$tigerEyeCamouflageBlockStateId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean antarchy$isTigerEyeCamouflageActive() {
|
||||||
|
return antarchy$tigerEyeCamouflageActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void antarchy$setTigerEyeCamouflageActive(boolean active) {
|
||||||
|
antarchy$tigerEyeCamouflageActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int antarchy$getTigerEyeCamouflageBlockStateId() {
|
||||||
|
return antarchy$tigerEyeCamouflageBlockStateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void antarchy$setTigerEyeCamouflageBlockStateId(int blockStateId) {
|
||||||
|
antarchy$tigerEyeCamouflageBlockStateId = blockStateId;
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package com.craisinlord.antarchy.mixins;
|
||||||
|
|
||||||
|
import com.craisinlord.antarchy.content.item.TigerEyeArmorUtil;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import net.minecraft.world.entity.Mob;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
@Mixin(LivingEntity.class)
|
||||||
|
public abstract class TigerEyeVisibilityMixin {
|
||||||
|
@Inject(method = "getVisibilityPercent", at = @At("RETURN"), cancellable = true)
|
||||||
|
private void antarchy$applyTigerEyeStealth(Entity observer, CallbackInfoReturnable<Double> cir) {
|
||||||
|
if (!((Object) this instanceof Player player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(observer instanceof Mob mob)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!TigerEyeArmorUtil.shouldReduceDetection(mob, player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cir.setReturnValue(cir.getReturnValueD() * (1.0D - TigerEyeArmorUtil.getDetectionReduction(player)));
|
||||||
|
}
|
||||||
|
}
|
||||||
+71
@@ -4,12 +4,17 @@ import com.craisinlord.antarchy.content.fluid.AntarchyFluidChecks;
|
|||||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
|
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
|
||||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
|
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TreeSet;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.MoverType;
|
import net.minecraft.world.entity.MoverType;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -19,6 +24,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
@Mixin(Entity.class)
|
@Mixin(Entity.class)
|
||||||
/*
|
/*
|
||||||
@@ -150,6 +156,71 @@ public abstract class EntityMoveMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "collide", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void antarchy$invertedStepUp(Vec3 movement, CallbackInfoReturnable<Vec3> cir) {
|
||||||
|
Entity entity = (Entity) (Object) this;
|
||||||
|
if (!AntarchyGravityApi.isGravityInverted(entity)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB aabb = entity.getBoundingBox();
|
||||||
|
List<VoxelShape> entityShapes = entity.level().getEntityCollisions(entity, aabb.expandTowards(movement));
|
||||||
|
Vec3 collided = movement.lengthSqr() == 0.0 ? movement : Entity.collideBoundingBox(entity, movement, aabb, entity.level(), entityShapes);
|
||||||
|
|
||||||
|
boolean movedX = movement.x != collided.x;
|
||||||
|
boolean movedY = movement.y != collided.y;
|
||||||
|
boolean movedZ = movement.z != collided.z;
|
||||||
|
boolean pressingIntoCeiling = movedY && movement.y > 0.0D;
|
||||||
|
float maxUpStep = entity.maxUpStep();
|
||||||
|
|
||||||
|
if (!(maxUpStep > 0.0F) || !(pressingIntoCeiling || entity.onGround()) || !(movedX || movedZ)) {
|
||||||
|
cir.setReturnValue(collided);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB steppedBox = pressingIntoCeiling ? aabb.move(0.0, collided.y, 0.0) : aabb;
|
||||||
|
AABB searchBox = steppedBox.expandTowards(movement.x, -(double) maxUpStep, movement.z);
|
||||||
|
if (!pressingIntoCeiling) {
|
||||||
|
searchBox = searchBox.expandTowards(0.0, 1.0E-5D, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<VoxelShape> stepShapes = new ArrayList<>(entityShapes);
|
||||||
|
entity.level().getBlockCollisions(entity, searchBox).forEach(stepShapes::add);
|
||||||
|
|
||||||
|
float currentStepY = (float) collided.y;
|
||||||
|
float[] candidateHeights = antarchy$collectCandidateStepDownHeights(steppedBox, stepShapes, maxUpStep, currentStepY);
|
||||||
|
for (float candidate : candidateHeights) {
|
||||||
|
Vec3 stepped = Entity.collideBoundingBox(entity, new Vec3(movement.x, -(double) candidate, movement.z), steppedBox, entity.level(), stepShapes);
|
||||||
|
if (stepped.horizontalDistanceSqr() > collided.horizontalDistanceSqr()) {
|
||||||
|
double offset = steppedBox.maxY - aabb.maxY;
|
||||||
|
cir.setReturnValue(stepped.add(0.0, offset, 0.0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cir.setReturnValue(collided);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static float[] antarchy$collectCandidateStepDownHeights(AABB box, List<VoxelShape> shapes, float maxStep, float currentY) {
|
||||||
|
TreeSet<Float> heights = new TreeSet<>();
|
||||||
|
for (VoxelShape shape : shapes) {
|
||||||
|
for (double coord : shape.getCoords(Direction.Axis.Y)) {
|
||||||
|
float height = (float) (box.maxY - coord);
|
||||||
|
if (height >= 0.0F && height != currentY && height <= maxStep) {
|
||||||
|
heights.add(height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] result = new float[heights.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (float height : heights) {
|
||||||
|
result[i++] = height;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private boolean antarchy$intersectsAntiwater(Entity entity, AABB box) {
|
private boolean antarchy$intersectsAntiwater(Entity entity, AABB box) {
|
||||||
BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
|
BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
|
||||||
|
|||||||
@@ -21,8 +21,12 @@
|
|||||||
"FlintAndSteelPortalIgnitionMixin",
|
"FlintAndSteelPortalIgnitionMixin",
|
||||||
"FrogSpawnVariantMixin",
|
"FrogSpawnVariantMixin",
|
||||||
"FrogVariantBootstrapMixin",
|
"FrogVariantBootstrapMixin",
|
||||||
|
"GlimmeringDamageImmunityMixin",
|
||||||
|
"GlimmeringPushableMixin",
|
||||||
|
"GlimmeringPushEntitiesMixin",
|
||||||
"GlowSquidLumenSpawnMixin",
|
"GlowSquidLumenSpawnMixin",
|
||||||
"GlowVinesUnderLeavesMixin",
|
"GlowVinesUnderLeavesMixin",
|
||||||
|
"GrindstoneMenuMixin",
|
||||||
"MantisClawWallClimbMixin",
|
"MantisClawWallClimbMixin",
|
||||||
"MilkBucketSizeResetMixin",
|
"MilkBucketSizeResetMixin",
|
||||||
"MinecartItemMixin",
|
"MinecartItemMixin",
|
||||||
@@ -38,6 +42,8 @@
|
|||||||
"SpongeAntiwaterMixin",
|
"SpongeAntiwaterMixin",
|
||||||
"SquidzookaEnchantMixin",
|
"SquidzookaEnchantMixin",
|
||||||
"SquidzookaMultishotMixin",
|
"SquidzookaMultishotMixin",
|
||||||
|
"TigerEyeCamouflageMixin",
|
||||||
|
"TigerEyeVisibilityMixin",
|
||||||
"gravity.AbstractArrowGravityMixin",
|
"gravity.AbstractArrowGravityMixin",
|
||||||
"gravity.BucketItemGravityMixin",
|
"gravity.BucketItemGravityMixin",
|
||||||
"gravity.ChunkMapAccessor",
|
"gravity.ChunkMapAccessor",
|
||||||
@@ -85,8 +91,11 @@
|
|||||||
"client.MountedVehicleCameraMixin",
|
"client.MountedVehicleCameraMixin",
|
||||||
"client.ParalyzedMouseTurnMixin",
|
"client.ParalyzedMouseTurnMixin",
|
||||||
"client.ScreenEffectRendererFireVisualMixin",
|
"client.ScreenEffectRendererFireVisualMixin",
|
||||||
|
"client.GlimmeringTranslucencyMixin",
|
||||||
"client.SplashManagerMixin",
|
"client.SplashManagerMixin",
|
||||||
"client.ThoraxisFogMixin",
|
"client.ThoraxisFogMixin",
|
||||||
|
"client.TigerEyeArmorHideMixin",
|
||||||
|
"client.TigerEyeNameTagHideMixin",
|
||||||
"client.WolfRendererGrimMixin",
|
"client.WolfRendererGrimMixin",
|
||||||
"gravity.client.CameraGravityMixin",
|
"gravity.client.CameraGravityMixin",
|
||||||
"gravity.client.ClientPacketListenerGravityMixin",
|
"gravity.client.ClientPacketListenerGravityMixin",
|
||||||
|
|||||||
+1819
-1274
File diff suppressed because it is too large.
Load diff
+174
-1400
File diff suppressed because it is too large.
Load diff
+7833
-1
File diff suppressed because it is too large.
Load diff
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"variants": {
|
|
||||||
"axis=x": {
|
|
||||||
"model": "antarchy:block/chiten_block",
|
|
||||||
"x": 90,
|
|
||||||
"y": 90
|
|
||||||
},
|
|
||||||
"axis=y": {
|
|
||||||
"model": "antarchy:block/chiten_block"
|
|
||||||
},
|
|
||||||
"axis=z": {
|
|
||||||
"model": "antarchy:block/chiten_block",
|
|
||||||
"x": 90
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"axis=x": {
|
||||||
|
"model": "antarchy:block/chitin_block",
|
||||||
|
"x": 90,
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"axis=y": {
|
||||||
|
"model": "antarchy:block/chitin_block"
|
||||||
|
},
|
||||||
|
"axis=z": {
|
||||||
|
"model": "antarchy:block/chitin_block",
|
||||||
|
"x": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-10
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"variants": {
|
"variants": {
|
||||||
"thickness=base,vertical_direction=down": { "model": "antarchy:block/chiten_spike_down_base" },
|
"thickness=base,vertical_direction=down": { "model": "antarchy:block/chitin_spike_down_base" },
|
||||||
"thickness=base,vertical_direction=up": { "model": "antarchy:block/chiten_spike_up_base" },
|
"thickness=base,vertical_direction=up": { "model": "antarchy:block/chitin_spike_up_base" },
|
||||||
"thickness=frustum,vertical_direction=down": { "model": "antarchy:block/chiten_spike_down_frustum" },
|
"thickness=frustum,vertical_direction=down": { "model": "antarchy:block/chitin_spike_down_frustum" },
|
||||||
"thickness=frustum,vertical_direction=up": { "model": "antarchy:block/chiten_spike_up_frustum" },
|
"thickness=frustum,vertical_direction=up": { "model": "antarchy:block/chitin_spike_up_frustum" },
|
||||||
"thickness=middle,vertical_direction=down": { "model": "antarchy:block/chiten_spike_down_middle" },
|
"thickness=middle,vertical_direction=down": { "model": "antarchy:block/chitin_spike_down_middle" },
|
||||||
"thickness=middle,vertical_direction=up": { "model": "antarchy:block/chiten_spike_up_middle" },
|
"thickness=middle,vertical_direction=up": { "model": "antarchy:block/chitin_spike_up_middle" },
|
||||||
"thickness=tip,vertical_direction=down": { "model": "antarchy:block/chiten_spike_down_tip" },
|
"thickness=tip,vertical_direction=down": { "model": "antarchy:block/chitin_spike_down_tip" },
|
||||||
"thickness=tip,vertical_direction=up": { "model": "antarchy:block/chiten_spike_up_tip" },
|
"thickness=tip,vertical_direction=up": { "model": "antarchy:block/chitin_spike_up_tip" },
|
||||||
"thickness=tip_merge,vertical_direction=down": { "model": "antarchy:block/chiten_spike_down_tip_merge" },
|
"thickness=tip_merge,vertical_direction=down": { "model": "antarchy:block/chitin_spike_down_tip_merge" },
|
||||||
"thickness=tip_merge,vertical_direction=up": { "model": "antarchy:block/chiten_spike_up_tip_merge" }
|
"thickness=tip_merge,vertical_direction=up": { "model": "antarchy:block/chitin_spike_up_tip_merge" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"multipart": [
|
|
||||||
{
|
|
||||||
"when": { "up": "true" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_post" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "north": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side", "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "east": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side", "y": 90, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "south": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side", "y": 180, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "west": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side", "y": 270, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "north": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side_tall", "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "east": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side_tall", "y": 90, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "south": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side_tall", "y": 180, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "west": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_titanium_wall_side_tall", "y": 270, "uvlock": true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"multipart": [
|
|
||||||
{
|
|
||||||
"when": { "up": "true" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_post" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "north": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side", "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "east": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side", "y": 90, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "south": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side", "y": 180, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "west": "low" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side", "y": 270, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "north": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side_tall", "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "east": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side_tall", "y": 90, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "south": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side_tall", "y": 180, "uvlock": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "west": "tall" },
|
|
||||||
"apply": { "model": "antarchy:block/cut_uranium_wall_side_tall", "y": 270, "uvlock": true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"lit=false": {
|
||||||
|
"model": "antarchy:block/lucid_anchor"
|
||||||
|
},
|
||||||
|
"lit=true": {
|
||||||
|
"model": "antarchy:block/lucid_anchor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,6 +105,14 @@
|
|||||||
{"origin": [-3, 30, 56], "size": [6, 7, 21], "uv": [70, 0]}
|
{"origin": [-3, 30, 56], "size": [6, 7, 21], "uv": [70, 0]}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spike",
|
||||||
|
"parent": "torso",
|
||||||
|
"pivot": [0, 39, 2.5],
|
||||||
|
"cubes": [
|
||||||
|
{"origin": [-3.5, 29, -3], "size": [7, 20, 11], "uv": [148, 128]}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "neck",
|
"name": "neck",
|
||||||
"parent": "torso",
|
"parent": "torso",
|
||||||
@@ -113,6 +121,14 @@
|
|||||||
{"origin": [-9, 13, -24], "size": [18, 19, 16], "uv": [0, 42]}
|
{"origin": [-9, 13, -24], "size": [18, 19, 16], "uv": [0, 42]}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spike2",
|
||||||
|
"parent": "neck",
|
||||||
|
"pivot": [0, 30, -14.5],
|
||||||
|
"cubes": [
|
||||||
|
{"origin": [-3.5, 30, -19], "size": [7, 14, 9], "uv": [129, 49]}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "head",
|
"name": "head",
|
||||||
"parent": "neck",
|
"parent": "neck",
|
||||||
@@ -123,11 +139,13 @@
|
|||||||
{"origin": [-8, 22, -42], "size": [16, 5, 19], "uv": [0, 0]},
|
{"origin": [-8, 22, -42], "size": [16, 5, 19], "uv": [0, 0]},
|
||||||
{"origin": [0, 27, -42], "size": [0, 13, 9], "uv": [0, 75]},
|
{"origin": [0, 27, -42], "size": [0, 13, 9], "uv": [0, 75]},
|
||||||
{"origin": [0, 27, -52], "size": [0, 4, 9], "uv": [0, 70]},
|
{"origin": [0, 27, -52], "size": [0, 4, 9], "uv": [0, 70]},
|
||||||
|
{"origin": [-11, 28, -36], "size": [0, 4, 9], "uv": [0, 70]},
|
||||||
|
{"origin": [11, 28, -36], "size": [0, 4, 9], "uv": [0, 70], "mirror": true},
|
||||||
{"origin": [-15, 24, -36], "size": [9, 4, 12], "uv": [0, 202]},
|
{"origin": [-15, 24, -36], "size": [9, 4, 12], "uv": [0, 202]},
|
||||||
{"origin": [6, 24, -36], "size": [9, 4, 12], "uv": [0, 202], "mirror": true},
|
{"origin": [6, 24, -36], "size": [9, 4, 12], "uv": [0, 202], "mirror": true},
|
||||||
{"origin": [-6, 18, -54], "size": [12, 5, 12], "inflate": 0.1, "uv": [68, 179]},
|
{"origin": [-6, 18, -54], "size": [12, 5, 12], "inflate": 0.1, "uv": [68, 179]},
|
||||||
{"origin": [-6, 21, -54], "size": [12, 6, 12], "uv": [0, 24]},
|
{"origin": [-6, 21, -54], "size": [12, 6, 12], "uv": [0, 24]},
|
||||||
{"origin": [-3, 27, -55], "size": [6, 6, 0], "uv": [53, 51]}
|
{"origin": [-3, 27, -53.75], "size": [6, 6, 0], "uv": [53, 51]}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "Stelle eine Gravitationskanone her.",
|
"advancements.antarchy.gravity_gun_craft.description": "Stelle eine Gravitationskanone her.",
|
||||||
"block.antarchy.cavaryn_portal": "Cavaryn-Portal",
|
"block.antarchy.cavaryn_portal": "Cavaryn-Portal",
|
||||||
"block.antarchy.termite_nest": "Termite-Nest",
|
"block.antarchy.termite_nest": "Termite-Nest",
|
||||||
"block.antarchy.chiten_spike": "Chitin-Stachel",
|
"block.antarchy.chitin_spike": "Chitin-Stachel",
|
||||||
"block.antarchy.chiten_block": "Chitin-Block",
|
"block.antarchy.chitin_block": "Chitin-Block",
|
||||||
"block.antarchy.myrmite": "Myrmite",
|
"block.antarchy.myrmite": "Myrmite",
|
||||||
"block.antarchy.broodstone": "Broodstone",
|
"block.antarchy.broodstone": "Broodstone",
|
||||||
"block.antarchy.amber_moss_block": "Bernsteinmoosblock",
|
"block.antarchy.amber_moss_block": "Bernsteinmoosblock",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "Kriechender Schrecken-Spawn-Ei",
|
"item.antarchy.creeping_horror_spawn_egg": "Kriechender Schrecken-Spawn-Ei",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "Lauernder Terror-Spawn-Ei",
|
"item.antarchy.lurking_terror_spawn_egg": "Lauernder Terror-Spawn-Ei",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "Herkuleskäfer-Spawn-Ei",
|
"item.antarchy.hercules_beetle_spawn_egg": "Herkuleskäfer-Spawn-Ei",
|
||||||
"item.antarchy.chiten": "Chitin",
|
"item.antarchy.chitin": "Chitin",
|
||||||
"block.antarchy.polished_broodstone": "Poliert Broodstone",
|
"block.antarchy.polished_broodstone": "Poliert Broodstone",
|
||||||
"block.antarchy.chiseled_broodstone": "Gemeißelt Broodstone",
|
"block.antarchy.chiseled_broodstone": "Gemeißelt Broodstone",
|
||||||
"block.antarchy.broodstone_bricks": "Broodstoneziegel",
|
"block.antarchy.broodstone_bricks": "Broodstoneziegel",
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
"item.antarchy.critter_cage": "Critter Cage",
|
"item.antarchy.critter_cage": "Critter Cage",
|
||||||
"block.antarchy.giant_lily_pad": "Giant Lily Pad",
|
"block.antarchy.giant_lily_pad": "Giant Lily Pad",
|
||||||
"block.antarchy.seashell": "Seashell",
|
"block.antarchy.seashell": "Seashell",
|
||||||
|
"block.antarchy.lucid_anchor": "Lucid Anchor",
|
||||||
"block.antarchy.critter_cage_block": "Critter Cage",
|
"block.antarchy.critter_cage_block": "Critter Cage",
|
||||||
"block.antarchy.hushweed": "Hushweed",
|
"block.antarchy.hushweed": "Hushweed",
|
||||||
"block.antarchy.umbral_moss_block": "Umbral Moss Block",
|
"block.antarchy.umbral_moss_block": "Umbral Moss Block",
|
||||||
@@ -60,6 +61,7 @@
|
|||||||
"block.antarchy.polished_nyxite": "Polished Nyxite",
|
"block.antarchy.polished_nyxite": "Polished Nyxite",
|
||||||
"block.antarchy.chiseled_nyxite": "Chiseled Nyxite",
|
"block.antarchy.chiseled_nyxite": "Chiseled Nyxite",
|
||||||
"block.antarchy.nyxite_bricks": "Nyxite Bricks",
|
"block.antarchy.nyxite_bricks": "Nyxite Bricks",
|
||||||
|
"block.antarchy.nyxite_pillar": "Nyxite Pillar",
|
||||||
"block.antarchy.shellstone": "Shellstone",
|
"block.antarchy.shellstone": "Shellstone",
|
||||||
"block.antarchy.polished_shellstone": "Polished Shellstone",
|
"block.antarchy.polished_shellstone": "Polished Shellstone",
|
||||||
"block.antarchy.shellstone_bricks": "Shellstone Bricks",
|
"block.antarchy.shellstone_bricks": "Shellstone Bricks",
|
||||||
@@ -69,6 +71,7 @@
|
|||||||
"block.antarchy.mossy_shellstone_brick_slab": "Mossy Shellstone Brick Slab",
|
"block.antarchy.mossy_shellstone_brick_slab": "Mossy Shellstone Brick Slab",
|
||||||
"block.antarchy.mossy_shellstone_brick_wall": "Mossy Shellstone Brick Wall",
|
"block.antarchy.mossy_shellstone_brick_wall": "Mossy Shellstone Brick Wall",
|
||||||
"block.antarchy.cracked_shellstone_bricks": "Cracked Shellstone Bricks",
|
"block.antarchy.cracked_shellstone_bricks": "Cracked Shellstone Bricks",
|
||||||
|
"block.antarchy.shellstone_pillar": "Shellstone Pillar",
|
||||||
"block.antarchy.shellstone_stairs": "Shellstone Stairs",
|
"block.antarchy.shellstone_stairs": "Shellstone Stairs",
|
||||||
"block.antarchy.shellstone_slab": "Shellstone Slab",
|
"block.antarchy.shellstone_slab": "Shellstone Slab",
|
||||||
"block.antarchy.shellstone_wall": "Shellstone Wall",
|
"block.antarchy.shellstone_wall": "Shellstone Wall",
|
||||||
@@ -97,12 +100,18 @@
|
|||||||
"block.antarchy.cloud_block": "Cloud Block",
|
"block.antarchy.cloud_block": "Cloud Block",
|
||||||
"block.antarchy.thoraxis_portal": "Thoraxis Portal",
|
"block.antarchy.thoraxis_portal": "Thoraxis Portal",
|
||||||
"block.antarchy.antimetal": "Antimetal",
|
"block.antarchy.antimetal": "Antimetal",
|
||||||
|
"block.antarchy.antimetal_stairs": "Antimetal Stairs",
|
||||||
|
"block.antarchy.antimetal_slab": "Antimetal Slab",
|
||||||
"block.antarchy.polished_antimetal": "Polished Antimetal",
|
"block.antarchy.polished_antimetal": "Polished Antimetal",
|
||||||
|
"block.antarchy.polished_antimetal_stairs": "Polished Antimetal Stairs",
|
||||||
|
"block.antarchy.polished_antimetal_slab": "Polished Antimetal Slab",
|
||||||
"block.antarchy.antimetal_scaffolding": "Antimetal Scaffolding",
|
"block.antarchy.antimetal_scaffolding": "Antimetal Scaffolding",
|
||||||
"block.antarchy.antimetal_rail": "Antimetal Rail",
|
"block.antarchy.antimetal_rail": "Antimetal Rail",
|
||||||
"block.antarchy.antimetal_powered_rail": "Antimetal Powered Rail",
|
"block.antarchy.antimetal_powered_rail": "Antimetal Powered Rail",
|
||||||
"block.antarchy.antimetal_detector_rail": "Antimetal Detector Rail",
|
"block.antarchy.antimetal_detector_rail": "Antimetal Detector Rail",
|
||||||
"block.antarchy.antimetal_activator_rail": "Antimetal Activator Rail",
|
"block.antarchy.antimetal_activator_rail": "Antimetal Activator Rail",
|
||||||
|
"block.antarchy.upper": "Upper",
|
||||||
|
"container.antarchy.upper": "Upper",
|
||||||
"block.antarchy.cornea_stalk": "Cornea Stalk",
|
"block.antarchy.cornea_stalk": "Cornea Stalk",
|
||||||
"block.antarchy.corn_crop": "Corn Crop",
|
"block.antarchy.corn_crop": "Corn Crop",
|
||||||
"block.antarchy.dream_torch": "Dream Torch",
|
"block.antarchy.dream_torch": "Dream Torch",
|
||||||
@@ -118,6 +127,8 @@
|
|||||||
"block.antarchy.large_blood_crystal_bud": "Large Blood Crystal Bud",
|
"block.antarchy.large_blood_crystal_bud": "Large Blood Crystal Bud",
|
||||||
"block.antarchy.blood_crystal_cluster": "Blood Crystal Cluster",
|
"block.antarchy.blood_crystal_cluster": "Blood Crystal Cluster",
|
||||||
"block.antarchy.dream_sand": "Dream Sand",
|
"block.antarchy.dream_sand": "Dream Sand",
|
||||||
|
"block.antarchy.antigravel": "Antigravel",
|
||||||
|
"block.antarchy.loam": "Loam",
|
||||||
"block.antarchy.dream_sandstone": "Dream Sandstone",
|
"block.antarchy.dream_sandstone": "Dream Sandstone",
|
||||||
"block.antarchy.chiseled_dream_sandstone": "Chiseled Dream Sandstone",
|
"block.antarchy.chiseled_dream_sandstone": "Chiseled Dream Sandstone",
|
||||||
"block.antarchy.cut_dream_sandstone": "Cut Dream Sandstone",
|
"block.antarchy.cut_dream_sandstone": "Cut Dream Sandstone",
|
||||||
@@ -142,6 +153,7 @@
|
|||||||
"block.antarchy.bluestone_repeater": "Bluestone Repeater",
|
"block.antarchy.bluestone_repeater": "Bluestone Repeater",
|
||||||
"block.antarchy.bluestone_comparator": "Bluestone Comparator",
|
"block.antarchy.bluestone_comparator": "Bluestone Comparator",
|
||||||
"block.antarchy.bluestone_torch": "Bluestone Torch",
|
"block.antarchy.bluestone_torch": "Bluestone Torch",
|
||||||
|
"block.antarchy.bluestone_lamp": "Bluestone Lamp",
|
||||||
"block.antarchy.uranium_block": "Block of Uranium",
|
"block.antarchy.uranium_block": "Block of Uranium",
|
||||||
"block.antarchy.titanium_block": "Block of Titanium",
|
"block.antarchy.titanium_block": "Block of Titanium",
|
||||||
"block.antarchy.raw_uranium_block": "Block of Raw Uranium",
|
"block.antarchy.raw_uranium_block": "Block of Raw Uranium",
|
||||||
@@ -236,6 +248,7 @@
|
|||||||
"tooltip.antarchy.critter_cage.place": "Shift + click to place",
|
"tooltip.antarchy.critter_cage.place": "Shift + click to place",
|
||||||
"item.antarchy.kraken_tooth": "Kraken Tooth",
|
"item.antarchy.kraken_tooth": "Kraken Tooth",
|
||||||
"item.antarchy.kraken_tentacle": "Kraken Tentacle",
|
"item.antarchy.kraken_tentacle": "Kraken Tentacle",
|
||||||
|
"item.antarchy.kraken_kalamari": "Kraken Calamari",
|
||||||
"item.antarchy.krakens_grasp": "Kraken's Grasp",
|
"item.antarchy.krakens_grasp": "Kraken's Grasp",
|
||||||
"entity.antarchy.tentacle": "Tentacle",
|
"entity.antarchy.tentacle": "Tentacle",
|
||||||
"item.antarchy.basilisk_fang": "Basilisk Fang",
|
"item.antarchy.basilisk_fang": "Basilisk Fang",
|
||||||
@@ -376,7 +389,6 @@
|
|||||||
"key.antarchy.dorrie_charge_jump": "Dorrie Charge Jump",
|
"key.antarchy.dorrie_charge_jump": "Dorrie Charge Jump",
|
||||||
"key.antarchy.hercules_beetle_charge": "Hercules Beetle Charge",
|
"key.antarchy.hercules_beetle_charge": "Hercules Beetle Charge",
|
||||||
"key.antarchy.hercules_beetle_flight_toggle": "Hercules Beetle Flight Toggle",
|
"key.antarchy.hercules_beetle_flight_toggle": "Hercules Beetle Flight Toggle",
|
||||||
"item.antarchy.carapace": "Carapace",
|
|
||||||
"item.antarchy.jumpy_bug_leg": "Jumpy Bug Leg",
|
"item.antarchy.jumpy_bug_leg": "Jumpy Bug Leg",
|
||||||
"item.antarchy.jumpy_boots": "Jumpy Boots",
|
"item.antarchy.jumpy_boots": "Jumpy Boots",
|
||||||
"tooltip.antarchy.jumpy_boots": "Sneak to charge, then jump to spring upward.",
|
"tooltip.antarchy.jumpy_boots": "Sneak to charge, then jump to spring upward.",
|
||||||
@@ -459,6 +471,7 @@
|
|||||||
"item.antarchy.ouranwood_deer_spawn_egg": "Ouranwood Deer Spawn Egg",
|
"item.antarchy.ouranwood_deer_spawn_egg": "Ouranwood Deer Spawn Egg",
|
||||||
"item.antarchy.spirit_apple": "Spirit Apple",
|
"item.antarchy.spirit_apple": "Spirit Apple",
|
||||||
"tooltip.antarchy.spirit_apple": "Tames a Glimmer",
|
"tooltip.antarchy.spirit_apple": "Tames a Glimmer",
|
||||||
|
"tooltip.antarchy.spirit_apple.eaten": "Grants Glimmering when eaten",
|
||||||
"item.antarchy.elka_spawn_egg": "Elka Spawn Egg",
|
"item.antarchy.elka_spawn_egg": "Elka Spawn Egg",
|
||||||
"item.antarchy.glimmer_bottle": "Bottle of Glimmer",
|
"item.antarchy.glimmer_bottle": "Bottle of Glimmer",
|
||||||
"item.antarchy.glimmer_bottle.contains": "Contains: %s",
|
"item.antarchy.glimmer_bottle.contains": "Contains: %s",
|
||||||
@@ -568,6 +581,8 @@
|
|||||||
"effect.antarchy.growth": "Growth",
|
"effect.antarchy.growth": "Growth",
|
||||||
"effect.antarchy.bloodglass_ward": "Bloodglass Ward",
|
"effect.antarchy.bloodglass_ward": "Bloodglass Ward",
|
||||||
"effect.antarchy.bloodglass_ward.description": "Gives hearts that shatter, absorbing an entire hit of damage. They regenerate over time.",
|
"effect.antarchy.bloodglass_ward.description": "Gives hearts that shatter, absorbing an entire hit of damage. They regenerate over time.",
|
||||||
|
"effect.antarchy.glimmering": "Glimmering",
|
||||||
|
"effect.antarchy.glimmering.description": "Passes through entities and attacks unharmed, like a spirit.",
|
||||||
"death.attack.triffid_mauling": "%1$s was mauled to death by a plant",
|
"death.attack.triffid_mauling": "%1$s was mauled to death by a plant",
|
||||||
"death.attack.triffid_mauling.player": "%1$s was mauled to death by a plant",
|
"death.attack.triffid_mauling.player": "%1$s was mauled to death by a plant",
|
||||||
"death.attack.triffid_swallow": "%1$s was swallowed by a triffid",
|
"death.attack.triffid_swallow": "%1$s was swallowed by a triffid",
|
||||||
@@ -606,9 +621,9 @@
|
|||||||
"advancements.antarchy.fallen_kingdom_castle.description": "Discover the Fallen Kingdom Castle.",
|
"advancements.antarchy.fallen_kingdom_castle.description": "Discover the Fallen Kingdom Castle.",
|
||||||
"advancements.antarchy.fallen_king_crown.title": "Chunks would load when I gave the word...",
|
"advancements.antarchy.fallen_king_crown.title": "Chunks would load when I gave the word...",
|
||||||
"advancements.antarchy.fallen_king_crown.description": "Obtain the Fallen King\u0027s Crown.",
|
"advancements.antarchy.fallen_king_crown.description": "Obtain the Fallen King\u0027s Crown.",
|
||||||
"advancements.antarchy.the_lab.title": "Hello Everyone, Dan Here!",
|
"advancements.antarchy.the_lab.title": "Hey everyone, Dan here",
|
||||||
"advancements.antarchy.the_lab.description": "Discover Dr. Trayaurus\u0027 lab.",
|
"advancements.antarchy.the_lab.description": "Discover Dr. Trayaurus\u0027 lab.",
|
||||||
"advancements.antarchy.sweater_dreams.title": "Sweater Dreams",
|
"advancements.antarchy.sweater_dreams.title": "Sweeter Dreams",
|
||||||
"advancements.antarchy.sweater_dreams.description": "Defeat the Nightmare.",
|
"advancements.antarchy.sweater_dreams.description": "Defeat the Nightmare.",
|
||||||
"advancements.antarchy.stone_cold.title": "Stone Cold",
|
"advancements.antarchy.stone_cold.title": "Stone Cold",
|
||||||
"advancements.antarchy.stone_cold.description": "Defeat a Basilisk.",
|
"advancements.antarchy.stone_cold.description": "Defeat a Basilisk.",
|
||||||
@@ -899,15 +914,22 @@
|
|||||||
"advancements.antarchy.rocket_powered_octopus.description": "Craft an R.P.O. Launcher.",
|
"advancements.antarchy.rocket_powered_octopus.description": "Craft an R.P.O. Launcher.",
|
||||||
"advancements.antarchy.gravity_gun_craft.title": "Pick Up Artist",
|
"advancements.antarchy.gravity_gun_craft.title": "Pick Up Artist",
|
||||||
"advancements.antarchy.gravity_gun_craft.description": "Craft a Gravity Gun.",
|
"advancements.antarchy.gravity_gun_craft.description": "Craft a Gravity Gun.",
|
||||||
|
"advancements.antarchy.upper_craft.title": "Uppies?? Uppies!!!",
|
||||||
|
"advancements.antarchy.upper_craft.description": "Craft an Upper.",
|
||||||
|
"advancements.antarchy.mucus_obtained.title": "Gazuntite!",
|
||||||
|
"advancements.antarchy.mucus_obtained.description": "Obtain some Mucus.",
|
||||||
"block.antarchy.cavaryn_portal": "Cavaryn Portal",
|
"block.antarchy.cavaryn_portal": "Cavaryn Portal",
|
||||||
|
"biome.antarchy.cavaryn_moleworm_caves": "Moleworm Caves",
|
||||||
"block.antarchy.termite_nest": "Termite Nest",
|
"block.antarchy.termite_nest": "Termite Nest",
|
||||||
"block.antarchy.chiten_spike": "Chiten Spike",
|
"block.antarchy.chitin_spike": "Chitin Spike",
|
||||||
"block.antarchy.chiten_block": "Chiten Block",
|
"block.antarchy.chitin_block": "Chitin Block",
|
||||||
"block.antarchy.myrmite": "Myrmite",
|
"block.antarchy.myrmite": "Myrmite",
|
||||||
"block.antarchy.broodstone": "Broodstone",
|
"block.antarchy.broodstone": "Broodstone",
|
||||||
"block.antarchy.amber_moss_block": "Amber Moss Block",
|
"block.antarchy.amber_moss_block": "Amber Moss Block",
|
||||||
"block.antarchy.amber_moss_carpet": "Amber Moss Carpet",
|
"block.antarchy.amber_moss_carpet": "Amber Moss Carpet",
|
||||||
"block.antarchy.amber_lichen": "Amber Lichen",
|
"block.antarchy.amber_lichen": "Amber Lichen",
|
||||||
|
"block.antarchy.mucus": "Mucus",
|
||||||
|
"tooltip.antarchy.mucus_slippery": "Makes the block it's on slippery like ice",
|
||||||
"block.antarchy.bile_vein": "Bile Vein",
|
"block.antarchy.bile_vein": "Bile Vein",
|
||||||
"block.antarchy.creepvine": "Creepvine",
|
"block.antarchy.creepvine": "Creepvine",
|
||||||
"block.antarchy.creeping_horror_egg": "Creeping Horror Egg",
|
"block.antarchy.creeping_horror_egg": "Creeping Horror Egg",
|
||||||
@@ -928,7 +950,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "Creeping Horror Spawn Egg",
|
"item.antarchy.creeping_horror_spawn_egg": "Creeping Horror Spawn Egg",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "Lurking Terror Spawn Egg",
|
"item.antarchy.lurking_terror_spawn_egg": "Lurking Terror Spawn Egg",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "Hercules Beetle Spawn Egg",
|
"item.antarchy.hercules_beetle_spawn_egg": "Hercules Beetle Spawn Egg",
|
||||||
"item.antarchy.chiten": "Chiten",
|
"item.antarchy.chitin": "Chitin",
|
||||||
"block.antarchy.polished_broodstone": "Polished Broodstone",
|
"block.antarchy.polished_broodstone": "Polished Broodstone",
|
||||||
"block.antarchy.chiseled_broodstone": "Chiseled Broodstone",
|
"block.antarchy.chiseled_broodstone": "Chiseled Broodstone",
|
||||||
"block.antarchy.broodstone_bricks": "Broodstone Bricks",
|
"block.antarchy.broodstone_bricks": "Broodstone Bricks",
|
||||||
@@ -941,6 +963,7 @@
|
|||||||
"block.antarchy.broodstone_brick_stairs": "Broodstone Brick Stairs",
|
"block.antarchy.broodstone_brick_stairs": "Broodstone Brick Stairs",
|
||||||
"block.antarchy.broodstone_brick_slab": "Broodstone Brick Slab",
|
"block.antarchy.broodstone_brick_slab": "Broodstone Brick Slab",
|
||||||
"block.antarchy.broodstone_brick_wall": "Broodstone Brick Wall",
|
"block.antarchy.broodstone_brick_wall": "Broodstone Brick Wall",
|
||||||
|
"block.antarchy.broodstone_pillar": "Broodstone Pillar",
|
||||||
"block.antarchy.myrmite_coal_ore": "Myrmite Coal Ore",
|
"block.antarchy.myrmite_coal_ore": "Myrmite Coal Ore",
|
||||||
"block.antarchy.broodstone_uranium_ore": "Broodstone Uranium Ore",
|
"block.antarchy.broodstone_uranium_ore": "Broodstone Uranium Ore",
|
||||||
"block.antarchy.broodstone_titanium_ore": "Broodstone Titanium Ore",
|
"block.antarchy.broodstone_titanium_ore": "Broodstone Titanium Ore",
|
||||||
@@ -1001,5 +1024,26 @@
|
|||||||
"advancements.antarchy.beetle_buddies.title": "Beetle Buddies",
|
"advancements.antarchy.beetle_buddies.title": "Beetle Buddies",
|
||||||
"advancements.antarchy.beetle_buddies.description": "Tame a Hercules Beetle.",
|
"advancements.antarchy.beetle_buddies.description": "Tame a Hercules Beetle.",
|
||||||
"advancements.antarchy.herculean_task.title": "Herculean Task",
|
"advancements.antarchy.herculean_task.title": "Herculean Task",
|
||||||
"advancements.antarchy.herculean_task.description": "Slay a Hercules Beetle."
|
"advancements.antarchy.herculean_task.description": "Slay a Hercules Beetle.",
|
||||||
|
"item.antarchy.tigers_eye": "Tiger's Eye",
|
||||||
|
"item.antarchy.tigers_eye_helmet": "Tiger's Eye Helmet",
|
||||||
|
"item.antarchy.tigers_eye_chestplate": "Tiger's Eye Chestplate",
|
||||||
|
"item.antarchy.tigers_eye_leggings": "Tiger's Eye Leggings",
|
||||||
|
"item.antarchy.tigers_eye_boots": "Tiger's Eye Boots",
|
||||||
|
"trim_material.antarchy.tigers_eye": "Tiger's Eye",
|
||||||
|
"item.antarchy.tigers_eye_armor.passive": "Up to 10% detection reduction",
|
||||||
|
"item.antarchy.tigers_eye_armor.full_set": "Full Set: Adaptive Camouflage",
|
||||||
|
"item.antarchy.tigers_eye_armor.activate": "Press %s to mimic the block beneath you",
|
||||||
|
"item.antarchy.tigers_eye_armor.active_bonus": "Doubles detection reduction while active",
|
||||||
|
"key.antarchy.tigers_eye_camouflage": "Adaptive Camouflage",
|
||||||
|
"message.antarchy.tiger_eye_camouflage.activated": "Adaptive Camouflage activated",
|
||||||
|
"message.antarchy.tiger_eye_camouflage.disabled": "Adaptive Camouflage disabled",
|
||||||
|
"message.antarchy.tiger_eye_camouflage.full_set_required": "A full set of Tiger's Eye armor is required",
|
||||||
|
"message.antarchy.tiger_eye_camouflage.invalid_block": "There is no suitable block beneath you",
|
||||||
|
"music.antarchy.lucid_lullaby": "Lucid Lullaby",
|
||||||
|
"music.antarchy.lucid_lullaby.credit": "hewo_",
|
||||||
|
"music.antarchy.venenatus": "Venenatus",
|
||||||
|
"music.antarchy.venenatus.credit": "hewo_",
|
||||||
|
"tooltip.antarchy.lucid_anchor.pyramid": "Requires an Antimetal Beacon pyramid above it",
|
||||||
|
"tooltip.antarchy.lucid_anchor.path": "Projects Inverted downward while it has an unobstructed path to the world below"
|
||||||
}
|
}
|
||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "Fabrica una pistola gravitatoria.",
|
"advancements.antarchy.gravity_gun_craft.description": "Fabrica una pistola gravitatoria.",
|
||||||
"block.antarchy.cavaryn_portal": "Portal de Cavaryn",
|
"block.antarchy.cavaryn_portal": "Portal de Cavaryn",
|
||||||
"block.antarchy.termite_nest": "Nido de Termita",
|
"block.antarchy.termite_nest": "Nido de Termita",
|
||||||
"block.antarchy.chiten_spike": "Púa de Quitina",
|
"block.antarchy.chitin_spike": "Púa de Quitina",
|
||||||
"block.antarchy.chiten_block": "Bloque de Quitina",
|
"block.antarchy.chitin_block": "Bloque de Quitina",
|
||||||
"block.antarchy.myrmite": "Myrmite",
|
"block.antarchy.myrmite": "Myrmite",
|
||||||
"block.antarchy.broodstone": "Broodstone",
|
"block.antarchy.broodstone": "Broodstone",
|
||||||
"block.antarchy.amber_moss_block": "Bloque de musgo ámbar",
|
"block.antarchy.amber_moss_block": "Bloque de musgo ámbar",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "Huevo generador de Horror rastrero",
|
"item.antarchy.creeping_horror_spawn_egg": "Huevo generador de Horror rastrero",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "Huevo generador de Terror acechante",
|
"item.antarchy.lurking_terror_spawn_egg": "Huevo generador de Terror acechante",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "Huevo generador de Escarabajo hércules",
|
"item.antarchy.hercules_beetle_spawn_egg": "Huevo generador de Escarabajo hércules",
|
||||||
"item.antarchy.chiten": "Quitina",
|
"item.antarchy.chitin": "Quitina",
|
||||||
"block.antarchy.polished_broodstone": "Broodstone pulido",
|
"block.antarchy.polished_broodstone": "Broodstone pulido",
|
||||||
"block.antarchy.chiseled_broodstone": "Broodstone cincelado",
|
"block.antarchy.chiseled_broodstone": "Broodstone cincelado",
|
||||||
"block.antarchy.broodstone_bricks": "Ladrillos de Broodstone",
|
"block.antarchy.broodstone_bricks": "Ladrillos de Broodstone",
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "Fabriquez un canon à gravité.",
|
"advancements.antarchy.gravity_gun_craft.description": "Fabriquez un canon à gravité.",
|
||||||
"block.antarchy.cavaryn_portal": "Portail de Cavaryn",
|
"block.antarchy.cavaryn_portal": "Portail de Cavaryn",
|
||||||
"block.antarchy.termite_nest": "Nid de Termite",
|
"block.antarchy.termite_nest": "Nid de Termite",
|
||||||
"block.antarchy.chiten_spike": "Pointe de Chitine",
|
"block.antarchy.chitin_spike": "Pointe de Chitine",
|
||||||
"block.antarchy.chiten_block": "Bloc de Chitine",
|
"block.antarchy.chitin_block": "Bloc de Chitine",
|
||||||
"block.antarchy.myrmite": "Myrmite",
|
"block.antarchy.myrmite": "Myrmite",
|
||||||
"block.antarchy.broodstone": "Broodstone",
|
"block.antarchy.broodstone": "Broodstone",
|
||||||
"block.antarchy.amber_moss_block": "Bloc de mousse ambrée",
|
"block.antarchy.amber_moss_block": "Bloc de mousse ambrée",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "Œuf d’apparition de Horreur rampante",
|
"item.antarchy.creeping_horror_spawn_egg": "Œuf d’apparition de Horreur rampante",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "Œuf d’apparition de Terreur tapie",
|
"item.antarchy.lurking_terror_spawn_egg": "Œuf d’apparition de Terreur tapie",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "Œuf d’apparition de Scarabée Hercule",
|
"item.antarchy.hercules_beetle_spawn_egg": "Œuf d’apparition de Scarabée Hercule",
|
||||||
"item.antarchy.chiten": "Chitine",
|
"item.antarchy.chitin": "Chitine",
|
||||||
"block.antarchy.polished_broodstone": "Broodstone poli",
|
"block.antarchy.polished_broodstone": "Broodstone poli",
|
||||||
"block.antarchy.chiseled_broodstone": "Broodstone ciselé",
|
"block.antarchy.chiseled_broodstone": "Broodstone ciselé",
|
||||||
"block.antarchy.broodstone_bricks": "Briques de Broodstone",
|
"block.antarchy.broodstone_bricks": "Briques de Broodstone",
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "Fabbrica un Cannone gravitazionale.",
|
"advancements.antarchy.gravity_gun_craft.description": "Fabbrica un Cannone gravitazionale.",
|
||||||
"block.antarchy.cavaryn_portal": "Portale per Cavaryn",
|
"block.antarchy.cavaryn_portal": "Portale per Cavaryn",
|
||||||
"block.antarchy.termite_nest": "Nido di Termite",
|
"block.antarchy.termite_nest": "Nido di Termite",
|
||||||
"block.antarchy.chiten_spike": "Spuntone di Chiten",
|
"block.antarchy.chitin_spike": "Spuntone di Chiten",
|
||||||
"block.antarchy.chiten_block": "Blocco di Chiten",
|
"block.antarchy.chitin_block": "Blocco di Chiten",
|
||||||
"block.antarchy.myrmite": "Myrmite",
|
"block.antarchy.myrmite": "Myrmite",
|
||||||
"block.antarchy.broodstone": "Broodstone",
|
"block.antarchy.broodstone": "Broodstone",
|
||||||
"block.antarchy.amber_moss_block": "Blocco di muschio ambrato",
|
"block.antarchy.amber_moss_block": "Blocco di muschio ambrato",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "Uovo generatore di Orrore strisciante",
|
"item.antarchy.creeping_horror_spawn_egg": "Uovo generatore di Orrore strisciante",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "Uovo generatore di Terrore in agguato",
|
"item.antarchy.lurking_terror_spawn_egg": "Uovo generatore di Terrore in agguato",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "Uovo generatore di Scarabeo Ercole",
|
"item.antarchy.hercules_beetle_spawn_egg": "Uovo generatore di Scarabeo Ercole",
|
||||||
"item.antarchy.chiten": "Chiten",
|
"item.antarchy.chitin": "Chiten",
|
||||||
"block.antarchy.polished_broodstone": "Broodstone levigato",
|
"block.antarchy.polished_broodstone": "Broodstone levigato",
|
||||||
"block.antarchy.chiseled_broodstone": "Broodstone cesellato",
|
"block.antarchy.chiseled_broodstone": "Broodstone cesellato",
|
||||||
"block.antarchy.broodstone_bricks": "Mattoni di Broodstone",
|
"block.antarchy.broodstone_bricks": "Mattoni di Broodstone",
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "重力銃をクラフトする。",
|
"advancements.antarchy.gravity_gun_craft.description": "重力銃をクラフトする。",
|
||||||
"block.antarchy.cavaryn_portal": "カヴァリンのポータル",
|
"block.antarchy.cavaryn_portal": "カヴァリンのポータル",
|
||||||
"block.antarchy.termite_nest": "シロアリの巣",
|
"block.antarchy.termite_nest": "シロアリの巣",
|
||||||
"block.antarchy.chiten_spike": "キチンのトゲ",
|
"block.antarchy.chitin_spike": "キチンのトゲ",
|
||||||
"block.antarchy.chiten_block": "キチンのブロック",
|
"block.antarchy.chitin_block": "キチンのブロック",
|
||||||
"block.antarchy.myrmite": "ミルマイト",
|
"block.antarchy.myrmite": "ミルマイト",
|
||||||
"block.antarchy.broodstone": "ブルードストーン",
|
"block.antarchy.broodstone": "ブルードストーン",
|
||||||
"block.antarchy.amber_moss_block": "琥珀色の苔ブロック",
|
"block.antarchy.amber_moss_block": "琥珀色の苔ブロック",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "這い寄る恐怖のスポーンエッグ",
|
"item.antarchy.creeping_horror_spawn_egg": "這い寄る恐怖のスポーンエッグ",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "潜む恐怖のスポーンエッグ",
|
"item.antarchy.lurking_terror_spawn_egg": "潜む恐怖のスポーンエッグ",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "ヘラクレスオオカブトのスポーンエッグ",
|
"item.antarchy.hercules_beetle_spawn_egg": "ヘラクレスオオカブトのスポーンエッグ",
|
||||||
"item.antarchy.chiten": "キチン",
|
"item.antarchy.chitin": "キチン",
|
||||||
"block.antarchy.polished_broodstone": "磨かれたブルードストーン",
|
"block.antarchy.polished_broodstone": "磨かれたブルードストーン",
|
||||||
"block.antarchy.chiseled_broodstone": "模様入りのブルードストーン",
|
"block.antarchy.chiseled_broodstone": "模様入りのブルードストーン",
|
||||||
"block.antarchy.broodstone_bricks": "ブルードストーンレンガ",
|
"block.antarchy.broodstone_bricks": "ブルードストーンレンガ",
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "중력총을 제작하세요.",
|
"advancements.antarchy.gravity_gun_craft.description": "중력총을 제작하세요.",
|
||||||
"block.antarchy.cavaryn_portal": "카바린 차원문",
|
"block.antarchy.cavaryn_portal": "카바린 차원문",
|
||||||
"block.antarchy.termite_nest": "흰개미 둥지",
|
"block.antarchy.termite_nest": "흰개미 둥지",
|
||||||
"block.antarchy.chiten_spike": "치텐 가시",
|
"block.antarchy.chitin_spike": "치텐 가시",
|
||||||
"block.antarchy.chiten_block": "치텐 블록",
|
"block.antarchy.chitin_block": "치텐 블록",
|
||||||
"block.antarchy.myrmite": "미르마이트",
|
"block.antarchy.myrmite": "미르마이트",
|
||||||
"block.antarchy.broodstone": "브루드스톤",
|
"block.antarchy.broodstone": "브루드스톤",
|
||||||
"block.antarchy.amber_moss_block": "호박색 이끼 블록",
|
"block.antarchy.amber_moss_block": "호박색 이끼 블록",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "기어오는 공포 생성 알",
|
"item.antarchy.creeping_horror_spawn_egg": "기어오는 공포 생성 알",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "도사린 공포 생성 알",
|
"item.antarchy.lurking_terror_spawn_egg": "도사린 공포 생성 알",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "헤라클레스장수풍뎅이 생성 알",
|
"item.antarchy.hercules_beetle_spawn_egg": "헤라클레스장수풍뎅이 생성 알",
|
||||||
"item.antarchy.chiten": "치텐",
|
"item.antarchy.chitin": "치텐",
|
||||||
"block.antarchy.polished_broodstone": "윤나는 브루드스톤",
|
"block.antarchy.polished_broodstone": "윤나는 브루드스톤",
|
||||||
"block.antarchy.chiseled_broodstone": "조각된 브루드스톤",
|
"block.antarchy.chiseled_broodstone": "조각된 브루드스톤",
|
||||||
"block.antarchy.broodstone_bricks": "브루드스톤 벽돌",
|
"block.antarchy.broodstone_bricks": "브루드스톤 벽돌",
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "Fabrique uma arma gravitacional.",
|
"advancements.antarchy.gravity_gun_craft.description": "Fabrique uma arma gravitacional.",
|
||||||
"block.antarchy.cavaryn_portal": "Portal de Cavaryn",
|
"block.antarchy.cavaryn_portal": "Portal de Cavaryn",
|
||||||
"block.antarchy.termite_nest": "Ninho de Cupim",
|
"block.antarchy.termite_nest": "Ninho de Cupim",
|
||||||
"block.antarchy.chiten_spike": "Espinho de Quitina",
|
"block.antarchy.chitin_spike": "Espinho de Quitina",
|
||||||
"block.antarchy.chiten_block": "Bloco de Quitina",
|
"block.antarchy.chitin_block": "Bloco de Quitina",
|
||||||
"block.antarchy.myrmite": "Myrmite",
|
"block.antarchy.myrmite": "Myrmite",
|
||||||
"block.antarchy.broodstone": "Broodstone",
|
"block.antarchy.broodstone": "Broodstone",
|
||||||
"block.antarchy.amber_moss_block": "Bloco de Musgo Âmbar",
|
"block.antarchy.amber_moss_block": "Bloco de Musgo Âmbar",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "Ovo Gerador de Horror Rastejante",
|
"item.antarchy.creeping_horror_spawn_egg": "Ovo Gerador de Horror Rastejante",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "Ovo Gerador de Terror à Espreita",
|
"item.antarchy.lurking_terror_spawn_egg": "Ovo Gerador de Terror à Espreita",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "Ovo Gerador de Besouro-hércules",
|
"item.antarchy.hercules_beetle_spawn_egg": "Ovo Gerador de Besouro-hércules",
|
||||||
"item.antarchy.chiten": "Quitina",
|
"item.antarchy.chitin": "Quitina",
|
||||||
"block.antarchy.polished_broodstone": "Broodstone polido",
|
"block.antarchy.polished_broodstone": "Broodstone polido",
|
||||||
"block.antarchy.chiseled_broodstone": "Broodstone talhado",
|
"block.antarchy.chiseled_broodstone": "Broodstone talhado",
|
||||||
"block.antarchy.broodstone_bricks": "Tijolos de Broodstone",
|
"block.antarchy.broodstone_bricks": "Tijolos de Broodstone",
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "合成重力枪。",
|
"advancements.antarchy.gravity_gun_craft.description": "合成重力枪。",
|
||||||
"block.antarchy.cavaryn_portal": "卡瓦林传送门",
|
"block.antarchy.cavaryn_portal": "卡瓦林传送门",
|
||||||
"block.antarchy.termite_nest": "白蚁巢",
|
"block.antarchy.termite_nest": "白蚁巢",
|
||||||
"block.antarchy.chiten_spike": "甲壳素尖刺",
|
"block.antarchy.chitin_spike": "甲壳素尖刺",
|
||||||
"block.antarchy.chiten_block": "甲壳素块",
|
"block.antarchy.chitin_block": "甲壳素块",
|
||||||
"block.antarchy.myrmite": "米尔迈特",
|
"block.antarchy.myrmite": "米尔迈特",
|
||||||
"block.antarchy.broodstone": "布鲁德斯通",
|
"block.antarchy.broodstone": "布鲁德斯通",
|
||||||
"block.antarchy.amber_moss_block": "琥珀苔藓块",
|
"block.antarchy.amber_moss_block": "琥珀苔藓块",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "爬行恐魔刷怪蛋",
|
"item.antarchy.creeping_horror_spawn_egg": "爬行恐魔刷怪蛋",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "潜伏恐魔刷怪蛋",
|
"item.antarchy.lurking_terror_spawn_egg": "潜伏恐魔刷怪蛋",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "赫拉克勒斯甲虫刷怪蛋",
|
"item.antarchy.hercules_beetle_spawn_egg": "赫拉克勒斯甲虫刷怪蛋",
|
||||||
"item.antarchy.chiten": "甲壳素",
|
"item.antarchy.chitin": "甲壳素",
|
||||||
"block.antarchy.polished_broodstone": "磨制布鲁德斯通",
|
"block.antarchy.polished_broodstone": "磨制布鲁德斯通",
|
||||||
"block.antarchy.chiseled_broodstone": "雕纹布鲁德斯通",
|
"block.antarchy.chiseled_broodstone": "雕纹布鲁德斯通",
|
||||||
"block.antarchy.broodstone_bricks": "布鲁德斯通砖块",
|
"block.antarchy.broodstone_bricks": "布鲁德斯通砖块",
|
||||||
|
|||||||
@@ -869,8 +869,8 @@
|
|||||||
"advancements.antarchy.gravity_gun_craft.description": "合成重力槍。",
|
"advancements.antarchy.gravity_gun_craft.description": "合成重力槍。",
|
||||||
"block.antarchy.cavaryn_portal": "卡瓦林傳送門",
|
"block.antarchy.cavaryn_portal": "卡瓦林傳送門",
|
||||||
"block.antarchy.termite_nest": "白蟻巢",
|
"block.antarchy.termite_nest": "白蟻巢",
|
||||||
"block.antarchy.chiten_spike": "甲殼素尖刺",
|
"block.antarchy.chitin_spike": "甲殼素尖刺",
|
||||||
"block.antarchy.chiten_block": "甲殼素塊",
|
"block.antarchy.chitin_block": "甲殼素塊",
|
||||||
"block.antarchy.myrmite": "米爾邁特",
|
"block.antarchy.myrmite": "米爾邁特",
|
||||||
"block.antarchy.broodstone": "布魯德斯通",
|
"block.antarchy.broodstone": "布魯德斯通",
|
||||||
"block.antarchy.amber_moss_block": "琥珀苔蘚塊",
|
"block.antarchy.amber_moss_block": "琥珀苔蘚塊",
|
||||||
@@ -896,7 +896,7 @@
|
|||||||
"item.antarchy.creeping_horror_spawn_egg": "爬行恐魔刷怪蛋",
|
"item.antarchy.creeping_horror_spawn_egg": "爬行恐魔刷怪蛋",
|
||||||
"item.antarchy.lurking_terror_spawn_egg": "潛伏恐魔刷怪蛋",
|
"item.antarchy.lurking_terror_spawn_egg": "潛伏恐魔刷怪蛋",
|
||||||
"item.antarchy.hercules_beetle_spawn_egg": "赫拉克勒斯甲蟲刷怪蛋",
|
"item.antarchy.hercules_beetle_spawn_egg": "赫拉克勒斯甲蟲刷怪蛋",
|
||||||
"item.antarchy.chiten": "甲殼素",
|
"item.antarchy.chitin": "甲殼素",
|
||||||
"block.antarchy.polished_broodstone": "磨製布魯德斯通",
|
"block.antarchy.polished_broodstone": "磨製布魯德斯通",
|
||||||
"block.antarchy.chiseled_broodstone": "雕紋布魯德斯通",
|
"block.antarchy.chiseled_broodstone": "雕紋布魯德斯通",
|
||||||
"block.antarchy.broodstone_bricks": "布魯德斯通磚塊",
|
"block.antarchy.broodstone_bricks": "布魯德斯通磚塊",
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"parent": "minecraft:block/cube_column",
|
|
||||||
"textures": {
|
|
||||||
"end": "antarchy:block/chiten_block",
|
|
||||||
"side": "antarchy:block/chiten_block"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cube_column",
|
||||||
|
"textures": {
|
||||||
|
"end": "antarchy:block/chitin_block",
|
||||||
|
"side": "antarchy:block/chitin_block"
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"parent": "minecraft:block/pointed_dripstone",
|
"parent": "minecraft:block/pointed_dripstone",
|
||||||
"textures": {
|
"textures": {
|
||||||
"cross": "antarchy:block/chiten_spike/chiten_spike_down_base"
|
"cross": "antarchy:block/chitin_spike/chitin_spike_down_base"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"parent": "minecraft:block/pointed_dripstone",
|
"parent": "minecraft:block/pointed_dripstone",
|
||||||
"textures": {
|
"textures": {
|
||||||
"cross": "antarchy:block/chiten_spike/chiten_spike_down_frustum"
|
"cross": "antarchy:block/chitin_spike/chitin_spike_down_frustum"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"parent": "minecraft:block/pointed_dripstone",
|
"parent": "minecraft:block/pointed_dripstone",
|
||||||
"textures": {
|
"textures": {
|
||||||
"cross": "antarchy:block/chiten_spike/chiten_spike_down_middle"
|
"cross": "antarchy:block/chitin_spike/chitin_spike_down_middle"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loaded 100 of 264 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user