Skip to content

Commit

Permalink
Bergamutes can occlude vibrations
Browse files Browse the repository at this point in the history
Vibration source and destination positions are rounded to the center of the respective blocks (same as wool occlusion checks). If the line drawn between the two positions intersects the Bergamute's spherical area of effect, the vibration is occluded.
  • Loading branch information
TheRealWormbo committed Jun 2, 2024
1 parent 8db1a22 commit 6afa016
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import com.mojang.datafixers.util.Pair;

import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;

import vazkii.botania.api.block_entity.RadiusDescriptor;
import vazkii.botania.api.block_entity.SpecialFlowerBlockEntity;
Expand Down Expand Up @@ -78,6 +80,42 @@ public static boolean isBergamuteNearby(Level level, double x, double y, double
return getBergamutesNearby(level, x, y, z, 1).getFirst() > 0;
}

public static boolean isBergamuteOccludingVibration(Level level, Vec3 sourcePos, Vec3 destPos) {
BlockPos sourceBlockPos = BlockPos.containing(sourcePos);
BlockPos destBlockPos = BlockPos.containing(destPos);

// vibration occlusions assume block centers as source and target positions, so do that here as well
Vec3 sourceCenterPos = sourceBlockPos.getCenter();
if (sourceBlockPos.equals(destBlockPos)) {
// trivial case: source and dest are in the same block, check Bergamute proximity to that block's center
return isBergamuteNearby(level, sourceCenterPos.x, sourceCenterPos.y, sourceCenterPos.z);
}

// find the point on the line between source and destination that is closest to each Bergamute,
// and check whether it's actually in range of that Bergamute
// (based on https://stackoverflow.com/questions/51905268/how-to-find-closest-point-on-line)
Vec3 destCenterPos = destBlockPos.getCenter();
Vec3 vibrationTravelVector = sourceCenterPos.vectorTo(destCenterPos);
double vibrationTravelDist = vibrationTravelVector.length();
Vec3 vibrationTravelDir = vibrationTravelVector.normalize();

for (BergamuteBlockEntity f : level.isClientSide ? clientFlowers : serverFlowers) {
if (f.disabled || f.level != level) {
continue;
}

Vec3 flowerPos = f.getEffectivePos().getCenter();
Vec3 vecSourceToFlower = sourceCenterPos.vectorTo(flowerPos);
double travelPosition = Mth.clamp(vibrationTravelDir.dot(vecSourceToFlower), 0, vibrationTravelDist);
Vec3 closestPos = sourceCenterPos.add(vibrationTravelDir.scale(travelPosition));
if (flowerPos.distanceToSqr(closestPos) <= RANGE * RANGE) {
return true;
}
}

return false;
}

public static void particle(BergamuteBlockEntity berg) {
int color = ManaPoolBlockEntity.PARTICLE_COLOR;
float red = (color >> 16 & 0xFF) / 255F;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package vazkii.botania.mixin;

import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.vibrations.VibrationSystem;
import net.minecraft.world.phys.Vec3;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import vazkii.botania.common.block.flower.functional.BergamuteBlockEntity;

@Mixin(VibrationSystem.Listener.class)
public class VibrationSystemListenerMixin {
/**
* Check if any active Bergamutes are near the direct line of sight between a vibration source
* and the vibration listener currently checking whether it can receive the vibration.
*/
@Inject(method = "isOccluded", at = @At("HEAD"), cancellable = true)
private static void checkBergamuteOcclusion(Level level, Vec3 sourcePos, Vec3 destPos, CallbackInfoReturnable<Boolean> cir) {
if (BergamuteBlockEntity.isBergamuteOccludingVibration(level, sourcePos, destPos)) {
cir.setReturnValue(true);
}
}
}
2 changes: 1 addition & 1 deletion Xplat/src/main/resources/assets/botania/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -2414,7 +2414,7 @@
"botania.entry.bergamute": "Bergamute",
"botania.tagline.bergamute": "Absorbs sound",
"botania.page.bergamute0": "Anyone who's ever attempted ranching knows of the cacophonous din emitted by herds of animals. Luckily, the $(item)Bergamute$(0) can deafen such dins.",
"botania.page.bergamute1": "The $(item)Bergamute$(0) absorbs sound energy emitted in a close radius around itself, converting it into trace amounts of mana and dispersing it harmlessly. It halves the volume of sounds within reach, the effect stacking with other nearby $(item)Bergamutes$(0).$(p)Additionally, $(l:tools/grass_horn)$(item)Horns$(0)$(/l) or $(l:devices/forest_drum)$(item)Drums$(0)$(/l) will not break blocks within its range.",
"botania.page.bergamute1": "The $(item)Bergamute$(0) absorbs sound energy emitted in a close radius around itself, converting it into trace amounts of mana and dispersing it harmlessly. It halves the volume of sounds within reach, the effect stacking with other nearby $(item)Bergamutes$(0).$(p)Additionally, $(l:tools/grass_horn)$(item)Horns$(0)$(/l) or $(l:devices/forest_drum)$(item)Drums$(0)$(/l) will not break blocks within its range, and vibrations passing through its area of effect are muffled.",
"botania.page.bergamute2": "Deaf to All but the Song",

"botania.entry.gIntro": "Generating Flora",
Expand Down
1 change: 1 addition & 0 deletions Xplat/src/main/resources/botania_xplat.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"StatsAccessor",
"TextureSlotAccessor",
"ThrowableProjectileMixin",
"VibrationSystemListenerMixin",
"WitherEntityAccessor"
],
"client": [
Expand Down
1 change: 1 addition & 0 deletions web/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and start a new "Upcoming" section.
{% include changelog_header.html version="Upcoming" %}

* Add: Horn and Drum of the Wild can break moss carpet, with the option to add more blocks through a block tag
* Add: Bergamute occludes vibrations within its range
* Change: Cellular blocks around the boundary of a Dandelifeon's simulation area are ignored, unless they belong to another active Dandelifeon (NEstoll)
* Change: Charm of the Diva also supports charming or targeting neutral mobs that are angry at the player or attacking one of the player's tamed animals, and properly prevents the player's tamed animals from being affected or targeted by the charm
* Change: Dandelifeon recipe also requires a redstone root (zacharybarbanell)
Expand Down

0 comments on commit 6afa016

Please sign in to comment.