From e994b5e837ec1806e6fc460e9c28830ced08ec24 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 21 Sep 2022 22:58:07 +0200 Subject: [PATCH] Earth ponies can now kick things other than trees --- .../ability/EarthPonyKickAbility.java | 54 +++++++++++++++---- .../ability/EarthPonyStompAbility.java | 40 ++++++++------ .../block/data/BlockDestructionManager.java | 24 +++++---- .../client/ClientBlockDestructionManager.java | 6 +-- .../unicopia/network/MsgBlockDestruction.java | 10 ++-- .../unicopia/util/MagicalDamageSource.java | 1 + .../unicopia/util/RayTraceHelper.java | 14 +++-- .../resources/assets/unicopia/lang/en_us.json | 6 ++- 8 files changed, 104 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java index 1eb00244..4b1c7410 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java @@ -15,8 +15,7 @@ import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; -import com.minelittlepony.unicopia.util.PosHelper; -import com.minelittlepony.unicopia.util.RayTraceHelper; +import com.minelittlepony.unicopia.util.*; import net.minecraft.block.BeehiveBlock; import net.minecraft.block.Block; @@ -24,12 +23,15 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BeehiveBlockEntity; import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.passive.BeeEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; +import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import net.minecraft.world.WorldEvents; /** @@ -62,18 +64,52 @@ public class EarthPonyKickAbility implements Ability { .isPresent() ? 3 : 1; } + @Override + public boolean onQuickAction(Pony player, ActivationType type) { + if (type == ActivationType.TAP) { + + if (!player.isClient()) { + Vec3d origin = player.getOriginVector(); + + Pos kickLocation = getDefaultKickLocation(player); + World w = player.getReferenceWorld(); + + for (var e : VecHelper.findInRange(player.getEntity(), w, kickLocation.vec(), 2, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR)) { + if (e instanceof LivingEntity entity) { + float calculatedStrength = 0.5F * (1 + player.getLevel().getScaled(9)); + entity.damage(MagicalDamageSource.KICK, player.getReferenceWorld().random.nextBetween(2, 10) + calculatedStrength); + entity.takeKnockback(calculatedStrength, origin.x - entity.getX(), origin.z - entity.getZ()); + player.subtractEnergyCost(3); + player.setAnimation(Animation.KICK); + return true; + } + } + + BlockPos pos = kickLocation.pos(); + EarthPonyStompAbility.stompBlock(w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.getMaster(), w, pos)); + player.setAnimation(Animation.KICK); + } + + return true; + } + + return false; + } + @Nullable @Override public Pos tryActivate(Pony player) { - double distance = MineLPDelegate.getInstance().getPlayerPonyRace(player.getMaster()).isDefault() ? 6 : -6; - - return RayTraceHelper.doTrace(player.getMaster(), distance, 1) + return RayTraceHelper.doTrace(player.getMaster(), 6 * getKickDirection(player), 1) .getBlockPos() .filter(pos -> TreeType.at(pos, player.getReferenceWorld()) != TreeType.NONE) .map(Pos::new) .orElseGet(() -> getDefaultKickLocation(player)); } + private int getKickDirection(Pony player) { + return MineLPDelegate.getInstance().getPlayerPonyRace(player.getMaster()).isDefault() ? 1 : -1; + } + private Pos getDefaultKickLocation(Pony player) { Vec3d kickVector = player.getMaster().getRotationVector().multiply(1, 0, 1); if (!MineLPDelegate.getInstance().getPlayerPonyRace(player.getMaster()).isDefault()) { @@ -115,9 +151,7 @@ public class EarthPonyKickAbility implements Ability { boolean harmed = player.getHealth() < player.getMaxHealth(); - BlockDestructionManager destr = ((BlockDestructionManager.Source)player.world).getDestructionManager(); - - if (destr.getBlockDestruction(pos) + 4 >= BlockDestructionManager.MAX_DAMAGE) { + if (BlockDestructionManager.of(player.world).getBlockDestruction(pos) + 4 >= BlockDestructionManager.MAX_DAMAGE) { if (!harmed || player.world.random.nextInt(30) == 0) { tree.traverse(player.world, pos, (w, state, p, recurseLevel) -> { if (recurseLevel < 5) { @@ -186,9 +220,7 @@ public class EarthPonyKickAbility implements Ability { } private void affectBlockChange(PlayerEntity player, BlockPos position) { - BlockDestructionManager destr = ((BlockDestructionManager.Source)player.world).getDestructionManager(); - - destr.damageBlock(position, 4); + BlockDestructionManager.of(player.world).damageBlock(position, 4); PosHelper.all(position, p -> { BlockState s = player.world.getBlockState(p); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index 09b44fd1..7ccc4257 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -163,31 +163,37 @@ public class EarthPonyStompAbility implements Ability { } public static void spawnEffect(World w, BlockPos pos, double dist, double rad) { - BlockState state = w.getBlockState(pos); - BlockDestructionManager destr = ((BlockDestructionManager.Source)w).getDestructionManager(); + if (w.getBlockState(pos.up()).isAir()) { + BlockState state = w.getBlockState(pos); - if (!state.isAir() && w.getBlockState(pos.up()).isAir()) { - - double amount = (1 - dist / rad) * 9; float hardness = state.getHardness(w, pos); float scaledHardness = (1 - hardness / 70); + float damage = hardness < 0 ? 0 : MathHelper.clamp((int)((1 - dist / rad) * 9 * scaledHardness), 0, BlockDestructionManager.MAX_DAMAGE - 1); - int damage = hardness < 0 ? 0 : MathHelper.clamp((int)(amount * scaledHardness), 2, 9); + stompBlock(w, pos, damage); + } + } - if (destr.damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE) { - w.breakBlock(pos, true); + public static void stompBlock(World w, BlockPos pos, float damage) { + BlockState state = w.getBlockState(pos); - if (w instanceof ServerWorld) { - if (state.getMaterial() == Material.STONE && w.getRandom().nextInt(4) == 0) { - ItemStack stack = UItems.PEBBLES.getDefaultStack(); - stack.setCount(1 + w.getRandom().nextInt(2)); - Block.dropStack(w, pos, stack); - state.onStacksDropped((ServerWorld)w, pos, stack, true); - } + if (state.isAir() || damage <= 0) { + return; + } + + if (BlockDestructionManager.of(w).damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE) { + w.breakBlock(pos, true); + + if (w instanceof ServerWorld) { + if (state.getMaterial() == Material.STONE && w.getRandom().nextInt(4) == 0) { + ItemStack stack = UItems.PEBBLES.getDefaultStack(); + stack.setCount(1 + w.getRandom().nextInt(2)); + Block.dropStack(w, pos, stack); + state.onStacksDropped((ServerWorld)w, pos, stack, true); } - } else { - w.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state)); } + } else { + w.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state)); } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/data/BlockDestructionManager.java b/src/main/java/com/minelittlepony/unicopia/block/data/BlockDestructionManager.java index 80d0253c..5b68ba64 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/data/BlockDestructionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/block/data/BlockDestructionManager.java @@ -30,21 +30,25 @@ public class BlockDestructionManager { return Suppliers.memoize(() -> new BlockDestructionManager(world)); } + public static BlockDestructionManager of(World world) { + return ((BlockDestructionManager.Source)world).getDestructionManager(); + } + private BlockDestructionManager(World world) { this.chunks = WorldOverlay.getOverlay(world, ID, w -> new WorldOverlay<>(world, Destruction::new, this::sendUpdates)); } - public int getBlockDestruction(BlockPos pos) { + public float getBlockDestruction(BlockPos pos) { Destruction destr = chunks.getState(pos); return destr == null ? UNSET_DAMAGE : destr.amount; } - public void setBlockDestruction(BlockPos pos, int amount) { + public void setBlockDestruction(BlockPos pos, float amount) { chunks.getOrCreateState(pos).set(amount); chunks.markDirty(); } - public int damageBlock(BlockPos pos, int amount) { + public float damageBlock(BlockPos pos, float amount) { if (amount == 0) { return getBlockDestruction(pos); } @@ -64,12 +68,12 @@ public class BlockDestructionManager { } private void sendUpdates(Long2ObjectMap destructions, List players) { - Long2ObjectOpenHashMap values = new Long2ObjectOpenHashMap<>(); + Long2ObjectOpenHashMap values = new Long2ObjectOpenHashMap<>(); destructions.forEach((blockPos, item) -> { if (item.dirty) { item.dirty = false; - values.put(blockPos.longValue(), (Integer)item.amount); + values.put(blockPos.longValue(), (Float)item.amount); } }); @@ -78,7 +82,7 @@ public class BlockDestructionManager { if (msg.toBuffer().writerIndex() > 1048576) { throw new IllegalStateException("Payload may not be larger than 1048576 bytes. Here's what we were trying to send: [" + values.size() + "]\n" - + Arrays.toString(values.values().stream().mapToInt(Integer::intValue).toArray())); + + Arrays.toString(values.values().stream().mapToDouble(Float::doubleValue).toArray())); } players.forEach(player -> { @@ -89,7 +93,7 @@ public class BlockDestructionManager { } private class Destruction implements WorldOverlay.State { - int amount = UNSET_DAMAGE; + float amount = UNSET_DAMAGE; int age = DESTRUCTION_COOLDOWN; boolean dirty; @@ -105,7 +109,7 @@ public class BlockDestructionManager { return amount < 0 || age-- <= 0; } - void set(int amount) { + void set(float amount) { this.age = DESTRUCTION_COOLDOWN; this.amount = amount >= 0 && amount < MAX_DAMAGE ? amount : UNSET_DAMAGE; this.dirty = true; @@ -113,13 +117,13 @@ public class BlockDestructionManager { @Override public void toNBT(NbtCompound compound) { - compound.putInt("destruction", amount); + compound.putFloat("destruction", amount); compound.putInt("age", age); } @Override public void fromNBT(NbtCompound compound) { - amount = compound.getInt("destruction"); + amount = compound.getFloat("destruction"); age = compound.getInt("age"); dirty = true; } diff --git a/src/main/java/com/minelittlepony/unicopia/client/ClientBlockDestructionManager.java b/src/main/java/com/minelittlepony/unicopia/client/ClientBlockDestructionManager.java index 35e3fe85..0a23d123 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/ClientBlockDestructionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/ClientBlockDestructionManager.java @@ -17,7 +17,7 @@ public class ClientBlockDestructionManager { private final Object locker = new Object(); - public void setBlockDestruction(long pos, int amount) { + public void setBlockDestruction(long pos, float amount) { synchronized (locker) { if (amount <= 0 || amount > BlockDestructionManager.MAX_DAMAGE) { destructions.remove(pos); @@ -70,9 +70,9 @@ public class ClientBlockDestructionManager { return amount < 0 || age-- <= 0; } - void set(int amount) { + void set(float amount) { this.age = 50; - info.setStage(amount >= 0 && amount < BlockDestructionManager.MAX_DAMAGE ? amount : BlockDestructionManager.UNSET_DAMAGE); + info.setStage(amount >= 0 && amount < BlockDestructionManager.MAX_DAMAGE ? (int)amount : BlockDestructionManager.UNSET_DAMAGE); } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java b/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java index 8c29dfac..a1cc8c21 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java @@ -13,21 +13,21 @@ import net.minecraft.entity.player.PlayerEntity; */ public class MsgBlockDestruction implements Packet { - private final Long2ObjectMap destructions; + private final Long2ObjectMap destructions; MsgBlockDestruction(PacketByteBuf buffer) { destructions = new Long2ObjectOpenHashMap<>(); int size = buffer.readInt(); for (int i = 0; i < size; i++) { - destructions.put(buffer.readLong(), (Integer)buffer.readInt()); + destructions.put(buffer.readLong(), (Float)buffer.readFloat()); } } - public MsgBlockDestruction(Long2ObjectMap destructions) { + public MsgBlockDestruction(Long2ObjectMap destructions) { this.destructions = destructions; } - public Long2ObjectMap getDestructions() { + public Long2ObjectMap getDestructions() { return destructions; } @@ -36,7 +36,7 @@ public class MsgBlockDestruction implements Packet { buffer.writeInt(destructions.size()); destructions.forEach((p, i) -> { buffer.writeLong(p); - buffer.writeInt(i); + buffer.writeFloat(i); }); } diff --git a/src/main/java/com/minelittlepony/unicopia/util/MagicalDamageSource.java b/src/main/java/com/minelittlepony/unicopia/util/MagicalDamageSource.java index 376906a7..afb359b4 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/MagicalDamageSource.java +++ b/src/main/java/com/minelittlepony/unicopia/util/MagicalDamageSource.java @@ -21,6 +21,7 @@ public class MagicalDamageSource extends EntityDamageSource { public static final DamageSource FOOD_POISONING = mundane("food_poisoning"); public static final DamageSource TRIBE_SWAP = mundane("tribe_swap"); public static final DamageSource ZAP_APPLE = create("zap"); + public static final DamageSource KICK = create("kick"); public static DamageSource mundane(String type) { return new DamageSource(type) {}; diff --git a/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java b/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java index 72ab5eb2..753fb8f0 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java @@ -50,12 +50,12 @@ public class RayTraceHelper { * @return A Trace describing what was found. */ public static Trace doTrace(Entity e, double distance, float tickDelta, Predicate predicate) { - final Vec3d ray = e.getRotationVec(tickDelta).multiply(distance); + final Vec3d orientation = e.getRotationVec(tickDelta); final Vec3d start = e.getCameraPosVec(tickDelta); - final Box box = e.getBoundingBox().stretch(ray).expand(1); + final Box box = e.getBoundingBox().stretch(orientation.multiply(Math.abs(distance))).expand(10); - EntityHitResult pointedEntity = ProjectileUtil.raycast(e, start, start.add(ray), box, predicate, distance); + EntityHitResult pointedEntity = ProjectileUtil.raycast(e, start, start.add(orientation.multiply(distance)), box, predicate, Math.abs(distance)); if (pointedEntity != null) { return new Trace(pointedEntity); @@ -85,6 +85,14 @@ public class RayTraceHelper { return Optional.empty(); } + @SuppressWarnings("unchecked") + public Optional getEntity(Predicate predicate) { + if (result != null && result.getType() == HitResult.Type.ENTITY) { + return Optional.of((T)((EntityHitResult)result).getEntity()).filter(predicate); + } + return Optional.empty(); + } + public Optional getBlockPos() { if (result != null && result.getType() == HitResult.Type.BLOCK) { return Optional.of(((BlockHitResult)result).getBlockPos()); diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index c25c3c78..b5239024 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -455,8 +455,10 @@ "death.attack.paradox": "%1$s imploded", "death.attack.food_poisoning": "%1$s died of food poisoning", "death.attack.food_poisoning.attacker": "%2$s poisoned %1$s to death", - "death.attack.back_hole": "%1$s was sucked into a black hole", - "death.attack.back_hole.attacker": "%1$s got sucked into %2$s's black hole", + "death.attack.black_hole": "%1$s was sucked into a black hole", + "death.attack.black_hole.attacker": "%1$s got sucked into %2$s's black hole", + "death.attack.kick": "%1$s was kicked really hard", + "death.attack.kick.attacker": "%2$s kicked %1$s really hard", "unicopia.subtitle.flap_wings": "Wing flaps", "unicopia.subtitle.wind_rush": "Wind gusts",