diff --git a/src/main/java/com/legobmw99/allomancy/Allomancy.java b/src/main/java/com/legobmw99/allomancy/Allomancy.java index df79f588..7a6125cd 100644 --- a/src/main/java/com/legobmw99/allomancy/Allomancy.java +++ b/src/main/java/com/legobmw99/allomancy/Allomancy.java @@ -8,15 +8,14 @@ import com.legobmw99.allomancy.modules.powers.PowersSetup; import com.legobmw99.allomancy.modules.powers.client.PowersClientSetup; import com.legobmw99.allomancy.modules.powers.client.gui.MetalOverlay; +import com.legobmw99.allomancy.modules.powers.client.util.Inputs; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; -import com.legobmw99.allomancy.network.Network; +import com.legobmw99.allomancy.modules.powers.network.Network; import com.legobmw99.allomancy.util.AllomancyConfig; import com.legobmw99.allomancy.util.ItemDisplay; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.common.Mod; -import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.common.NeoForge; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -32,44 +31,34 @@ public class Allomancy { public Allomancy(IEventBus bus, Dist dist) { - // Register our setup events on the necessary buses - bus.addListener(Allomancy::init); - bus.addListener(Allomancy::clientInit); - bus.addListener(AllomancyConfig::onLoad); - bus.addListener(AllomancyConfig::onReload); - bus.addListener(CombatClientSetup::registerEntityRenders); - bus.addListener(ItemDisplay::addTabContents); - bus.addListener(Network::registerPayloads); - - bus.addListener(MetalOverlay::registerGUI); - if (dist.isClient()) { - bus.addListener(PowersClientSetup::registerKeyBinding); - bus.addListener(PowersClientSetup::registerParticle); PowersClientSetup.register(bus); - } + bus.addListener(PowersClientSetup::clientInit); + bus.addListener(PowersClientSetup::registerParticle); - NeoForge.EVENT_BUS.addListener(PowersSetup::registerCommands); + bus.addListener(MetalOverlay::registerGUI); + bus.addListener(Inputs::registerKeyBinding); + } - // Register all Registries AllomancerAttachment.register(bus); - PowersSetup.register(bus); + bus.addListener(PowersSetup::init); + bus.addListener(Network::registerPayloads); + + ExtrasSetup.register(bus); + NeoForge.EVENT_BUS.addListener(ExtrasSetup::registerCommands); + CombatSetup.register(bus); + bus.addListener(CombatClientSetup::registerEntityRenders); + ConsumeSetup.register(bus); MaterialsSetup.register(bus); - ExtrasSetup.register(bus); + ItemDisplay.register(bus); + bus.addListener(ItemDisplay::addTabContents); AllomancyConfig.register(); + bus.addListener(AllomancyConfig::onLoad); + bus.addListener(AllomancyConfig::onReload); } - - public static void clientInit(final FMLClientSetupEvent e) { - PowersSetup.clientInit(e); - } - - public static void init(final FMLCommonSetupEvent e) { - PowersSetup.init(e); - } - } diff --git a/src/main/java/com/legobmw99/allomancy/modules/combat/item/CoinBagItem.java b/src/main/java/com/legobmw99/allomancy/modules/combat/item/CoinBagItem.java index 0823ddad..a9ea28dd 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/combat/item/CoinBagItem.java +++ b/src/main/java/com/legobmw99/allomancy/modules/combat/item/CoinBagItem.java @@ -2,8 +2,8 @@ import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.combat.entity.ProjectileNuggetEntity; -import com.legobmw99.allomancy.modules.powers.PowerUtils; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; +import com.legobmw99.allomancy.modules.powers.util.Physical; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -20,7 +20,7 @@ public class CoinBagItem extends ProjectileWeaponItem { public static final Predicate NUGGETS = (stack) -> { Item item = stack.getItem(); - return PowerUtils.doesResourceContainsMetal(BuiltInRegistries.ITEM.getKey(item)) && BuiltInRegistries.ITEM.getKey(item).getPath().contains("nugget"); + return Physical.doesResourceContainMetal(BuiltInRegistries.ITEM.getKey(item)) && BuiltInRegistries.ITEM.getKey(item).getPath().contains("nugget"); }; public CoinBagItem() { diff --git a/src/main/java/com/legobmw99/allomancy/modules/extras/ExtrasSetup.java b/src/main/java/com/legobmw99/allomancy/modules/extras/ExtrasSetup.java index f6a05e6d..b5be3d75 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/extras/ExtrasSetup.java +++ b/src/main/java/com/legobmw99/allomancy/modules/extras/ExtrasSetup.java @@ -7,7 +7,12 @@ import com.legobmw99.allomancy.modules.extras.advancement.MetalUsedOnPlayerTrigger; import com.legobmw99.allomancy.modules.extras.block.IronButtonBlock; import com.legobmw99.allomancy.modules.extras.block.IronLeverBlock; +import com.legobmw99.allomancy.modules.extras.command.AllomancyPowerCommand; +import com.legobmw99.allomancy.modules.extras.command.AllomancyPowerType; import net.minecraft.advancements.CriterionTrigger; +import net.minecraft.commands.synchronization.ArgumentTypeInfo; +import net.minecraft.commands.synchronization.ArgumentTypeInfos; +import net.minecraft.commands.synchronization.SingletonArgumentInfo; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -16,6 +21,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.level.block.entity.BannerPattern; import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.registries.DeferredBlock; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredItem; @@ -45,6 +51,12 @@ public class ExtrasSetup { public static final List> PATTERN_KEYS = new ArrayList<>(); public static final List> PATTERN_ITEMS = new ArrayList<>(); + private static final DeferredRegister> COMMAND_ARGUMENT_TYPES = DeferredRegister.create(Registries.COMMAND_ARGUMENT_TYPE, Allomancy.MODID); + private static final Supplier> CONTAINER_CLASS = COMMAND_ARGUMENT_TYPES.register("allomancy_power", + () -> ArgumentTypeInfos.registerByClass( + AllomancyPowerType.class, + SingletonArgumentInfo.contextFree( + AllomancyPowerType::allomancyPowerType))); static { @@ -72,6 +84,11 @@ public static void register(IEventBus bus) { ITEMS.register(bus); BP.register(bus); CT.register(bus); + COMMAND_ARGUMENT_TYPES.register(bus); + } + + public static void registerCommands(final RegisterCommandsEvent e) { + AllomancyPowerCommand.register(e.getDispatcher()); } } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/command/AllomancyPowerCommand.java b/src/main/java/com/legobmw99/allomancy/modules/extras/command/AllomancyPowerCommand.java similarity index 98% rename from src/main/java/com/legobmw99/allomancy/modules/powers/command/AllomancyPowerCommand.java rename to src/main/java/com/legobmw99/allomancy/modules/extras/command/AllomancyPowerCommand.java index 1db7d6d9..3e1dfe3e 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/command/AllomancyPowerCommand.java +++ b/src/main/java/com/legobmw99/allomancy/modules/extras/command/AllomancyPowerCommand.java @@ -1,9 +1,9 @@ -package com.legobmw99.allomancy.modules.powers.command; +package com.legobmw99.allomancy.modules.extras.command; import com.legobmw99.allomancy.api.data.IAllomancerData; import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; -import com.legobmw99.allomancy.network.Network; +import com.legobmw99.allomancy.modules.powers.network.Network; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/command/AllomancyPowerType.java b/src/main/java/com/legobmw99/allomancy/modules/extras/command/AllomancyPowerType.java similarity index 97% rename from src/main/java/com/legobmw99/allomancy/modules/powers/command/AllomancyPowerType.java rename to src/main/java/com/legobmw99/allomancy/modules/extras/command/AllomancyPowerType.java index 0e065a88..43407d82 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/command/AllomancyPowerType.java +++ b/src/main/java/com/legobmw99/allomancy/modules/extras/command/AllomancyPowerType.java @@ -1,4 +1,4 @@ -package com.legobmw99.allomancy.modules.powers.command; +package com.legobmw99.allomancy.modules.extras.command; import com.legobmw99.allomancy.api.enums.Metal; import com.mojang.brigadier.StringReader; diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java b/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java index 0d916003..e529d681 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/CommonEventHandler.java @@ -1,7 +1,6 @@ package com.legobmw99.allomancy.modules.powers; import com.legobmw99.allomancy.Allomancy; -import com.legobmw99.allomancy.api.data.IAllomancerData; import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.combat.item.KolossBladeItem; import com.legobmw99.allomancy.modules.extras.ExtrasSetup; @@ -9,31 +8,25 @@ import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; import com.legobmw99.allomancy.modules.powers.data.AllomancerData; import com.legobmw99.allomancy.modules.powers.network.EnhanceTimePayload; -import com.legobmw99.allomancy.network.Network; +import com.legobmw99.allomancy.modules.powers.network.Network; +import com.legobmw99.allomancy.modules.powers.util.Emotional; +import com.legobmw99.allomancy.modules.powers.util.Enhancement; +import com.legobmw99.allomancy.modules.powers.util.Physical; +import com.legobmw99.allomancy.modules.powers.util.Temporal; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityTicker; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.event.TickEvent; import net.neoforged.neoforge.event.entity.living.LivingAttackEvent; @@ -181,7 +174,7 @@ public static void onEntityHurt(final LivingHurtEvent event) { if (data.isEnhanced()) { if (source.getMainHandItem().getItem() instanceof KolossBladeItem) { event.setAmount(550); // Duralumin OHK with Koloss blade - PowerUtils.wipePlayer(source); + Enhancement.wipePlayer(source); } else { event.setAmount(event.getAmount() * 3); } @@ -194,8 +187,8 @@ public static void onEntityHurt(final LivingHurtEvent event) { ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(source, event.getEntity(), Metal.CHROMIUM, data.isEnhanced()); if (event.getEntity() instanceof ServerPlayer player) { ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().trigger(player, Metal.CHROMIUM, data.isEnhanced()); - if (!PowerUtils.hasTinFoilHat(player)) { - PowerUtils.wipePlayer(player); + if (!Emotional.hasTinFoilHat(player)) { + Enhancement.wipePlayer(player); } } } @@ -227,7 +220,7 @@ public static void onPlayerAttacked(final LivingAttackEvent event) { if (data.isBurning(Metal.STEEL)) { if (event.getSource().type().equals(player.level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.FALL).value())) { BlockPos on = player.getOnPos(); - if (PowerUtils.isBlockStateMetal(player.level().getBlockState(on)) || PowerUtils.isBlockStateMetal(player.level().getBlockState(on.above()))) { + if (Physical.isBlockStateMetallic(player.level().getBlockState(on)) || Physical.isBlockStateMetallic(player.level().getBlockState(on.above()))) { event.setCanceled(true); } } @@ -262,7 +255,7 @@ private static void playerPowerTick(Player curPlayer, Level level) { * ALUMINUM AND DURALUMIN * *********************************************/ if (data.isBurning(Metal.ALUMINUM)) { - PowerUtils.wipePlayer(curPlayer); + Enhancement.wipePlayer(curPlayer); syncRequired = true; } if (data.isBurning(Metal.DURALUMIN) && !data.isEnhanced()) { @@ -286,69 +279,26 @@ private static void playerPowerTick(Player curPlayer, Level level) { * CHROMIUM (enhanced) * *********************************************/ if (data.isEnhanced() && data.isBurning(Metal.CHROMIUM)) { - if (level instanceof ServerLevel) { - int max = 20; - Vec3 negative = curPlayer.position().add(-max, -max, -max); - Vec3 positive = curPlayer.position().add(max, max, max); - level - .getEntitiesOfClass(Player.class, new AABB(negative, positive)) - .forEach(otherPlayer -> otherPlayer.getData(AllomancerAttachment.ALLOMANCY_DATA).drainMetals(Metal.values())); - } + Enhancement.wipeNearby(curPlayer, level); } /********************************************* * GOLD AND ELECTRUM (enhanced) * *********************************************/ if (data.isEnhanced() && data.isBurning(Metal.ELECTRUM) && data.getStored(Metal.ELECTRUM) >= 9) { - ResourceKey spawnDim = data.getSpawnDim(); - BlockPos spawnLoc; - - if (spawnDim != null) { - spawnLoc = data.getSpawnLoc(); - } else { - spawnDim = Level.OVERWORLD; // no spawn --> use world spawn - spawnLoc = new BlockPos(level.getLevelData().getXSpawn(), level.getLevelData().getYSpawn(), level.getLevelData().getZSpawn()); - - } - - PowerUtils.teleport(curPlayer, level, spawnDim, spawnLoc); - if (data.isBurning(Metal.DURALUMIN)) { - data.drainMetals(Metal.DURALUMIN); - } - data.drainMetals(Metal.ELECTRUM); - - + Enhancement.teleportToSpawn(curPlayer, level, data); } else if (data.isEnhanced() && data.isBurning(Metal.GOLD) && data.getStored(Metal.GOLD) >= 9) { // These should be mutually exclusive - ResourceKey deathDim = data.getDeathDim(); - if (deathDim != null) { - PowerUtils.teleport(curPlayer, level, deathDim, data.getDeathLoc()); - if (data.isBurning(Metal.DURALUMIN)) { - data.drainMetals(Metal.DURALUMIN); - } - data.drainMetals(Metal.GOLD); - } + Enhancement.teleportToLastDeath(curPlayer, level, data); } - /********************************************* * BENDALLOY AND CADMIUM * *********************************************/ if (data.isBurning(Metal.BENDALLOY) && !data.isBurning(Metal.CADMIUM)) { - curPlayer.addEffect(new MobEffectInstance(MobEffects.DIG_SPEED, 10, 3, true, false)); - - tickNearby(curPlayer, level, data); + Temporal.speedUpNearby(curPlayer, level, data); } if (data.isBurning(Metal.CADMIUM) && !data.isBurning(Metal.BENDALLOY)) { - int max = data.isEnhanced() ? 20 : 10; - Vec3 negative = curPlayer.position().add(-max, -max, -max); - Vec3 positive = curPlayer.position().add(max, max, max); - int slowness_amplifier = data.isEnhanced() ? 255 : 2; // Duralumin freezes entities - level.getEntitiesOfClass(LivingEntity.class, new AABB(negative, positive)).forEach(entity -> { - entity.addEffect(new MobEffectInstance(MobEffects.SLOW_FALLING, 10, 0, true, false)); - if (entity != curPlayer) { - entity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 10, slowness_amplifier, true, false)); - } - }); + Temporal.slowDownNearby(curPlayer, level, data); } @@ -362,10 +312,10 @@ private static void playerPowerTick(Player curPlayer, Level level) { if (level.random.nextInt(50) == 0) { curPlayer.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 100, 0, true, false)); } - } else { // Remove blindness from normal tin burners - if (curPlayer.hasEffect(MobEffects.BLINDNESS)) { - curPlayer.removeEffect(MobEffects.BLINDNESS); - } + } + // Remove blindness from normal tin burners + if (curPlayer.hasEffect(MobEffects.BLINDNESS)) { + curPlayer.removeEffect(MobEffects.BLINDNESS); } } // Remove night vision from non-tin burners if duration < 10 seconds. Related to the above issue with flashing, only if the amplifier is 5 @@ -400,39 +350,5 @@ private static void playerPowerTick(Player curPlayer, Level level) { } } } - - @SuppressWarnings("unchecked") - private static void tickNearby(Player curPlayer, Level level, IAllomancerData data) { - if (level instanceof ServerLevel serverLevel) { - int max = data.isEnhanced() ? 10 : 5; - BlockPos negative = curPlayer.blockPosition().offset(-max, -max, -max); - BlockPos positive = curPlayer.blockPosition().offset(max, max, max); - serverLevel.getEntitiesOfClass(LivingEntity.class, AABB.encapsulatingFullBlocks(negative, positive)).forEach(entity -> { - entity.aiStep(); - entity.aiStep(); - }); - BlockPos.betweenClosedStream(negative, positive).forEach(bp -> { - BlockState block = level.getBlockState(bp); - BlockEntity te = level.getBlockEntity(bp); - if (te == null) { - if (block.isRandomlyTicking()) { - for (int i = 0; i < max * 4 / 15; i++) { - block.randomTick(serverLevel, bp, serverLevel.random); - } - } - } else { - Block underlying_block = block.getBlock(); - if (underlying_block instanceof EntityBlock eb) { - BlockEntityTicker ticker = eb.getTicker(level, block, te.getType()); - if (ticker != null) { - for (int i = 0; i < max * 4 / 3; i++) { - ticker.tick(level, bp, block, te); - } - } - } - } - }); - } - } } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/PowerUtils.java b/src/main/java/com/legobmw99/allomancy/modules/powers/PowerUtils.java deleted file mode 100644 index 4678f3c2..00000000 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/PowerUtils.java +++ /dev/null @@ -1,339 +0,0 @@ -package com.legobmw99.allomancy.modules.powers; - -import com.legobmw99.allomancy.Allomancy; -import com.legobmw99.allomancy.api.enums.Metal; -import com.legobmw99.allomancy.modules.combat.CombatSetup; -import com.legobmw99.allomancy.modules.combat.entity.ProjectileNuggetEntity; -import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; -import com.legobmw99.allomancy.modules.powers.entity.ai.AIAttackOnCollideExtended; -import com.legobmw99.allomancy.modules.powers.entity.ai.AIEvilAttack; -import com.legobmw99.allomancy.network.Network; -import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.Mth; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.*; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.ai.goal.*; -import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; -import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; -import net.minecraft.world.entity.ai.goal.target.TargetGoal; -import net.minecraft.world.entity.ai.village.ReputationEventType; -import net.minecraft.world.entity.animal.IronGolem; -import net.minecraft.world.entity.animal.Rabbit; -import net.minecraft.world.entity.animal.Sheep; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.entity.decoration.ItemFrame; -import net.minecraft.world.entity.item.FallingBlockEntity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.monster.*; -import net.minecraft.world.entity.npc.AbstractVillager; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.WanderingTrader; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.neoforged.neoforge.common.util.ITeleporter; - -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -/** - * Contains all static, common methods in one place - */ - -public class PowerUtils { - - public static final byte PUSH = 1; - public static final byte PULL = -1; - private static final Predicate isAggroGoal = (goal) -> goal instanceof SwellGoal || goal instanceof AIAttackOnCollideExtended || goal instanceof MeleeAttackGoal || - goal instanceof TargetGoal || goal instanceof PanicGoal || goal.getClass().getName().contains("Fireball") || - goal.getClass().getName().contains("Attack") || goal.getClass().getName().contains("Anger"); - - private static final Pattern ACTIVE_METAL_REGEX = Pattern.compile( - ".*(iron|steel|tin_|pewter|zinc|brass|copper|bronze|duralumin|chromium|nicrosil|gold|electrum|cadmium|bendalloy|lead_|silver|platinum|nickle).*"); - - - public static boolean doesResourceContainsMetal(ResourceLocation input) { - return ACTIVE_METAL_REGEX.matcher(input.getPath()).matches(); - } - - - /** - * Block state wrapper on {@link PowerUtils#isBlockMetal} - * - * @param state BlockState to check - * @return whether the block state is metal - */ - public static boolean isBlockStateMetal(BlockState state) { - return isBlockMetal(state.getBlock()); - } - - /** - * Determines if a block is metal or not - * - * @param block to be checked - * @return Whether the block is metal - */ - public static boolean isBlockMetal(Block block) { - return isOnWhitelist(BuiltInRegistries.BLOCK.getKey(block).toString()); - } - - /** - * Determines if an item is metal or not - * - * @param item to be checked - * @return Whether the item is metal - */ - public static boolean isItemMetal(ItemStack item) { - return isOnWhitelist(BuiltInRegistries.ITEM.getKey(item.getItem()).toString()); - } - - private static boolean isOnWhitelist(String s) { - return PowersConfig.whitelist.contains(s); - } - - /** - * Determines if an entity is metal or not - * - * @param entity to be checked - * @return Whether the entity is metallic - */ - public static boolean isEntityMetal(Entity entity) { - if (entity == null) { - return false; - } - if (entity instanceof ItemEntity item) { - return isItemMetal(item.getItem()); - } - if (entity instanceof ItemFrame itemFrame) { - return isItemMetal(itemFrame.getItem()); - } - if (entity instanceof FallingBlockEntity fbe) { - return isBlockStateMetal(fbe.getBlockState()); - } - if (entity instanceof ProjectileNuggetEntity) { - return true; - } - if (entity instanceof AbstractMinecart) { - return true; - } - if (entity instanceof LivingEntity ent) { - if (ent instanceof IronGolem) { - return true; - } - if (isItemMetal(ent.getItemInHand(InteractionHand.MAIN_HAND)) || isItemMetal(ent.getItemInHand(InteractionHand.OFF_HAND))) { - return true; - } - for (ItemStack itemStack : ent.getArmorSlots()) { - if (isItemMetal(itemStack)) { - return true; - } - } - } - - return false; - } - - /** - * Wipe all metals from the player and sync to tracking entities. Used by Aluminum and Nicrosil - * - * @param player The player to wipe - */ - public static void wipePlayer(Player player) { - var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); - data.drainMetals(Metal.values()); - player.removeAllEffects(); - - if (player instanceof ServerPlayer sp) { - Network.syncAllomancerData(sp); - } - } - - /** - * Move an entity either toward or away from an anchor point - * - * @param directionScalar the direction and (possibly) scalar multiple of the magnitude - * @param toMove the entity to move - * @param block the point being moved toward or away from - */ - public static void move(double directionScalar, Entity toMove, BlockPos block) { - - if (toMove.isPassenger()) { - toMove = toMove.getVehicle(); - } - - Vec3 motion = toMove.position().subtract(Vec3.atCenterOf(block)).normalize().scale(directionScalar * 1.1); - Vec3 mod = clamp(cutoff(motion.add(toMove.getDeltaMovement()), 0.1), abs(motion).reverse(), abs(motion)); - toMove.setDeltaMovement(mod); - toMove.hurtMarked = true; - - // Only save players from fall damage - if (toMove instanceof ServerPlayer) { - toMove.fallDistance = 0; - } - } - - - /* - * Three helper functions for working with Vec3s - */ - private static Vec3 clamp(Vec3 value, Vec3 min, Vec3 max) { - return new Vec3(Mth.clamp(value.x, min.x, max.x), Mth.clamp(value.y, min.y, max.y), Mth.clamp(value.z, min.z, max.z)); - } - - private static Vec3 abs(Vec3 vec) { - return new Vec3(Math.abs(vec.x), Math.abs(vec.y), Math.abs(vec.z)); - } - - private static Vec3 cutoff(Vec3 value, double e) { - Vec3 mag = abs(value); - return new Vec3(mag.x < e ? 0 : value.x, mag.y < e ? 0 : value.y, mag.z < e ? 0 : value.z); - } - - - /** - * Teleports a player to the given dimension and blockpos - * - * @param player The player to move - * @param world The server world. Fails if clientside - * @param dimension Dimension to call {@link Entity#changeDimension} on - * @param pos BlockPos to move the player to using {@link Entity#teleportToWithTicket} - */ - public static void teleport(Player player, Level world, ResourceKey dimension, BlockPos pos) { - if (!world.isClientSide) { - if (player != null) { - if (player.isPassenger()) { - player.stopRiding(); - } - - if (player.level().dimension() != dimension) { - //change dimension - player = (Player) player.changeDimension(world.getServer().getLevel(dimension), new ITeleporter() { - @Override - public Entity placeEntity(Entity entity, ServerLevel currentWorld, ServerLevel destWorld, float yaw, Function repositionEntity) { - Entity repositionedEntity = repositionEntity.apply(false); - repositionedEntity.teleportTo(pos.getX(), pos.getY(), pos.getZ()); - return repositionedEntity; - } - }); - } - - player.teleportToWithTicket(pos.getX(), pos.getY() + 1.5, pos.getZ()); - player.fallDistance = 0.0F; - } - } - } - - public static void riotEntity(PathfinderMob target, Player allomancer, boolean enhanced) { - try { - if (!enhanced) { - if (hasTinFoilHat(target)) { - return; - } - //Enable Targeting goals - target.targetSelector.enableControlFlag(Goal.Flag.TARGET); - //Add new goals - target.setTarget(allomancer); - target.setLastHurtByMob(allomancer); - // TODO: try to use PrioritizedGoal::startExecuting for already hostiles - target.targetSelector.addGoal(1, new AIAttackOnCollideExtended(target, 1d, false)); - target.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(target, Player.class, false)); - target.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(target, target.getClass(), false)); - target.goalSelector.addGoal(4, new RandomLookAroundGoal(target)); - target.targetSelector.addGoal(2, new HurtByTargetGoal(target).setAlertOthers()); - if (target.getAttribute(Attributes.ATTACK_DAMAGE) != null && !(target instanceof Guardian)) { - target.goalSelector.addGoal(3, new MeleeAttackGoal(target, 1.2D, true)); - } - - target.setAggressive(true); - - if (target instanceof Creeper creeper) { - target.goalSelector.addGoal(1, new SwellGoal(creeper)); - } - if (target instanceof Rabbit rabbit) { - target.goalSelector.addGoal(1, new AIEvilAttack(rabbit)); - } - if (target instanceof AbstractSkeleton skeleton) { - target.goalSelector.addGoal(1, new RangedBowAttackGoal<>(skeleton, 1.0D, 20, 15.0F)); - } - if (target instanceof Illusioner illusioner) { - target.goalSelector.addGoal(1, new RangedBowAttackGoal<>(illusioner, 0.5D, 20, 15.0F)); - } - if (target instanceof Pillager pillager) { - target.goalSelector.addGoal(2, new RangedCrossbowAttackGoal<>(pillager, 1.0D, 8.0F)); - } - } else { - target.level().explode(target, target.position().x(), target.position().y(), target.position().z(), 1.2F, false, Level.ExplosionInteraction.MOB); - target.kill(); - } - } catch (Exception e) { - Allomancy.LOGGER.error("Failed to riot entity " + target + "! Please report this error!", e); - } - } - - public static void sootheEntity(PathfinderMob target, Player allomancer, boolean enhanced) { - try { - if (!enhanced) { - if (hasTinFoilHat(target)) { - return; - } - - if (target.isNoAi()) { - target.setNoAi(false); - } - // Reset all current aggro goals - target.goalSelector.getRunningGoals().filter(isAggroGoal).forEach(WrappedGoal::stop); - target.targetSelector.getRunningGoals().filter(isAggroGoal).forEach(WrappedGoal::stop); - target.goalSelector.tick(); - target.targetSelector.tick(); - target.setTarget(null); - target.setLastHurtByMob(null); - //Disable targeting as a whole - target.targetSelector.disableControlFlag(Goal.Flag.TARGET); - target.setAggressive(false); - //Add new goals - target.goalSelector.addGoal(7, new LookAtPlayerGoal(target, Player.class, 6.0F)); - - if (target instanceof TamableAnimal animal) { - if (Math.random() < 0.3) { - animal.tame(allomancer); - } - } - if (target instanceof AbstractHorse horse) { - if (Math.random() < 0.3) { - horse.tameWithName(allomancer); - } - } - if (target instanceof Sheep) { - target.goalSelector.addGoal(1, new EatBlockGoal(target)); - } - if (target instanceof Villager villager) { - villager.onReputationEventFrom(ReputationEventType.TRADE, allomancer); - } - if (target instanceof WanderingTrader) { - target.goalSelector.addGoal(1, new TradeWithPlayerGoal((AbstractVillager) target)); - } - } else { // Completely remove all AI if enhanced - target.setNoAi(true); - } - - } catch (Exception e) { - Allomancy.LOGGER.error("Failed to soothe entity " + target + "! Please report this error!", e); - } - - } - - public static boolean hasTinFoilHat(LivingEntity entity) { - return entity.getItemBySlot(EquipmentSlot.HEAD).getItem() == CombatSetup.ALUMINUM_HELMET.get(); - } -} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/PowersConfig.java b/src/main/java/com/legobmw99/allomancy/modules/powers/PowersConfig.java index f9d6e413..11518da4 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/PowersConfig.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/PowersConfig.java @@ -1,22 +1,16 @@ package com.legobmw99.allomancy.modules.powers; -import com.legobmw99.allomancy.Allomancy; -import com.legobmw99.allomancy.modules.combat.CombatSetup; -import com.legobmw99.allomancy.modules.consumables.ConsumeSetup; import com.legobmw99.allomancy.modules.powers.client.gui.MetalOverlay; +import com.legobmw99.allomancy.modules.powers.util.Physical; import com.legobmw99.allomancy.util.AllomancyConfig; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.properties.WoodType; import net.neoforged.fml.config.ModConfig; import net.neoforged.fml.event.config.ModConfigEvent; import net.neoforged.neoforge.common.ModConfigSpec; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class PowersConfig { @@ -29,7 +23,6 @@ public class PowersConfig { public static ModConfigSpec.BooleanValue generate_whitelist; public static ModConfigSpec.BooleanValue respect_player_UUID; public static ModConfigSpec.ConfigValue> cfg_whitelist; - private static HashSet defaultList; public static void init(ModConfigSpec.Builder server_builder, ModConfigSpec.Builder common_builder, ModConfigSpec.Builder client_builder) { common_builder.comment("Settings for the gameplay elements of the mod").push("gameplay"); @@ -71,126 +64,12 @@ public static void load_whitelist(final ModConfigEvent.Loading e) { ModConfig cfg = e.getConfig(); if (cfg.getSpec() == AllomancyConfig.SERVER_CONFIG) { if (generate_whitelist.get()) { - ArrayList list = new ArrayList<>(default_whitelist()); - list.sort(String::compareTo); - cfg_whitelist.set(list); + cfg_whitelist.set(Physical.default_whitelist()); generate_whitelist.set(false); } refresh_whitelist(); } } - // this could be a Tag one day - private static Set default_whitelist() { - defaultList = new HashSet<>(); - add(Items.BUCKET); - add(Items.LAVA_BUCKET); - add(Items.MILK_BUCKET); - add(Items.COD_BUCKET); - add(Items.PUFFERFISH_BUCKET); - add(Items.SALMON_BUCKET); - add(Items.TROPICAL_FISH_BUCKET); - add(Items.WATER_BUCKET); - add(Items.TADPOLE_BUCKET); - add(Items.AXOLOTL_BUCKET); - add(Items.POWDER_SNOW_BUCKET); - add(Items.COMPASS); - add(Items.RECOVERY_COMPASS); - add(Items.CHAINMAIL_HELMET); - add(Items.CHAINMAIL_CHESTPLATE); - add(Items.CHAINMAIL_LEGGINGS); - add(Items.CHAINMAIL_BOOTS); - add(Items.MINECART); - add(Items.CHEST_MINECART); - add(Items.HOPPER_MINECART); - add(Items.FURNACE_MINECART); - add(Items.TNT_MINECART); - add(Items.CLOCK); - add(Items.SHEARS); - add(Items.SHIELD); - add(Items.NETHERITE_INGOT); - add(Items.NETHERITE_HELMET); - add(Items.NETHERITE_CHESTPLATE); - add(Items.NETHERITE_LEGGINGS); - add(Items.NETHERITE_BOOTS); - add(Items.NETHERITE_HOE); - add(Items.NETHERITE_PICKAXE); - add(Items.NETHERITE_SHOVEL); - add(Items.NETHERITE_SWORD); - add(Items.NETHERITE_AXE); - add(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE); - add(Items.CROSSBOW); - - add(Blocks.ANVIL); - add(Blocks.CHIPPED_ANVIL); - add(Blocks.DAMAGED_ANVIL); - add(Blocks.CAULDRON); - add(Blocks.POWDER_SNOW_CAULDRON); - add(Blocks.LAVA_CAULDRON); - add(Blocks.WATER_CAULDRON); - add(Blocks.SMITHING_TABLE); - add(Blocks.STONECUTTER); - add(Blocks.CHAIN); - add(Blocks.HOPPER); - add(Blocks.PISTON_HEAD); - add(Blocks.MOVING_PISTON); - add(Blocks.STICKY_PISTON); - add(Blocks.BLAST_FURNACE); - add(Blocks.BELL); - add(Blocks.PISTON); - add(Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE); - add(Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE); - add(Blocks.RAIL); - add(Blocks.ACTIVATOR_RAIL); - add(Blocks.DETECTOR_RAIL); - add(Blocks.POWERED_RAIL); - add(Blocks.LANTERN); - add(Blocks.TRAPPED_CHEST); - add(Blocks.TRIPWIRE_HOOK); - add(Blocks.SOUL_LANTERN); - add(Blocks.NETHERITE_BLOCK); - add(Blocks.LODESTONE); - add(Blocks.GILDED_BLACKSTONE); - add(Blocks.LIGHTNING_ROD); - - add(Items.BRUSH); - - WoodType.values().forEach(wt -> { - add("minecraft:" + wt.name() + "_hanging_sign"); - add("minecraft:" + wt.name() + "_wall_hanging_sign"); - }); - - - add(ConsumeSetup.VIAL.get()); - add(ConsumeSetup.LERASIUM_NUGGET.get()); - add(ConsumeSetup.ALLOMANTIC_GRINDER.get()); - add(CombatSetup.COIN_BAG.get()); - - - BuiltInRegistries.ITEM.keySet().stream().filter(Objects::nonNull).filter(PowerUtils::doesResourceContainsMetal).forEach(PowersConfig::add); - - BuiltInRegistries.BLOCK.keySet().stream().filter(Objects::nonNull).filter(PowerUtils::doesResourceContainsMetal).forEach(PowersConfig::add); - - return defaultList; - - } - - - private static void add(String s) { - Allomancy.LOGGER.info("Adding " + s + " to the default whitelist!"); - defaultList.add(s); - } - - private static void add(ResourceLocation r) { - add(r.toString()); - } - - private static void add(Block block) { - add(BuiltInRegistries.BLOCK.getKey(block)); - } - - private static void add(Item item) { - add(BuiltInRegistries.ITEM.getKey(item)); - } } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/PowersSetup.java b/src/main/java/com/legobmw99/allomancy/modules/powers/PowersSetup.java index cea299ac..2bcc1341 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/PowersSetup.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/PowersSetup.java @@ -1,51 +1,13 @@ package com.legobmw99.allomancy.modules.powers; -import com.legobmw99.allomancy.Allomancy; -import com.legobmw99.allomancy.modules.powers.client.ClientEventHandler; -import com.legobmw99.allomancy.modules.powers.command.AllomancyPowerCommand; -import com.legobmw99.allomancy.modules.powers.command.AllomancyPowerType; -import net.minecraft.commands.synchronization.ArgumentTypeInfo; -import net.minecraft.commands.synchronization.ArgumentTypeInfos; -import net.minecraft.commands.synchronization.SingletonArgumentInfo; -import net.minecraft.core.registries.Registries; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.RegisterCommandsEvent; -import net.neoforged.neoforge.registries.DeferredRegister; - -import java.util.function.Supplier; public class PowersSetup { - - - private static final DeferredRegister> COMMAND_ARGUMENT_TYPES = DeferredRegister.create(Registries.COMMAND_ARGUMENT_TYPE, Allomancy.MODID); - private static final Supplier> CONTAINER_CLASS = COMMAND_ARGUMENT_TYPES.register("allomancy_power", - () -> ArgumentTypeInfos.registerByClass( - AllomancyPowerType.class, - SingletonArgumentInfo.contextFree( - AllomancyPowerType::allomancyPowerType))); - - public static void clientInit(final FMLClientSetupEvent e) { - e.enqueueWork(() -> { - NeoForge.EVENT_BUS.register(new ClientEventHandler()); - }); - } - - - public static void registerCommands(final RegisterCommandsEvent e) { - AllomancyPowerCommand.register(e.getDispatcher()); - } - - public static void init(final FMLCommonSetupEvent e) { e.enqueueWork(() -> { NeoForge.EVENT_BUS.register(CommonEventHandler.class); }); } - public static void register(IEventBus bus) { - COMMAND_ARGUMENT_TYPES.register(bus); - } } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/ClientEventHandler.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/ClientEventHandler.java index 0515a4c0..2d7932a1 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/client/ClientEventHandler.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/ClientEventHandler.java @@ -1,40 +1,21 @@ package com.legobmw99.allomancy.modules.powers.client; -import com.legobmw99.allomancy.api.data.IAllomancerData; import com.legobmw99.allomancy.api.enums.Metal; -import com.legobmw99.allomancy.modules.combat.CombatSetup; -import com.legobmw99.allomancy.modules.powers.PowerUtils; -import com.legobmw99.allomancy.modules.powers.PowersConfig; import com.legobmw99.allomancy.modules.powers.client.gui.MetalSelectScreen; -import com.legobmw99.allomancy.modules.powers.client.particle.SoundParticleData; -import com.legobmw99.allomancy.modules.powers.client.util.ClientUtils; -import com.legobmw99.allomancy.modules.powers.client.util.SensoryTracking; +import com.legobmw99.allomancy.modules.powers.client.network.PowerRequests; +import com.legobmw99.allomancy.modules.powers.client.util.Inputs; +import com.legobmw99.allomancy.modules.powers.client.util.Rendering; +import com.legobmw99.allomancy.modules.powers.client.util.Sounds; +import com.legobmw99.allomancy.modules.powers.client.util.Tracking; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; -import com.legobmw99.allomancy.modules.powers.network.BlockPushPullPayload; -import com.legobmw99.allomancy.modules.powers.network.EmotionPayload; -import com.legobmw99.allomancy.modules.powers.network.EnhanceTimePayload; -import com.legobmw99.allomancy.modules.powers.network.EntityPushPullPayload; -import com.legobmw99.allomancy.network.Network; -import com.mojang.blaze3d.platform.InputConstants; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; -import net.minecraft.client.Options; -import net.minecraft.client.player.Input; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.resources.sounds.SoundInstance; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceKey; import net.minecraft.util.Mth; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.Level; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.EntityHitResult; -import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; @@ -48,19 +29,18 @@ import org.lwjgl.glfw.GLFW; public class ClientEventHandler { - private final Minecraft mc = Minecraft.getInstance(); - private final SensoryTracking tracking = new SensoryTracking(); - + private static final Tracking tracking = new Tracking(); @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void onClientTick(final TickEvent.ClientTickEvent event) { + public static void onClientTick(final TickEvent.ClientTickEvent event) { + Minecraft mc = Minecraft.getInstance(); // Run once per tick, only if in game, and only if there is a player - if (event.phase != TickEvent.Phase.END || this.mc.isPaused() || this.mc.player == null || !this.mc.player.isAlive()) { + if (event.phase != TickEvent.Phase.END || mc.isPaused() || mc.player == null || !mc.player.isAlive()) { return; } - Player player = this.mc.player; + Player player = mc.player; var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); if (data.isUninvested()) { return; @@ -69,131 +49,52 @@ public void onClientTick(final TickEvent.ClientTickEvent event) { int dist_modifier = data.isEnhanced() ? 2 : 1; // Handle our input-based powers - if (this.mc.options.keyAttack.isDown()) { + if (mc.options.keyAttack.isDown()) { // Ray trace 20 blocks (or 40 if enhanced) - var trace = ClientUtils.getMouseOverExtended(20F * dist_modifier); - // All iron pulling powers - metalPushPull(player, data, trace, Metal.IRON, PowerUtils.PULL); - // All zinc powers - emotionPushPull(data, trace, Metal.ZINC, true); + var trace = Inputs.getMouseOverExtended(20F * dist_modifier); + PowerRequests.metallicPushPull(data, trace, Metal.IRON); + PowerRequests.emotionPushPull(data, trace, Metal.ZINC); } - if (this.mc.options.keyUse.isDown()) { + if (mc.options.keyUse.isDown()) { // Ray trace 20 blocks (or 40 if enhanced) - var trace = ClientUtils.getMouseOverExtended(20F * dist_modifier); - // All steel pushing powers - metalPushPull(player, data, trace, Metal.STEEL, PowerUtils.PUSH); - // All brass powers - emotionPushPull(data, trace, Metal.BRASS, false); - - if (data.isBurning(Metal.NICROSIL)) { - if ((trace != null) && (trace.getType() == HitResult.Type.ENTITY)) { - Entity entity = ((EntityHitResult) trace).getEntity(); - if (entity instanceof Player) { - Network.sendToServer(new EnhanceTimePayload(true, entity.getId())); - } - } - } - } - - this.tracking.tick(); - } - - - private static void emotionPushPull(IAllomancerData data, HitResult trace, Metal metal, boolean make_aggressive) { - if (!data.isBurning(metal) || trace == null) { - return; + var trace = Inputs.getMouseOverExtended(20F * dist_modifier); + PowerRequests.metallicPushPull(data, trace, Metal.STEEL); + PowerRequests.emotionPushPull(data, trace, Metal.BRASS); + PowerRequests.nicrosilEnhance(data, trace); } - if (trace.getType() == HitResult.Type.ENTITY) { - Entity entity = ((EntityHitResult) trace).getEntity(); - if (entity instanceof PathfinderMob) { - Network.sendToServer(new EmotionPayload(entity.getId(), make_aggressive)); - } - } + tracking.tick(); } - private void metalPushPull(Player player, IAllomancerData data, HitResult trace, Metal metal, byte direction) { - if (!data.isBurning(metal) || trace == null) { - return; - } - - int force_multiplier = data.isEnhanced() ? 4 : 1; - - if (trace.getType() == HitResult.Type.ENTITY && PowerUtils.isEntityMetal(((EntityHitResult) trace).getEntity())) { - Network.sendToServer(new EntityPushPullPayload(((EntityHitResult) trace).getEntity().getId(), direction * force_multiplier)); - } else if (trace.getType() == HitResult.Type.BLOCK) { - BlockPos bp = ((BlockHitResult) trace).getBlockPos(); - if (PowerUtils.isBlockStateMetal(this.mc.level.getBlockState(bp)) || (player.getMainHandItem().getItem() == CombatSetup.COIN_BAG.get() && player.isCrouching())) { - Network.sendToServer(new BlockPushPullPayload(bp, direction * force_multiplier)); - } - } - } @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void onKeyInput(final InputEvent.Key event) { + public static void onKeyInput(final InputEvent.Key event) { if (event.getAction() == GLFW.GLFW_PRESS) { - acceptInput(); + Inputs.acceptAllomancyKeybinds(); } } @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void onMouseInput(final InputEvent.MouseButton.Pre event) { + public static void onMouseInput(final InputEvent.MouseButton.Pre event) { if (event.getAction() == GLFW.GLFW_PRESS) { - acceptInput(); - } - } - - /** - * Handles either mouse or button presses for the mod's keybinds - */ - private void acceptInput() { - if (this.mc.screen != null) { - return; - } - Player player = this.mc.player; - if (player == null || !this.mc.isWindowActive()) { - return; - } - - if (PowersClientSetup.hud.isDown()) { - PowersConfig.enable_overlay.set(!PowersConfig.enable_overlay.get()); - return; - } - var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); - - for (int i = 0; i < PowersClientSetup.powers.length; i++) { - if (PowersClientSetup.powers[i].isDown()) { - ClientUtils.toggleBurn(Metal.getMetal(i), data); - } - } - if (PowersClientSetup.burn.isDown()) { - switch (data.getPowerCount()) { - case 0: - break; - case 1: - ClientUtils.toggleBurn(data.getPowers()[0], data); - break; - default: - this.mc.setScreen(new MetalSelectScreen()); - break; - } + Inputs.acceptAllomancyKeybinds(); } } @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void onRenderLevelStage(final RenderLevelStageEvent event) { - + public static void onRenderLevelStage(final RenderLevelStageEvent event) { if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_PARTICLES) { return; } - Player player = this.mc.player; - if (player == null || !player.isAlive() || this.mc.options.getCameraType().isMirrored()) { + Minecraft mc = Minecraft.getInstance(); + Player player = mc.player; + if (player == null || !player.isAlive() || mc.options.getCameraType().isMirrored()) { return; } var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); @@ -202,15 +103,15 @@ public void onRenderLevelStage(final RenderLevelStageEvent event) { if (data.isUninvested()) { return; } - PoseStack stack = setupPoseStack(event); + float partialTick = event.getPartialTick(); + + PoseStack stack = Rendering.prepareToDrawLines(event.getPoseStack(), partialTick); double rho = 1; - float theta = (float) ((this.mc.player.getViewYRot(event.getPartialTick()) + 90) * Math.PI / 180); - float phi = Mth.clamp((float) ((this.mc.player.getViewXRot(event.getPartialTick()) + 90) * Math.PI / 180), 0.0001F, 3.14F); + float theta = (float) ((player.getViewYRot(partialTick) + 90) * Math.PI / 180); + float phi = Mth.clamp((float) ((player.getViewXRot(partialTick) + 90) * Math.PI / 180), 0.0001F, 3.14F); - Vec3 playervec = this.mc.cameraEntity - .getEyePosition(event.getPartialTick()) - .add(rho * Mth.sin(phi) * Mth.cos(theta), rho * Mth.cos(phi) - 0.35F, rho * Mth.sin(phi) * Mth.sin(theta)); + Vec3 playervec = mc.cameraEntity.getEyePosition(partialTick).add(rho * Mth.sin(phi) * Mth.cos(theta), rho * Mth.cos(phi) - 0.35F, rho * Mth.sin(phi) * Mth.sin(theta)); /********************************************* * IRON AND STEEL LINES * @@ -218,16 +119,16 @@ public void onRenderLevelStage(final RenderLevelStageEvent event) { if ((data.isBurning(Metal.IRON) || data.isBurning(Metal.STEEL))) { - this.tracking.forEachMetallicEntity(entity -> ClientUtils.drawMetalLine(stack, playervec, entity.position(), 1.5F, 0F, 0.6F, 1F)); + tracking.forEachMetallicEntity(entity -> Rendering.drawMetalLine(stack, playervec, entity.position(), 1.5F, 0F, 0.6F, 1F)); - this.tracking.forEachMetalBlob(blob -> ClientUtils.drawMetalLine(stack, playervec, blob.getCenter(), Mth.clamp(0.3F + blob.size() * 0.4F, 0.5F, 7.5F), 0F, 0.6F, 1F)); + tracking.forEachMetalBlob(blob -> Rendering.drawMetalLine(stack, playervec, blob.getCenter(), Mth.clamp(0.3F + blob.size() * 0.4F, 0.5F, 7.5F), 0F, 0.6F, 1F)); } /********************************************* * BRONZE LINES * *********************************************/ if ((data.isBurning(Metal.BRONZE) && (data.isEnhanced() || !data.isBurning(Metal.COPPER)))) { - this.tracking.forEachSeeked(playerEntity -> ClientUtils.drawMetalLine(stack, playervec, playerEntity.position(), 5.0F, 0.7F, 0.15F, 0.15F)); + tracking.forEachSeeked(playerEntity -> Rendering.drawMetalLine(stack, playervec, playerEntity.position(), 5.0F, 0.7F, 0.15F, 0.15F)); } /********************************************* @@ -236,7 +137,7 @@ public void onRenderLevelStage(final RenderLevelStageEvent event) { if (data.isBurning(Metal.GOLD)) { ResourceKey deathDim = data.getDeathDim(); if (deathDim != null && player.level().dimension() == deathDim) { - ClientUtils.drawMetalLine(stack, playervec, Vec3.atCenterOf(data.getDeathLoc()), 3.0F, 0.9F, 0.85F, 0.0F); + Rendering.drawMetalLine(stack, playervec, Vec3.atCenterOf(data.getDeathLoc()), 3.0F, 0.9F, 0.85F, 0.0F); } } if (data.isBurning(Metal.ELECTRUM)) { @@ -244,48 +145,19 @@ public void onRenderLevelStage(final RenderLevelStageEvent event) { if (spawnDim == null && player.level().dimension() == Level.OVERWORLD) { // overworld, no spawn --> use world spawn var levelData = player.level().getLevelData(); BlockPos spawnLoc = new BlockPos(levelData.getXSpawn(), levelData.getYSpawn(), levelData.getZSpawn()); - ClientUtils.drawMetalLine(stack, playervec, Vec3.atCenterOf(spawnLoc), 3.0F, 0.7F, 0.8F, 0.2F); + Rendering.drawMetalLine(stack, playervec, Vec3.atCenterOf(spawnLoc), 3.0F, 0.7F, 0.8F, 0.2F); } else if (spawnDim != null && player.level().dimension() == spawnDim) { - ClientUtils.drawMetalLine(stack, playervec, Vec3.atCenterOf(data.getSpawnLoc()), 3.0F, 0.7F, 0.8F, 0.2F); + Rendering.drawMetalLine(stack, playervec, Vec3.atCenterOf(data.getSpawnLoc()), 3.0F, 0.7F, 0.8F, 0.2F); } } - teardownPoseStack(stack); - - } - - private static void teardownPoseStack(PoseStack stack) { - stack.popPose(); - RenderSystem.applyModelViewMatrix(); - - RenderSystem.disableBlend(); - RenderSystem.enablePolygonOffset(); - RenderSystem.enableDepthTest(); - RenderSystem.depthMask(true); - RenderSystem.enableCull(); + Rendering.doneDrawingLines(stack); } - private PoseStack setupPoseStack(final RenderLevelStageEvent event) { - RenderSystem.setShader(GameRenderer::getRendertypeLinesShader); - RenderSystem.disableDepthTest(); - RenderSystem.depthMask(false); - RenderSystem.disableCull(); - RenderSystem.enableBlend(); - RenderSystem.disablePolygonOffset(); - RenderSystem.defaultBlendFunc(); - - PoseStack stack = event.getPoseStack(); - stack.pushPose(); - Vec3 view = this.mc.cameraEntity.getEyePosition(event.getPartialTick()); - stack.translate(-view.x, -view.y, -view.z); - RenderSystem.applyModelViewMatrix(); - return stack; - } - @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void onFovCompute(final ComputeFovModifierEvent event) { + public static void onFovCompute(final ComputeFovModifierEvent event) { var data = event.getPlayer().getData(AllomancerAttachment.ALLOMANCY_DATA); // tin and duralumin give a zoom effect if (data.isBurning(Metal.TIN) && data.isEnhanced()) { @@ -295,70 +167,28 @@ public void onFovCompute(final ComputeFovModifierEvent event) { @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void onSound(final PlaySoundEvent event) { + public static void onSound(final PlaySoundEvent event) { - Player player = this.mc.player; + Player player = Minecraft.getInstance().player; SoundInstance sound = event.getSound(); if ((player == null) || (sound == null) || !player.isAlive()) { return; } var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); - double motionX, motionY, motionZ, magnitude; - if (data.isBurning(Metal.TIN)) { - - magnitude = Math.sqrt(player.position().distanceToSqr(sound.getX(), sound.getY(), sound.getZ())); - - if (((magnitude) > 25) || ((magnitude) < 3)) { - return; - } - Vec3 vec = player.position(); - double posX = vec.x(), posY = vec.y(), posZ = vec.z(); - // Spawn sound particles - String soundName = sound.getLocation().toString(); - if (soundName.contains("entity") || soundName.contains("step")) { - motionX = ((posX - (event.getSound().getX() + .5)) * -0.7) / magnitude; - motionY = ((posY - (event.getSound().getY() + .2)) * -0.7) / magnitude; - motionZ = ((posZ - (event.getSound().getZ() + .5)) * -0.7) / magnitude; - this.mc.particleEngine.createParticle(new SoundParticleData(sound.getSource()), posX + (Math.sin(Math.toRadians(player.getYHeadRot())) * -.7d), posY + .2, - posZ + (Math.cos(Math.toRadians(player.getYHeadRot())) * .7d), motionX, motionY, motionZ); - } + Sounds.spawnParticleForSound(player, sound); } } /** * Used to enable movement while the MetalSelectScreen is open */ + @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void updateInputEvent(final MovementInputUpdateEvent event) { - if (this.mc.screen instanceof MetalSelectScreen) { - Options options = this.mc.options; - Input eInput = event.getInput(); - float f = Mth.clamp(0.3F + EnchantmentHelper.getSneakingSpeedBonus(this.mc.player), 0.0F, 1.0F); - // from KeyboardInput#tick - eInput.up = InputConstants.isKeyDown(this.mc.getWindow().getWindow(), options.keyUp.getKey().getValue()); - eInput.down = InputConstants.isKeyDown(this.mc.getWindow().getWindow(), options.keyDown.getKey().getValue()); - eInput.left = InputConstants.isKeyDown(this.mc.getWindow().getWindow(), options.keyLeft.getKey().getValue()); - eInput.right = InputConstants.isKeyDown(this.mc.getWindow().getWindow(), options.keyRight.getKey().getValue()); - eInput.forwardImpulse = eInput.up == eInput.down ? 0.0f : (eInput.up ? 1.0f : -1.0f); - eInput.leftImpulse = eInput.left == eInput.right ? 0.0f : (eInput.left ? 1.0f : -1.0f); - eInput.jumping = InputConstants.isKeyDown(this.mc.getWindow().getWindow(), options.keyJump.getKey().getValue()); - eInput.shiftKeyDown = InputConstants.isKeyDown(this.mc.getWindow().getWindow(), options.keyShift.getKey().getValue()); - if (this.mc.player.isMovingSlowly()) { - eInput.leftImpulse *= f; - eInput.forwardImpulse *= f; - } - - // from LocalPlayer#aiStep - if (!this.mc.player.isSprinting() && - (!(this.mc.player.isInWater() || this.mc.player.isInFluidType((fluidType, height) -> this.mc.player.canSwimInFluidType(fluidType))) || - (this.mc.player.isUnderWater() || this.mc.player.canStartSwimming())) && eInput.forwardImpulse >= 0.8 && !this.mc.player.isUsingItem() && - (this.mc.player.getFoodData().getFoodLevel() > 6.0F || this.mc.player.getAbilities().mayfly) && !this.mc.player.hasEffect(MobEffects.BLINDNESS) && - InputConstants.isKeyDown(this.mc.getWindow().getWindow(), options.keySprint.getKey().getValue())) { - this.mc.player.setSprinting(true); - } + public static void updateInputEvent(final MovementInputUpdateEvent event) { + if (Minecraft.getInstance().screen instanceof MetalSelectScreen) { + Inputs.fakeMovement(event.getInput()); } } - } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/PowersClientSetup.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/PowersClientSetup.java index fffe6c6e..a323441e 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/client/PowersClientSetup.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/PowersClientSetup.java @@ -1,20 +1,16 @@ package com.legobmw99.allomancy.modules.powers.client; import com.legobmw99.allomancy.Allomancy; -import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.powers.client.particle.SoundParticle; import com.legobmw99.allomancy.modules.powers.client.particle.SoundParticleData; import com.mojang.serialization.Codec; -import net.minecraft.client.KeyMapping; import net.minecraft.core.particles.ParticleType; import net.minecraft.core.registries.Registries; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; +import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent; +import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.registries.DeferredRegister; -import org.lwjgl.glfw.GLFW; import java.util.function.Supplier; @@ -27,29 +23,6 @@ public Codec codec() { return SoundParticleData.CODEC; } }); - @OnlyIn(Dist.CLIENT) - public static KeyMapping hud; - - @OnlyIn(Dist.CLIENT) - public static KeyMapping burn; - - @OnlyIn(Dist.CLIENT) - public static KeyMapping[] powers; - - public static void registerKeyBinding(final RegisterKeyMappingsEvent evt) { - burn = new KeyMapping("key.burn", GLFW.GLFW_KEY_V, "key.categories.allomancy"); - hud = new KeyMapping("key.hud", GLFW.GLFW_KEY_UNKNOWN, "key.categories.allomancy"); - evt.register(burn); - evt.register(hud); - - powers = new KeyMapping[Metal.values().length]; - for (int i = 0; i < powers.length; i++) { - powers[i] = new KeyMapping("key.metals." + Metal.getMetal(i).name().toLowerCase(), GLFW.GLFW_KEY_UNKNOWN, "key.categories.allomancy"); - evt.register(powers[i]); - } - - - } public static void register(IEventBus bus) { PARTICLES.register(bus); @@ -60,4 +33,9 @@ public static void registerParticle(final RegisterParticleProvidersEvent event) event.registerSprite(PowersClientSetup.SOUND_PARTICLE_TYPE.get(), new SoundParticle.Factory()); } + public static void clientInit(final FMLClientSetupEvent e) { + e.enqueueWork(() -> { + NeoForge.EVENT_BUS.register(ClientEventHandler.class); + }); + } } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/gui/MetalSelectScreen.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/gui/MetalSelectScreen.java index 4e4ed6a2..6da3dfcb 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/client/gui/MetalSelectScreen.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/gui/MetalSelectScreen.java @@ -11,8 +11,8 @@ import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.powers.PowersConfig; -import com.legobmw99.allomancy.modules.powers.client.PowersClientSetup; -import com.legobmw99.allomancy.modules.powers.client.util.ClientUtils; +import com.legobmw99.allomancy.modules.powers.client.network.PowerRequests; +import com.legobmw99.allomancy.modules.powers.client.util.Inputs; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferBuilder; @@ -177,7 +177,7 @@ public void tick() { // tick @Override public boolean keyReleased(int keysym, int scancode, int modifiers) { - if (PowersClientSetup.burn.matches(keysym, scancode)) { + if (Inputs.burn.matches(keysym, scancode)) { this.mc.setScreen(null); this.mc.mouseHandler.grabMouse(); return true; @@ -188,7 +188,7 @@ public boolean keyReleased(int keysym, int scancode, int modifiers) { @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (PowersClientSetup.burn.matchesMouse(button)) { + if (Inputs.burn.matchesMouse(button)) { this.mc.setScreen(null); this.mc.mouseHandler.grabMouse(); return true; @@ -204,7 +204,7 @@ private void toggleSelected() { if (this.slotSelected != -1) { Metal mt = Metal.getMetal(toMetalIndex(this.slotSelected)); var data = this.mc.player.getData(AllomancerAttachment.ALLOMANCY_DATA); - ClientUtils.toggleBurn(mt, data); + PowerRequests.toggleBurn(mt, data); this.mc.player.playSound(SoundEvents.UI_BUTTON_CLICK.value(), 0.1F, 2.0F); } } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/ClientPayloadHandler.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/network/ClientPayloadHandler.java similarity index 85% rename from src/main/java/com/legobmw99/allomancy/modules/powers/client/ClientPayloadHandler.java rename to src/main/java/com/legobmw99/allomancy/modules/powers/client/network/ClientPayloadHandler.java index c84cf231..faaa84cc 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/client/ClientPayloadHandler.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/network/ClientPayloadHandler.java @@ -1,14 +1,13 @@ -package com.legobmw99.allomancy.modules.powers.client; +package com.legobmw99.allomancy.modules.powers.client.network; import com.legobmw99.allomancy.Allomancy; import com.legobmw99.allomancy.api.enums.Metal; +import com.legobmw99.allomancy.modules.powers.client.util.Sounds; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; import com.legobmw99.allomancy.modules.powers.network.AllomancerDataPayload; import com.legobmw99.allomancy.modules.powers.network.EnhanceTimePayload; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvent; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.network.handling.PlayPayloadContext; @@ -17,7 +16,7 @@ public class ClientPayloadHandler { - public static void handleAllomancerData(final AllomancerDataPayload payload, final PlayPayloadContext ctx) { + public static void updateAllomancer(final AllomancerDataPayload payload, final PlayPayloadContext ctx) { ctx.workHandler().submitAsync(() -> { Player player = Minecraft.getInstance().level.getPlayerByUUID(payload.player()); if (player == Minecraft.getInstance().player) { @@ -26,7 +25,7 @@ public static void handleAllomancerData(final AllomancerDataPayload payload, fin data.deserializeNBT(payload.nbt()); long burningAfter = Arrays.stream(Metal.values()).filter(data::isBurning).count(); if (burningAfter < burningBefore) { - player.playSound(SoundEvent.createFixedRangeEvent(new ResourceLocation("block.fire.extinguish"), 1f), 1, 4); + Sounds.soundForBurnChange(false); } } else { player.getData(AllomancerAttachment.ALLOMANCY_DATA).deserializeNBT(payload.nbt()); diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/network/PowerRequests.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/network/PowerRequests.java new file mode 100644 index 00000000..0b658b75 --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/network/PowerRequests.java @@ -0,0 +1,89 @@ +package com.legobmw99.allomancy.modules.powers.client.network; + +import com.legobmw99.allomancy.api.data.IAllomancerData; +import com.legobmw99.allomancy.api.enums.Metal; +import com.legobmw99.allomancy.modules.combat.CombatSetup; +import com.legobmw99.allomancy.modules.powers.client.util.Sounds; +import com.legobmw99.allomancy.modules.powers.data.AllomancerData; +import com.legobmw99.allomancy.modules.powers.network.*; +import com.legobmw99.allomancy.modules.powers.util.Physical; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.neoforged.neoforge.network.PacketDistributor; + +public class PowerRequests { + /** + * Used to toggle a metal's burn state and play a sound effect + * + * @param metal the index of the metal to toggle + * @param data the Allomancer data of the player + */ + public static void toggleBurn(Metal metal, IAllomancerData data) { + if (!data.hasPower(metal)) { + return; + } + + if (data.getStored(metal) > 0) { + data.setBurning(metal, !data.isBurning(metal)); + } + + sendToServer(new ToggleBurnPayload(metal, data.isBurning(metal))); + + Sounds.soundForBurnChange(data.isBurning(metal)); + } + + public static void emotionPushPull(IAllomancerData data, HitResult trace, Metal metal) { + if (!data.isBurning(metal) || trace == null) { + return; + } + + boolean aggro = metal == Metal.ZINC; + + if (trace.getType() == HitResult.Type.ENTITY) { + Entity entity = ((EntityHitResult) trace).getEntity(); + if (entity instanceof PathfinderMob) { + sendToServer(new EmotionPayload(entity.getId(), aggro)); + } + } + } + + public static void metallicPushPull(IAllomancerData data, HitResult trace, Metal metal) { + if (!data.isBurning(metal) || trace == null) { + return; + } + + int force = (data.isEnhanced() ? 4 : 1) * (metal == Metal.STEEL ? 1 : -1); + + if (trace.getType() == HitResult.Type.ENTITY && Physical.isEntityMetallic(((EntityHitResult) trace).getEntity())) { + sendToServer(new EntityPushPullPayload(((EntityHitResult) trace).getEntity().getId(), force)); + } else if (trace.getType() == HitResult.Type.BLOCK) { + BlockPos bp = ((BlockHitResult) trace).getBlockPos(); + Player player = Minecraft.getInstance().player; + if (Physical.isBlockStateMetallic(player.level().getBlockState(bp)) || (player.getMainHandItem().getItem() == CombatSetup.COIN_BAG.get() && player.isCrouching())) { + sendToServer(new BlockPushPullPayload(bp, force)); + } + } + } + + public static void nicrosilEnhance(AllomancerData data, HitResult trace) { + if (data.isBurning(Metal.NICROSIL)) { + if ((trace != null) && (trace.getType() == HitResult.Type.ENTITY)) { + Entity entity = ((EntityHitResult) trace).getEntity(); + if (entity instanceof Player) { + sendToServer(new EnhanceTimePayload(true, entity.getId())); + } + } + } + } + + private static void sendToServer(CustomPacketPayload msg) { + PacketDistributor.SERVER.noArg().send(msg); + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/ClientUtils.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/ClientUtils.java deleted file mode 100644 index 72acb545..00000000 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/ClientUtils.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.legobmw99.allomancy.modules.powers.client.util; - -import com.legobmw99.allomancy.api.data.IAllomancerData; -import com.legobmw99.allomancy.api.enums.Metal; -import com.legobmw99.allomancy.modules.powers.network.ToggleBurnPayload; -import com.legobmw99.allomancy.network.Network; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.projectile.ProjectileUtil; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.EntityHitResult; -import net.minecraft.world.phys.HitResult; -import net.minecraft.world.phys.Vec3; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.api.distmarker.OnlyIn; -import org.joml.Matrix4f; - -import javax.annotation.Nullable; - -@OnlyIn(Dist.CLIENT) -public class ClientUtils { - - private static Minecraft mc = Minecraft.getInstance(); - private static final LocalPlayer player = mc.player; - - /** - * Adapted from vanilla, allows getting mouseover at given distances - * - * @param dist the distance requested - * @return a RayTraceResult for the requested raytrace - */ - @Nullable - public static HitResult getMouseOverExtended(float dist) { - mc = Minecraft.getInstance(); - float partialTicks = mc.getFrameTime(); - HitResult objectMouseOver = null; - Entity entity = mc.getCameraEntity(); - if (entity != null) { - if (mc.level != null) { - objectMouseOver = entity.pick(dist, partialTicks, false); - Vec3 vec3d = entity.getEyePosition(partialTicks); - boolean flag = false; - int i = 3; - double d1; - - d1 = objectMouseOver.getLocation().distanceToSqr(vec3d); - - Vec3 vec3d1 = entity.getViewVector(1.0F); - Vec3 vec3d2 = vec3d.add(vec3d1.x * dist, vec3d1.y * dist, vec3d1.z * dist); - float f = 1.0F; - AABB axisalignedbb = entity.getBoundingBox().expandTowards(vec3d1.scale(dist)).inflate(1.0D, 1.0D, 1.0D); - EntityHitResult entityraytraceresult = ProjectileUtil.getEntityHitResult(entity, vec3d, vec3d2, axisalignedbb, (e) -> true, d1); - if (entityraytraceresult != null) { - Entity entity1 = entityraytraceresult.getEntity(); - Vec3 vec3d3 = entityraytraceresult.getLocation(); - double d2 = vec3d.distanceToSqr(vec3d3); - if (d2 < d1) { - objectMouseOver = entityraytraceresult; - } - } - - } - } - return objectMouseOver; - - } - - /** - * Draws a line from the player (denoted pX,Y,Z) to the given set of - * coordinates (oX,Y,Z) in a certain color (r,g,b) - * - * @param player - * @param dest - * @param width the width of the line - */ - public static void drawMetalLine(PoseStack stack, Vec3 player, Vec3 dest, float width, float r, float g, float b) { - - // RenderSystem.lineWidth(width); - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder builder = tessellator.getBuilder(); - - builder.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR); - Matrix4f matrix4f = stack.last().pose(); - builder.vertex(matrix4f, (float) player.x, (float) player.y, (float) player.z).color(r, g, b, 0.6f).endVertex(); - builder.vertex(matrix4f, (float) dest.x, (float) dest.y, (float) dest.z).color(r, g, b, 0.6f).endVertex(); - RenderSystem.lineWidth(width); - - tessellator.end(); - - } - - - /** - * Used to toggle a metal's burn state and play a sound effect - * - * @param metal the index of the metal to toggle - * @param data the Allomancer data of the player - */ - public static void toggleBurn(Metal metal, IAllomancerData data) { - if (!data.hasPower(metal)) { - return; - } - - if (data.getStored(metal) > 0) { - data.setBurning(metal, !data.isBurning(metal)); - } - - Network.sendToServer(new ToggleBurnPayload(metal, data.isBurning(metal))); - - // play a sound effect - if (data.isBurning(metal)) { - player.playSound(SoundEvent.createFixedRangeEvent(new ResourceLocation("item.flintandsteel.use"), 1f), 1, 5); - } else { - player.playSound(SoundEvent.createFixedRangeEvent(new ResourceLocation("block.fire.extinguish"), 1f), 1, 4); - } - } -} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Inputs.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Inputs.java new file mode 100644 index 00000000..d3aa61b3 --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Inputs.java @@ -0,0 +1,160 @@ +package com.legobmw99.allomancy.modules.powers.client.util; + +import com.legobmw99.allomancy.api.enums.Metal; +import com.legobmw99.allomancy.modules.powers.PowersConfig; +import com.legobmw99.allomancy.modules.powers.client.gui.MetalSelectScreen; +import com.legobmw99.allomancy.modules.powers.client.network.PowerRequests; +import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.minecraft.client.Options; +import net.minecraft.client.player.Input; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.ProjectileUtil; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; +import org.lwjgl.glfw.GLFW; + +import javax.annotation.Nullable; + +@OnlyIn(Dist.CLIENT) +public class Inputs { + + @OnlyIn(Dist.CLIENT) + public static KeyMapping hud; + @OnlyIn(Dist.CLIENT) + public static KeyMapping burn; + @OnlyIn(Dist.CLIENT) + public static KeyMapping[] powers; + + /** + * Adapted from vanilla, allows getting mouseover at given distances + * + * @param dist the distance requested + * @return a RayTraceResult for the requested raytrace + */ + @Nullable + public static HitResult getMouseOverExtended(float dist) { + var mc = Minecraft.getInstance(); + float partialTicks = mc.getFrameTime(); + HitResult objectMouseOver = null; + Entity entity = mc.getCameraEntity(); + if (entity != null) { + if (mc.level != null) { + objectMouseOver = entity.pick(dist, partialTicks, false); + Vec3 vec3d = entity.getEyePosition(partialTicks); + boolean flag = false; + int i = 3; + double d1; + + d1 = objectMouseOver.getLocation().distanceToSqr(vec3d); + + Vec3 vec3d1 = entity.getViewVector(1.0F); + Vec3 vec3d2 = vec3d.add(vec3d1.x * dist, vec3d1.y * dist, vec3d1.z * dist); + float f = 1.0F; + AABB axisalignedbb = entity.getBoundingBox().expandTowards(vec3d1.scale(dist)).inflate(1.0D, 1.0D, 1.0D); + EntityHitResult entityraytraceresult = ProjectileUtil.getEntityHitResult(entity, vec3d, vec3d2, axisalignedbb, (e) -> true, d1); + if (entityraytraceresult != null) { + Entity entity1 = entityraytraceresult.getEntity(); + Vec3 vec3d3 = entityraytraceresult.getLocation(); + double d2 = vec3d.distanceToSqr(vec3d3); + if (d2 < d1) { + objectMouseOver = entityraytraceresult; + } + } + + } + } + return objectMouseOver; + + } + + public static void fakeMovement(Input input) { + Options options = Minecraft.getInstance().options; + LocalPlayer player = Minecraft.getInstance().player; + float f = Mth.clamp(0.3F + EnchantmentHelper.getSneakingSpeedBonus(player), 0.0F, 1.0F); + var window = Minecraft.getInstance().getWindow().getWindow(); + // from KeyboardInput#tick + input.up = InputConstants.isKeyDown(window, options.keyUp.getKey().getValue()); + input.down = InputConstants.isKeyDown(window, options.keyDown.getKey().getValue()); + input.left = InputConstants.isKeyDown(window, options.keyLeft.getKey().getValue()); + input.right = InputConstants.isKeyDown(window, options.keyRight.getKey().getValue()); + input.forwardImpulse = input.up == input.down ? 0.0f : (input.up ? 1.0f : -1.0f); + input.leftImpulse = input.left == input.right ? 0.0f : (input.left ? 1.0f : -1.0f); + input.jumping = InputConstants.isKeyDown(window, options.keyJump.getKey().getValue()); + input.shiftKeyDown = InputConstants.isKeyDown(window, options.keyShift.getKey().getValue()); + if (player.isMovingSlowly()) { + input.leftImpulse *= f; + input.forwardImpulse *= f; + } + + // from LocalPlayer#aiStep + if (!player.isSprinting() && + (!(player.isInWater() || player.isInFluidType((fluidType, height) -> player.canSwimInFluidType(fluidType))) || (player.isUnderWater() || player.canStartSwimming())) && + input.forwardImpulse >= 0.8 && !player.isUsingItem() && (player.getFoodData().getFoodLevel() > 6.0F || player.getAbilities().mayfly) && + !player.hasEffect(MobEffects.BLINDNESS) && InputConstants.isKeyDown(window, options.keySprint.getKey().getValue())) { + player.setSprinting(true); + } + } + + public static void registerKeyBinding(final RegisterKeyMappingsEvent evt) { + burn = new KeyMapping("key.burn", GLFW.GLFW_KEY_V, "key.categories.allomancy"); + hud = new KeyMapping("key.hud", GLFW.GLFW_KEY_UNKNOWN, "key.categories.allomancy"); + evt.register(burn); + evt.register(hud); + + powers = new KeyMapping[Metal.values().length]; + for (int i = 0; i < powers.length; i++) { + powers[i] = new KeyMapping("key.metals." + Metal.getMetal(i).name().toLowerCase(), GLFW.GLFW_KEY_UNKNOWN, "key.categories.allomancy"); + evt.register(powers[i]); + } + + } + + + public static void acceptAllomancyKeybinds() { + Minecraft mc = Minecraft.getInstance(); + if (mc.screen != null) { + return; + } + Player player = mc.player; + if (player == null || !mc.isWindowActive()) { + return; + } + + if (hud.isDown()) { + PowersConfig.enable_overlay.set(!PowersConfig.enable_overlay.get()); + return; + } + var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); + + for (int i = 0; i < powers.length; i++) { + if (powers[i].isDown()) { + PowerRequests.toggleBurn(Metal.getMetal(i), data); + } + } + if (burn.isDown()) { + switch (data.getPowerCount()) { + case 0: + break; + case 1: + PowerRequests.toggleBurn(data.getPowers()[0], data); + break; + default: + mc.setScreen(new MetalSelectScreen()); + break; + } + } + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Rendering.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Rendering.java new file mode 100644 index 00000000..b60b5d9d --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Rendering.java @@ -0,0 +1,62 @@ +package com.legobmw99.allomancy.modules.powers.client.util; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4f; + +public class Rendering { + /** + * Draws a line from the player (denoted pX,Y,Z) to the given set of + * coordinates (oX,Y,Z) in a certain color (r,g,b) + * + * @param player + * @param dest + * @param width the width of the line + */ + public static void drawMetalLine(PoseStack stack, Vec3 player, Vec3 dest, float width, float r, float g, float b) { + + // RenderSystem.lineWidth(width); + Tesselator tessellator = Tesselator.getInstance(); + BufferBuilder builder = tessellator.getBuilder(); + + builder.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR); + Matrix4f matrix4f = stack.last().pose(); + builder.vertex(matrix4f, (float) player.x, (float) player.y, (float) player.z).color(r, g, b, 0.6f).endVertex(); + builder.vertex(matrix4f, (float) dest.x, (float) dest.y, (float) dest.z).color(r, g, b, 0.6f).endVertex(); + RenderSystem.lineWidth(width); + + tessellator.end(); + + } + + public static void doneDrawingLines(PoseStack stack) { + stack.popPose(); + RenderSystem.applyModelViewMatrix(); + + RenderSystem.disableBlend(); + RenderSystem.enablePolygonOffset(); + RenderSystem.enableDepthTest(); + RenderSystem.depthMask(true); + RenderSystem.enableCull(); + + } + + public static PoseStack prepareToDrawLines(PoseStack start, float partialTicks) { + RenderSystem.setShader(GameRenderer::getRendertypeLinesShader); + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.disableCull(); + RenderSystem.enableBlend(); + RenderSystem.disablePolygonOffset(); + RenderSystem.defaultBlendFunc(); + + start.pushPose(); + Vec3 view = Minecraft.getInstance().cameraEntity.getEyePosition(partialTicks); + start.translate(-view.x, -view.y, -view.z); + RenderSystem.applyModelViewMatrix(); + return start; + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Sounds.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Sounds.java new file mode 100644 index 00000000..8495ef79 --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Sounds.java @@ -0,0 +1,41 @@ +package com.legobmw99.allomancy.modules.powers.client.util; + +import com.legobmw99.allomancy.modules.powers.client.particle.SoundParticleData; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.Vec3; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public class Sounds { + public static void soundForBurnChange(boolean burning) { + if (burning) { + Minecraft.getInstance().player.playSound(SoundEvent.createFixedRangeEvent(new ResourceLocation("item.flintandsteel.use"), 1f), 1, 5); + } else { + Minecraft.getInstance().player.playSound(SoundEvent.createFixedRangeEvent(new ResourceLocation("block.fire.extinguish"), 1f), 1, 4); + } + } + + public static void spawnParticleForSound(Player player, SoundInstance sound) { + double magnitude = Math.sqrt(player.position().distanceToSqr(sound.getX(), sound.getY(), sound.getZ())); + + if (((magnitude) > 25) || ((magnitude) < 3)) { + return; + } + Vec3 vec = player.position(); + double posX = vec.x(), posY = vec.y(), posZ = vec.z(); + // Spawn sound particles + String soundName = sound.getLocation().toString(); + if (soundName.contains("entity") || soundName.contains("step")) { + double motionX = ((posX - (sound.getX() + .5)) * -0.7) / magnitude; + double motionY = ((posY - (sound.getY() + .2)) * -0.7) / magnitude; + double motionZ = ((posZ - (sound.getZ() + .5)) * -0.7) / magnitude; + Minecraft.getInstance().particleEngine.createParticle(new SoundParticleData(sound.getSource()), posX + (Math.sin(Math.toRadians(player.getYHeadRot())) * -.7d), + posY + .2, posZ + (Math.cos(Math.toRadians(player.getYHeadRot())) * .7d), motionX, motionY, motionZ); + } + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/SensoryTracking.java b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Tracking.java similarity index 92% rename from src/main/java/com/legobmw99/allomancy/modules/powers/client/util/SensoryTracking.java rename to src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Tracking.java index cf193b4a..60ad2ba7 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/SensoryTracking.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/client/util/Tracking.java @@ -2,9 +2,9 @@ import com.legobmw99.allomancy.api.data.IAllomancerData; import com.legobmw99.allomancy.api.enums.Metal; -import com.legobmw99.allomancy.modules.powers.PowerUtils; import com.legobmw99.allomancy.modules.powers.PowersConfig; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; +import com.legobmw99.allomancy.modules.powers.util.Physical; import com.legobmw99.allomancy.util.SyncList; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import net.minecraft.Util; @@ -21,7 +21,7 @@ import java.util.concurrent.Future; import java.util.function.Consumer; -public class SensoryTracking { +public class Tracking { private final List metal_entities = new ArrayList<>(); private final SyncList metal_blobs = new SyncList<>(); @@ -56,7 +56,7 @@ public void tick() { // Add metal entities to metal list this.metal_entities.clear(); this.metal_entities.addAll( - player.level().getEntitiesOfClass(Entity.class, AABB.encapsulatingFullBlocks(negative, positive), e -> PowerUtils.isEntityMetal(e) && !e.equals(player))); + player.level().getEntitiesOfClass(Entity.class, AABB.encapsulatingFullBlocks(negative, positive), e -> Physical.isEntityMetallic(e) && !e.equals(player))); // Add metal blobs to metal list if (this.blobFuture == null || this.blobFuture.isDone()) { @@ -86,7 +86,7 @@ public void tick() { var nearby_players = player.level().getEntitiesOfClass(Player.class, new AABB(negative, positive), entity -> entity != null && entity != player); for (Player otherPlayer : nearby_players) { - if (!addSeeked(data, otherPlayer)) { + if (!seek(data, otherPlayer)) { this.nearby_allomancers.clear(); break; } @@ -99,7 +99,7 @@ public void tick() { */ private void searchNearbyMetalBlocks(BlockPos origin, int range, BlockPos starter, Level level) { var starterState = level.getBlockState(starter); - if (!this.seen.add(starter.asLong()) || !PowerUtils.isBlockStateMetal(starterState)) { + if (!this.seen.add(starter.asLong()) || !Physical.isBlockStateMetallic(starterState)) { return; } var blob = new MetalBlockBlob(starter, starterState); @@ -116,7 +116,7 @@ private void searchNearbyMetalBlocks(BlockPos origin, int range, BlockPos starte for (var next : BlockPos.withinManhattan(pos, 1, 1, 1)) { if (this.seen.add(next.asLong()) && origin.distToCenterSqr(next.getCenter()) < range_sqr) { var nextState = level.getBlockState(next); - if (PowerUtils.isBlockStateMetal(nextState)) { + if (Physical.isBlockStateMetallic(nextState)) { blob.add(next, nextState); this.to_consider.add(next.immutable()); } @@ -126,7 +126,7 @@ private void searchNearbyMetalBlocks(BlockPos origin, int range, BlockPos starte this.metal_blobs.add(blob); } - private boolean addSeeked(IAllomancerData data, Player otherPlayer) { + private boolean seek(IAllomancerData data, Player otherPlayer) { var otherData = otherPlayer.getData(AllomancerAttachment.ALLOMANCY_DATA); if (otherData.isBurning(Metal.COPPER) && (!data.isEnhanced() || otherData.isEnhanced())) { return false; diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java b/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java index 9cf59d0a..b655cd80 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/network/EntityPushPullPayload.java @@ -5,7 +5,7 @@ import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; -public record EntityPushPullPayload(int entityID, int direction) implements CustomPacketPayload { +public record EntityPushPullPayload(int entityID, int force) implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(Allomancy.MODID, "entity_push_pull"); @@ -16,11 +16,11 @@ public EntityPushPullPayload(FriendlyByteBuf buf) { @Override public void write(FriendlyByteBuf buf) { buf.writeInt(this.entityID); - buf.writeInt(this.direction); + buf.writeInt(this.force); } public boolean isPush() { - return this.direction > 0; + return this.force > 0; } @Override diff --git a/src/main/java/com/legobmw99/allomancy/network/Network.java b/src/main/java/com/legobmw99/allomancy/modules/powers/network/Network.java similarity index 78% rename from src/main/java/com/legobmw99/allomancy/network/Network.java rename to src/main/java/com/legobmw99/allomancy/modules/powers/network/Network.java index 7729901b..9edfd6c9 100644 --- a/src/main/java/com/legobmw99/allomancy/network/Network.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/network/Network.java @@ -1,8 +1,7 @@ -package com.legobmw99.allomancy.network; +package com.legobmw99.allomancy.modules.powers.network; import com.legobmw99.allomancy.Allomancy; -import com.legobmw99.allomancy.modules.powers.client.ClientPayloadHandler; -import com.legobmw99.allomancy.modules.powers.network.*; +import com.legobmw99.allomancy.modules.powers.client.network.ClientPayloadHandler; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.PacketDistributor; @@ -14,8 +13,8 @@ public class Network { public static void registerPayloads(final RegisterPayloadHandlerEvent event) { final IPayloadRegistrar registrar = event.registrar(Allomancy.MODID).versioned("2.0"); - registrar.play(AllomancerDataPayload.ID, AllomancerDataPayload::new, handler -> handler.client(ClientPayloadHandler::handleAllomancerData)); - registrar.play(EmotionPayload.ID, EmotionPayload::new, handler -> handler.server(ServerPayloadHandler::handleEmotionChange)); + registrar.play(AllomancerDataPayload.ID, AllomancerDataPayload::new, handler -> handler.client(ClientPayloadHandler::updateAllomancer)); + registrar.play(EmotionPayload.ID, EmotionPayload::new, handler -> handler.server(ServerPayloadHandler::changeEmotion)); registrar.play(BlockPushPullPayload.ID, BlockPushPullPayload::new, handler -> handler.server(ServerPayloadHandler::tryPushPullBlock)); registrar.play(EntityPushPullPayload.ID, EntityPushPullPayload::new, handler -> handler.server(ServerPayloadHandler::tryPushPullEntity)); registrar.play(ToggleBurnPayload.ID, ToggleBurnPayload::new, handler -> handler.server(ServerPayloadHandler::toggleBurnRequest)); @@ -24,10 +23,6 @@ public static void registerPayloads(final RegisterPayloadHandlerEvent event) { } - public static void sendToServer(CustomPacketPayload msg) { - PacketDistributor.SERVER.noArg().send(msg); - } - public static void syncAllomancerData(ServerPlayer player) { sync(new AllomancerDataPayload(player), player); } diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java b/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java index 89c2b180..aca93cd4 100644 --- a/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/network/ServerPayloadHandler.java @@ -6,9 +6,9 @@ import com.legobmw99.allomancy.api.enums.Metal; import com.legobmw99.allomancy.modules.combat.CombatSetup; import com.legobmw99.allomancy.modules.extras.ExtrasSetup; -import com.legobmw99.allomancy.modules.powers.PowerUtils; import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; -import com.legobmw99.allomancy.network.Network; +import com.legobmw99.allomancy.modules.powers.util.Emotional; +import com.legobmw99.allomancy.modules.powers.util.Physical; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; @@ -29,7 +29,7 @@ public class ServerPayloadHandler { - public static void handleEmotionChange(final EmotionPayload data, final PlayPayloadContext ctx) { + public static void changeEmotion(final EmotionPayload data, final PlayPayloadContext ctx) { ctx.workHandler().submitAsync(() -> { ServerPlayer allomancer = (ServerPlayer) ctx.player().get(); PathfinderMob target = (PathfinderMob) ctx.level().get().getEntity(data.entityID()); @@ -39,9 +39,9 @@ public static void handleEmotionChange(final EmotionPayload data, final PlayPayl boolean enhanced = allomancer.getData(AllomancerAttachment.ALLOMANCY_DATA).isEnhanced(); ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(allomancer, target, data.makeAggressive() ? Metal.ZINC : Metal.BRASS, enhanced); if (data.makeAggressive()) { - PowerUtils.riotEntity(target, allomancer, enhanced); + Emotional.riot(target, allomancer, enhanced); } else { - PowerUtils.sootheEntity(target, allomancer, enhanced); + Emotional.soothe(target, allomancer, enhanced); } }).exceptionally(e -> { Allomancy.LOGGER.error("Failed to handle changeEmotions", e); @@ -62,10 +62,10 @@ public static void tryPushPullBlock(final BlockPushPullPayload data, final PlayP BlockState blockState = level.getBlockState(pos); if (blockState.getBlock() instanceof IAllomanticallyUsableBlock block) { block.useAllomantically(blockState, level, pos, player, data.isPush()); - } else if (PowerUtils.isBlockStateMetal(blockState) // Check whitelist on server + } else if (Physical.isBlockStateMetallic(blockState) // Check whitelist on server || (player.getMainHandItem().getItem() == CombatSetup.COIN_BAG.get() // check coin bag && (!player.getProjectile(player.getMainHandItem()).isEmpty()) && data.isPush())) { - PowerUtils.move(data.direction(), player, pos); + Physical.lurch(data.direction(), player, pos); } else { Allomancy.LOGGER.warn("Illegal use of iron/steel by player: {}!", player); ctx.packetHandler().disconnect(Component.translatable("allomancy.networking.kicked", "Tried to push or pull against an non-metallic block!")); @@ -86,23 +86,23 @@ public static void tryPushPullEntity(final EntityPushPullPayload payload, final Metal which = payload.isPush() ? Metal.STEEL : Metal.IRON; if (target != null) { - if (PowerUtils.isEntityMetal(target)) { + if (Physical.isEntityMetallic(target)) { ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(player, target, which, data.isEnhanced()); // The player moves if (target instanceof IronGolem || target instanceof ItemFrame) { - PowerUtils.move(payload.direction(), player, target.blockPosition()); + Physical.lurch(payload.force(), player, target.blockPosition()); } else if (target instanceof ItemEntity || target instanceof FallingBlockEntity || target instanceof ArmorStand || (target instanceof AbstractMinecart && !target.isVehicle())) { - PowerUtils.move(payload.direction() / 2.0, target, player.blockPosition()); + Physical.lurch(payload.force() / 2.0, target, player.blockPosition()); // Split the difference } else if (!(target instanceof ThrowableItemProjectile)) { if (target instanceof ServerPlayer targetPlayer) { ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().trigger(targetPlayer, which, data.isEnhanced()); } - PowerUtils.move(payload.direction() / 2.0, target, player.blockPosition()); - PowerUtils.move(payload.direction() / 2.0, player, target.blockPosition()); + Physical.lurch(payload.force() / 2.0, target, player.blockPosition()); + Physical.lurch(payload.force() / 2.0, player, target.blockPosition()); } } } @@ -154,7 +154,7 @@ public static void updateEnhanced(final EnhanceTimePayload payload, final PlayPa ExtrasSetup.METAL_USED_ON_ENTITY_TRIGGER.get().trigger(source, e, Metal.NICROSIL, data.isEnhanced()); if (e instanceof ServerPlayer target) { ExtrasSetup.METAL_USED_ON_PLAYER_TRIGGER.get().trigger(target, Metal.NICROSIL, data.isEnhanced()); - if (!PowerUtils.hasTinFoilHat(target)) { + if (!Emotional.hasTinFoilHat(target)) { target.getData(AllomancerAttachment.ALLOMANCY_DATA).setEnhanced(payload.enhanceTime()); // broadcast back to player and tracking Network.sync(payload, target); diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/util/Emotional.java b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Emotional.java new file mode 100644 index 00000000..9d3a57a3 --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Emotional.java @@ -0,0 +1,136 @@ +package com.legobmw99.allomancy.modules.powers.util; + +import com.legobmw99.allomancy.Allomancy; +import com.legobmw99.allomancy.modules.combat.CombatSetup; +import com.legobmw99.allomancy.modules.powers.entity.ai.AIAttackOnCollideExtended; +import com.legobmw99.allomancy.modules.powers.entity.ai.AIEvilAttack; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.*; +import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.ai.goal.target.TargetGoal; +import net.minecraft.world.entity.ai.village.ReputationEventType; +import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.Sheep; +import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.monster.*; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.WanderingTrader; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; + +import java.util.function.Predicate; + +public class Emotional { + private static final Predicate isAggroGoal = (goal) -> goal instanceof SwellGoal || goal instanceof AIAttackOnCollideExtended || goal instanceof MeleeAttackGoal || + goal instanceof TargetGoal || goal instanceof PanicGoal || goal.getClass().getName().contains("Fireball") || + goal.getClass().getName().contains("Attack") || goal.getClass().getName().contains("Anger"); + + public static void riot(PathfinderMob target, Player allomancer, boolean enhanced) { + try { + if (!enhanced) { + if (hasTinFoilHat(target)) { + return; + } + //Enable Targeting goals + target.targetSelector.enableControlFlag(Goal.Flag.TARGET); + //Add new goals + target.setTarget(allomancer); + target.setLastHurtByMob(allomancer); + // TODO: try to use PrioritizedGoal::startExecuting for already hostiles + target.targetSelector.addGoal(1, new AIAttackOnCollideExtended(target, 1d, false)); + target.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(target, Player.class, false)); + target.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(target, target.getClass(), false)); + target.goalSelector.addGoal(4, new RandomLookAroundGoal(target)); + target.targetSelector.addGoal(2, new HurtByTargetGoal(target).setAlertOthers()); + if (target.getAttribute(Attributes.ATTACK_DAMAGE) != null && !(target instanceof Guardian)) { + target.goalSelector.addGoal(3, new MeleeAttackGoal(target, 1.2D, true)); + } + + target.setAggressive(true); + + if (target instanceof Creeper creeper) { + target.goalSelector.addGoal(1, new SwellGoal(creeper)); + } + if (target instanceof Rabbit rabbit) { + target.goalSelector.addGoal(1, new AIEvilAttack(rabbit)); + } + if (target instanceof AbstractSkeleton skeleton) { + target.goalSelector.addGoal(1, new RangedBowAttackGoal<>(skeleton, 1.0D, 20, 15.0F)); + } + if (target instanceof Illusioner illusioner) { + target.goalSelector.addGoal(1, new RangedBowAttackGoal<>(illusioner, 0.5D, 20, 15.0F)); + } + if (target instanceof Pillager pillager) { + target.goalSelector.addGoal(2, new RangedCrossbowAttackGoal<>(pillager, 1.0D, 8.0F)); + } + } else { + target.level().explode(target, target.position().x(), target.position().y(), target.position().z(), 1.2F, false, Level.ExplosionInteraction.MOB); + target.kill(); + } + } catch (Exception e) { + Allomancy.LOGGER.error("Failed to riot entity " + target + "! Please report this error!", e); + } + } + + public static void soothe(PathfinderMob target, Player allomancer, boolean enhanced) { + try { + if (!enhanced) { + if (hasTinFoilHat(target)) { + return; + } + + if (target.isNoAi()) { + target.setNoAi(false); + } + // Reset all current aggro goals + target.goalSelector.getRunningGoals().filter(isAggroGoal).forEach(WrappedGoal::stop); + target.targetSelector.getRunningGoals().filter(isAggroGoal).forEach(WrappedGoal::stop); + target.goalSelector.tick(); + target.targetSelector.tick(); + target.setTarget(null); + target.setLastHurtByMob(null); + //Disable targeting as a whole + target.targetSelector.disableControlFlag(Goal.Flag.TARGET); + target.setAggressive(false); + //Add new goals + target.goalSelector.addGoal(7, new LookAtPlayerGoal(target, Player.class, 6.0F)); + + if (target instanceof TamableAnimal animal) { + if (Math.random() < 0.3) { + animal.tame(allomancer); + } + } + if (target instanceof AbstractHorse horse) { + if (Math.random() < 0.3) { + horse.tameWithName(allomancer); + } + } + if (target instanceof Sheep) { + target.goalSelector.addGoal(1, new EatBlockGoal(target)); + } + if (target instanceof Villager villager) { + villager.onReputationEventFrom(ReputationEventType.TRADE, allomancer); + } + if (target instanceof WanderingTrader) { + target.goalSelector.addGoal(1, new TradeWithPlayerGoal((AbstractVillager) target)); + } + } else { // Completely remove all AI if enhanced + target.setNoAi(true); + } + + } catch (Exception e) { + Allomancy.LOGGER.error("Failed to soothe entity " + target + "! Please report this error!", e); + } + + } + + public static boolean hasTinFoilHat(LivingEntity entity) { + return entity.getItemBySlot(EquipmentSlot.HEAD).getItem() == CombatSetup.ALUMINUM_HELMET.get(); + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/util/Enhancement.java b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Enhancement.java new file mode 100644 index 00000000..5cbc70c5 --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Enhancement.java @@ -0,0 +1,109 @@ +package com.legobmw99.allomancy.modules.powers.util; + +import com.legobmw99.allomancy.api.enums.Metal; +import com.legobmw99.allomancy.modules.powers.data.AllomancerAttachment; +import com.legobmw99.allomancy.modules.powers.data.AllomancerData; +import com.legobmw99.allomancy.modules.powers.network.Network; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.common.util.ITeleporter; + +import java.util.function.Function; + +public class Enhancement { + /** + * Wipe all metals from the player and sync to tracking entities. Used by Aluminum and Nicrosil + * + * @param player The player to wipe + */ + public static void wipePlayer(Player player) { + var data = player.getData(AllomancerAttachment.ALLOMANCY_DATA); + data.drainMetals(Metal.values()); + player.removeAllEffects(); + + if (player instanceof ServerPlayer sp) { + Network.syncAllomancerData(sp); + } + } + + /** + * Teleports a player to the given dimension and blockpos + * + * @param player The player to move + * @param world The server world. Fails if clientside + * @param dimension Dimension to call {@link Entity#changeDimension} on + * @param pos BlockPos to move the player to using {@link Entity#teleportToWithTicket} + */ + private static void teleport(Player player, Level world, ResourceKey dimension, BlockPos pos) { + if (!world.isClientSide) { + if (player != null) { + if (player.isPassenger()) { + player.stopRiding(); + } + + if (player.level().dimension() != dimension) { + //change dimension + player = (Player) player.changeDimension(world.getServer().getLevel(dimension), new ITeleporter() { + @Override + public Entity placeEntity(Entity entity, ServerLevel currentWorld, ServerLevel destWorld, float yaw, Function repositionEntity) { + Entity repositionedEntity = repositionEntity.apply(false); + repositionedEntity.teleportTo(pos.getX(), pos.getY(), pos.getZ()); + return repositionedEntity; + } + }); + } + + player.teleportToWithTicket(pos.getX(), pos.getY() + 1.5, pos.getZ()); + player.fallDistance = 0.0F; + } + } + } + + public static void teleportToLastDeath(Player curPlayer, Level level, AllomancerData data) { + ResourceKey deathDim = data.getDeathDim(); + if (deathDim != null) { + teleport(curPlayer, level, deathDim, data.getDeathLoc()); + if (data.isBurning(Metal.DURALUMIN)) { + data.drainMetals(Metal.DURALUMIN); + } + data.drainMetals(Metal.GOLD); + } + } + + public static void teleportToSpawn(Player curPlayer, Level level, AllomancerData data) { + ResourceKey spawnDim = data.getSpawnDim(); + BlockPos spawnLoc; + + if (spawnDim != null) { + spawnLoc = data.getSpawnLoc(); + } else { + spawnDim = Level.OVERWORLD; // no spawn --> use world spawn + spawnLoc = new BlockPos(level.getLevelData().getXSpawn(), level.getLevelData().getYSpawn(), level.getLevelData().getZSpawn()); + + } + + teleport(curPlayer, level, spawnDim, spawnLoc); + if (data.isBurning(Metal.DURALUMIN)) { + data.drainMetals(Metal.DURALUMIN); + } + data.drainMetals(Metal.ELECTRUM); + } + + public static void wipeNearby(Player curPlayer, Level level) { + if (level instanceof ServerLevel) { + int max = 20; + Vec3 negative = curPlayer.position().add(-max, -max, -max); + Vec3 positive = curPlayer.position().add(max, max, max); + level + .getEntitiesOfClass(Player.class, new AABB(negative, positive)) + .forEach(otherPlayer -> otherPlayer.getData(AllomancerAttachment.ALLOMANCY_DATA).drainMetals(Metal.values())); + } + } +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/util/Physical.java b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Physical.java new file mode 100644 index 00000000..603ac5e5 --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Physical.java @@ -0,0 +1,282 @@ +package com.legobmw99.allomancy.modules.powers.util; + +import com.legobmw99.allomancy.Allomancy; +import com.legobmw99.allomancy.modules.combat.CombatSetup; +import com.legobmw99.allomancy.modules.combat.entity.ProjectileNuggetEntity; +import com.legobmw99.allomancy.modules.consumables.ConsumeSetup; +import com.legobmw99.allomancy.modules.powers.PowersConfig; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.IronGolem; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.WoodType; +import net.minecraft.world.phys.Vec3; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; + +public class Physical { + + + /** + * Block state wrapper on {@link Physical#isBlockMetallic} + * + * @param state BlockState to check + * @return whether the block state is metal + */ + public static boolean isBlockStateMetallic(BlockState state) { + return isBlockMetallic(state.getBlock()); + } + + /** + * Determines if a block is metal or not + * + * @param block to be checked + * @return Whether the block is metal + */ + public static boolean isBlockMetallic(Block block) { + return isOnWhitelist(BuiltInRegistries.BLOCK.getKey(block).toString()); + } + + /** + * Determines if an item is metal or not + * + * @param item to be checked + * @return Whether the item is metal + */ + public static boolean isItemMetallic(ItemStack item) { + return isOnWhitelist(BuiltInRegistries.ITEM.getKey(item.getItem()).toString()); + } + + private static boolean isOnWhitelist(String s) { + return PowersConfig.whitelist.contains(s); + } + + /** + * Determines if an entity is metal or not + * + * @param entity to be checked + * @return Whether the entity is metallic + */ + public static boolean isEntityMetallic(Entity entity) { + if (entity == null) { + return false; + } + if (entity instanceof ItemEntity item) { + return isItemMetallic(item.getItem()); + } + if (entity instanceof ItemFrame itemFrame) { + return isItemMetallic(itemFrame.getItem()); + } + if (entity instanceof FallingBlockEntity fbe) { + return isBlockStateMetallic(fbe.getBlockState()); + } + if (entity instanceof ProjectileNuggetEntity) { + return true; + } + if (entity instanceof AbstractMinecart) { + return true; + } + if (entity instanceof LivingEntity ent) { + if (ent instanceof IronGolem) { + return true; + } + if (isItemMetallic(ent.getItemInHand(InteractionHand.MAIN_HAND)) || isItemMetallic(ent.getItemInHand(InteractionHand.OFF_HAND))) { + return true; + } + for (ItemStack itemStack : ent.getArmorSlots()) { + if (isItemMetallic(itemStack)) { + return true; + } + } + } + + return false; + } + + private static final Pattern ACTIVE_METAL_REGEX = Pattern.compile( + ".*(iron|steel|tin_|pewter|zinc|brass|copper|bronze|duralumin|chromium|nicrosil|gold|electrum|cadmium|bendalloy|lead_|silver|platinum|nickle).*"); + + public static boolean doesResourceContainMetal(ResourceLocation input) { + return ACTIVE_METAL_REGEX.matcher(input.getPath()).matches(); + } + + + /** + * Move an entity either toward or away from an anchor point + * + * @param directionScalar the direction and (possibly) scalar multiple of the magnitude + * @param toMove the entity to move + * @param block the point being moved toward or away from + */ + public static void lurch(double directionScalar, Entity toMove, BlockPos block) { + + if (toMove.isPassenger()) { + toMove = toMove.getVehicle(); + } + + Vec3 motion = toMove.position().subtract(Vec3.atCenterOf(block)).normalize().scale(directionScalar * 1.1); + Vec3 mod = clamp(cutoff(motion.add(toMove.getDeltaMovement()), 0.1), abs(motion).reverse(), abs(motion)); + toMove.setDeltaMovement(mod); + toMove.hurtMarked = true; + + // Only save players from fall damage + if (toMove instanceof ServerPlayer) { + toMove.fallDistance = 0; + } + } + + /* + * Three helper functions for working with Vec3s + */ + private static Vec3 clamp(Vec3 value, Vec3 min, Vec3 max) { + return new Vec3(Mth.clamp(value.x, min.x, max.x), Mth.clamp(value.y, min.y, max.y), Mth.clamp(value.z, min.z, max.z)); + } + + private static Vec3 abs(Vec3 vec) { + return new Vec3(Math.abs(vec.x), Math.abs(vec.y), Math.abs(vec.z)); + } + + private static Vec3 cutoff(Vec3 value, double e) { + Vec3 mag = abs(value); + return new Vec3(mag.x < e ? 0 : value.x, mag.y < e ? 0 : value.y, mag.z < e ? 0 : value.z); + } + + private static HashSet defaultList; + + + // TODO? this could be a Tag one day + public static List default_whitelist() { + defaultList = new HashSet<>(); + + add(Items.BUCKET); + add(Items.LAVA_BUCKET); + add(Items.MILK_BUCKET); + add(Items.COD_BUCKET); + add(Items.PUFFERFISH_BUCKET); + add(Items.SALMON_BUCKET); + add(Items.TROPICAL_FISH_BUCKET); + add(Items.WATER_BUCKET); + add(Items.TADPOLE_BUCKET); + add(Items.AXOLOTL_BUCKET); + add(Items.POWDER_SNOW_BUCKET); + add(Items.COMPASS); + add(Items.RECOVERY_COMPASS); + add(Items.CHAINMAIL_HELMET); + add(Items.CHAINMAIL_CHESTPLATE); + add(Items.CHAINMAIL_LEGGINGS); + add(Items.CHAINMAIL_BOOTS); + add(Items.MINECART); + add(Items.CHEST_MINECART); + add(Items.HOPPER_MINECART); + add(Items.FURNACE_MINECART); + add(Items.TNT_MINECART); + add(Items.CLOCK); + add(Items.SHEARS); + add(Items.SHIELD); + add(Items.NETHERITE_INGOT); + add(Items.NETHERITE_HELMET); + add(Items.NETHERITE_CHESTPLATE); + add(Items.NETHERITE_LEGGINGS); + add(Items.NETHERITE_BOOTS); + add(Items.NETHERITE_HOE); + add(Items.NETHERITE_PICKAXE); + add(Items.NETHERITE_SHOVEL); + add(Items.NETHERITE_SWORD); + add(Items.NETHERITE_AXE); + add(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE); + add(Items.CROSSBOW); + + add(Blocks.ANVIL); + add(Blocks.CHIPPED_ANVIL); + add(Blocks.DAMAGED_ANVIL); + add(Blocks.CAULDRON); + add(Blocks.POWDER_SNOW_CAULDRON); + add(Blocks.LAVA_CAULDRON); + add(Blocks.WATER_CAULDRON); + add(Blocks.SMITHING_TABLE); + add(Blocks.STONECUTTER); + add(Blocks.CHAIN); + add(Blocks.HOPPER); + add(Blocks.PISTON_HEAD); + add(Blocks.MOVING_PISTON); + add(Blocks.STICKY_PISTON); + add(Blocks.BLAST_FURNACE); + add(Blocks.BELL); + add(Blocks.PISTON); + add(Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE); + add(Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE); + add(Blocks.RAIL); + add(Blocks.ACTIVATOR_RAIL); + add(Blocks.DETECTOR_RAIL); + add(Blocks.POWERED_RAIL); + add(Blocks.LANTERN); + add(Blocks.TRAPPED_CHEST); + add(Blocks.TRIPWIRE_HOOK); + add(Blocks.SOUL_LANTERN); + add(Blocks.NETHERITE_BLOCK); + add(Blocks.LODESTONE); + add(Blocks.GILDED_BLACKSTONE); + add(Blocks.LIGHTNING_ROD); + + add(Items.BRUSH); + + WoodType.values().forEach(wt -> { + add("minecraft:" + wt.name() + "_hanging_sign"); + add("minecraft:" + wt.name() + "_wall_hanging_sign"); + }); + + + add(ConsumeSetup.VIAL.get()); + add(ConsumeSetup.LERASIUM_NUGGET.get()); + add(ConsumeSetup.ALLOMANTIC_GRINDER.get()); + add(CombatSetup.COIN_BAG.get()); + + + BuiltInRegistries.ITEM.keySet().stream().filter(Objects::nonNull).filter(Physical::doesResourceContainMetal).forEach(Physical::add); + + BuiltInRegistries.BLOCK.keySet().stream().filter(Objects::nonNull).filter(Physical::doesResourceContainMetal).forEach(Physical::add); + + + ArrayList list = new ArrayList<>(defaultList); + list.sort(String::compareTo); + return list; + + } + + private static void add(String s) { + Allomancy.LOGGER.info("Adding " + s + " to the default whitelist!"); + defaultList.add(s); + } + + private static void add(ResourceLocation r) { + add(r.toString()); + } + + private static void add(Block block) { + add(BuiltInRegistries.BLOCK.getKey(block)); + } + + private static void add(Item item) { + add(BuiltInRegistries.ITEM.getKey(item)); + } + +} diff --git a/src/main/java/com/legobmw99/allomancy/modules/powers/util/Temporal.java b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Temporal.java new file mode 100644 index 00000000..8ea0365a --- /dev/null +++ b/src/main/java/com/legobmw99/allomancy/modules/powers/util/Temporal.java @@ -0,0 +1,69 @@ +package com.legobmw99.allomancy.modules.powers.util; + +import com.legobmw99.allomancy.api.data.IAllomancerData; +import com.legobmw99.allomancy.modules.powers.data.AllomancerData; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class Temporal { + @SuppressWarnings("unchecked") + public static void speedUpNearby(Player curPlayer, Level level, IAllomancerData data) { + curPlayer.addEffect(new MobEffectInstance(MobEffects.DIG_SPEED, 10, 3, true, false)); + + if (level instanceof ServerLevel serverLevel) { + int max = data.isEnhanced() ? 10 : 5; + BlockPos negative = curPlayer.blockPosition().offset(-max, -max, -max); + BlockPos positive = curPlayer.blockPosition().offset(max, max, max); + serverLevel.getEntitiesOfClass(LivingEntity.class, AABB.encapsulatingFullBlocks(negative, positive)).forEach(entity -> { + entity.aiStep(); + entity.aiStep(); + }); + BlockPos.betweenClosedStream(negative, positive).forEach(bp -> { + BlockState block = level.getBlockState(bp); + BlockEntity te = level.getBlockEntity(bp); + if (te == null) { + if (block.isRandomlyTicking()) { + for (int i = 0; i < max * 4 / 15; i++) { + block.randomTick(serverLevel, bp, serverLevel.random); + } + } + } else { + Block underlying_block = block.getBlock(); + if (underlying_block instanceof EntityBlock eb) { + BlockEntityTicker ticker = eb.getTicker(level, block, te.getType()); + if (ticker != null) { + for (int i = 0; i < max * 4 / 3; i++) { + ticker.tick(level, bp, block, te); + } + } + } + } + }); + } + } + + public static void slowDownNearby(Player curPlayer, Level level, AllomancerData data) { + int max = data.isEnhanced() ? 20 : 10; + Vec3 negative = curPlayer.position().add(-max, -max, -max); + Vec3 positive = curPlayer.position().add(max, max, max); + int slowness_amplifier = data.isEnhanced() ? 255 : 2; // Duralumin freezes entities + level.getEntitiesOfClass(LivingEntity.class, new AABB(negative, positive)).forEach(entity -> { + entity.addEffect(new MobEffectInstance(MobEffects.SLOW_FALLING, 10, 0, true, false)); + if (entity != curPlayer) { + entity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 10, slowness_amplifier, true, false)); + } + }); + } +} diff --git a/src/main/java/com/legobmw99/allomancy/util/SyncList.java b/src/main/java/com/legobmw99/allomancy/util/SyncList.java index 8eca82e5..6259be48 100644 --- a/src/main/java/com/legobmw99/allomancy/util/SyncList.java +++ b/src/main/java/com/legobmw99/allomancy/util/SyncList.java @@ -14,6 +14,8 @@ * Writes are issued to a list which is not currently a candidate for iteration, * and on demand this list is swapped in. The lock required to swap is only held * for the length of one atomic integer increment. + * This is a simplified version of the ideas in something like https://github.com/jonhoo/left-right/, + * but we assume a single reader that works relatively quickly, so we block do to our atomic swap */ public class SyncList { private final List list_a = new ArrayList<>();