Skip to content

Commit

Permalink
cool lightning feature
Browse files Browse the repository at this point in the history
  • Loading branch information
AViewFromTheTop committed Dec 5, 2023
1 parent 36e38c4 commit c2a981c
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Bug Fixes & Changes

- Landing/Potion sound code will no longer attempt to run on the client
- Landing Ender Pearls will now play sounds in their owner's sound category (Zombies would be Hostile, and Players would be Player)
- Added a config option for whether or not Block particles will spawn upon a Lightning Bolt striking the ground

- The config will now sync between server and client
- Operators of servers will modify the server's config upon modifying it on their end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
import net.frozenblock.wilderwild.entity.render.renderer.TumbleweedRenderer;
import net.frozenblock.wilderwild.item.FireflyBottle;
import net.frozenblock.wilderwild.misc.WilderSharedConstants;
import net.frozenblock.wilderwild.networking.client.WilderClientNetworking;
import net.frozenblock.wilderwild.networking.WilderClientNetworking;
import net.frozenblock.wilderwild.particle.FallingParticle;
import net.frozenblock.wilderwild.particle.FloatingSculkBubbleParticle;
import net.frozenblock.wilderwild.particle.MesogleaDripParticle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public final class EntityConfig {
@FieldIdentifier(identifier = "unpassableRail")
public boolean unpassableRail = false;

@UnsyncableEntry
@FieldIdentifier(identifier = "lightningParticles")
public boolean lightningParticles = true;

public static EntityConfig get() {
return get(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public static void setupEntries(@NotNull ConfigCategory category, @NotNull Confi
var warden = config.warden;
var modifiedWarden = modifiedConfig.warden;
category.setBackground(WilderSharedConstants.id("textures/config/entity.png"));

var unpassableRail = category.addEntry(
FrozenClothConfig.syncedBuilder(
entryBuilder.startBooleanToggle(text("unpassable_rail"), modifiedConfig.unpassableRail)
Expand All @@ -68,8 +69,21 @@ public static void setupEntries(@NotNull ConfigCategory category, @NotNull Confi
"unpassableRail",
configInstance
)
.build()
);

.build());
var lightningParticles = category.addEntry(
FrozenClothConfig.syncedBuilder(
entryBuilder.startBooleanToggle(text("lightning_particles"), modifiedConfig.lightningParticles)
.setDefaultValue(defaultConfig.lightningParticles)
.setSaveConsumer(newValue -> config.lightningParticles = newValue)
.setTooltip(tooltip("lightning_particles")),
clazz,
"lightningParticles",
configInstance
)
.build()
);

var keyframeAllayDance = FrozenClothConfig.syncedBuilder(
entryBuilder.startBooleanToggle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,19 @@

package net.frozenblock.wilderwild.mixin.entity.lightning;

import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import net.frozenblock.wilderwild.block.ScorchedBlock;
import net.frozenblock.wilderwild.networking.WilderNetworking;
import net.frozenblock.wilderwild.world.additions.feature.WilderMiscConfigured;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
Expand All @@ -39,23 +45,60 @@ public class LightningBoltMixin {
@Shadow
private boolean visualOnly;

@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LightningBolt;spawnFire(I)V", ordinal = 1, shift = At.Shift.AFTER))
private void wilderWild$tick(CallbackInfo info) {
this.wilderWild$scorchSand(LightningBolt.class.cast(this));
@Inject(
method = "tick",
at = @At(
value = "HEAD"
)
)
private void wilderWild$tick(
CallbackInfo info,
@Share("wilderWild$strikePos") LocalRef<BlockPos> strikePosLocalRef,
@Share("wilderWild$strikeState") LocalRef<BlockState> strikeStateLocalRef
) {
if (LightningBolt.class.cast(this).level() instanceof ServerLevel serverLevel) {
BlockPos blockPos = this.getStrikePosition();
BlockState state = serverLevel.getBlockState(blockPos);
if (!LightningBolt.class.cast(this).level().isClientSide) {
WilderNetworking.sendLightningStrikeToAll(
LightningBolt.class.cast(this),
state,
Vec3.atCenterOf(blockPos).add(0D, 0.5D, 0D),
Math.max(1, LightningBolt.class.cast(this).tickCount - 6D)
);
}
strikePosLocalRef.set(blockPos);
strikeStateLocalRef.set(state);
}
}

@Inject(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/LightningBolt;spawnFire(I)V"
)
)
private void wilderWild$scorchTheSand(
CallbackInfo info,
@Share("wilderWild$strikePos") LocalRef<BlockPos> strikePosLocalRef,
@Share("wilderWild$strikeState") LocalRef<BlockState> strikeStateLocalRef
) {
this.wilderWild$scorchSand(LightningBolt.class.cast(this), strikePosLocalRef.get(), strikeStateLocalRef.get());
}

@Unique
private void wilderWild$scorchSand(@NotNull LightningBolt bolt) {
private void wilderWild$scorchSand(@NotNull LightningBolt bolt, BlockPos strikePose, BlockState strikeState) {
if (this.visualOnly || bolt.level().isClientSide) {
return;
}
if (bolt.level() instanceof ServerLevel serverLevel) {
BlockPos blockPos = this.getStrikePosition();
if (bolt.level().getBlockState(blockPos).is(BlockTags.SAND)) {
if (strikeState.is(BlockTags.SAND)) {
ChunkGenerator chunkGenerator = serverLevel.getChunkSource().getGenerator();
RandomSource randomSource = serverLevel.getRandom();
WilderMiscConfigured.SCORCHED_SAND_DISK_LIGHTNING.getConfiguredFeature(serverLevel).place(serverLevel, chunkGenerator, randomSource, blockPos);
WilderMiscConfigured.SCORCHED_RED_SAND_DISK_LIGHTNING.getConfiguredFeature(serverLevel).place(serverLevel, chunkGenerator, randomSource, blockPos);
WilderMiscConfigured.SCORCHED_SAND_DISK_LIGHTNING.getConfiguredFeature(serverLevel).place(serverLevel, chunkGenerator, randomSource, strikePose);
WilderMiscConfigured.SCORCHED_RED_SAND_DISK_LIGHTNING.getConfiguredFeature(serverLevel).place(serverLevel, chunkGenerator, randomSource, strikePose);
ScorchedBlock.scorch(strikeState, serverLevel, strikePose);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package net.frozenblock.wilderwild.networking.client;
package net.frozenblock.wilderwild.networking;

import java.util.concurrent.atomic.AtomicInteger;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.frozenblock.lib.math.api.AdvancedMath;
import net.frozenblock.wilderwild.networking.WilderNetworking;
import net.frozenblock.wilderwild.config.EntityConfig;
import net.frozenblock.wilderwild.particle.options.FloatingSculkBubbleParticleOptions;
import net.frozenblock.wilderwild.particle.options.SeedParticleOptions;
import net.frozenblock.wilderwild.registry.RegisterParticles;
import net.frozenblock.wilderwild.registry.RegisterSounds;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.particles.BlockParticleOption;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;

@Environment(EnvType.CLIENT)
Expand All @@ -26,6 +31,7 @@ public static void registerPacketReceivers() {
receiveTermitePacket();
receiveSensorHiccupPacket();
receiveJellyStingPacket();
receiveLightningStrikePacket();
}
private static void receiveEasyEchoerBubblePacket() {
ClientPlayNetworking.registerGlobalReceiver(WilderNetworking.FLOATING_SCULK_BUBBLE_PACKET, (ctx, handler, byteBuf, responseSender) -> {
Expand Down Expand Up @@ -133,4 +139,45 @@ private static void receiveJellyStingPacket() {
}));
}

private static void receiveLightningStrikePacket() {
ClientPlayNetworking.registerGlobalReceiver(WilderNetworking.LIGHTNING_STRIKE_PACKET, (ctx, handler, byteBuf, responseSender) -> ctx.execute(() -> {
BlockState blockState = Block.stateById(byteBuf.readInt());
double x = byteBuf.readDouble();
double y = byteBuf.readDouble();
double z = byteBuf.readDouble();
double tickCount = byteBuf.readDouble();
if (ctx.level != null) {
if (EntityConfig.get().lightningParticles) {
RandomSource random = ctx.level.getRandom();
Vec3 origin = new Vec3(x, y, z);
int particles = ctx.level.getRandom().nextInt(20, 40);
double rotAngle = 360D / (double) particles;
double angle = ctx.level.getRandom().nextDouble() * 360D;
BlockParticleOption blockParticleOption = new BlockParticleOption(ParticleTypes.BLOCK, blockState);

for (int a = 0; a < particles; a++) {
Vec3 offsetPos = AdvancedMath.rotateAboutXZ(origin, 1D, angle + (((random.nextDouble() * rotAngle) * 0.25D) * (random.nextBoolean() ? 1D : -1D)));
double dirX = offsetPos.x - origin.x;
double dirZ = offsetPos.z - origin.z;
Particle particle = ctx.particleEngine.createParticle(
blockParticleOption,
x + (dirX * 0.25D),
y,
z + (dirZ * 0.25D),
0D,
0D,
0D
);
if (particle != null) {
particle.xd = (dirX * 0.1D) / tickCount;
particle.yd = (0.5D) / tickCount;
particle.zd = (dirZ * 0.1D) / tickCount;
}
angle += rotAngle;
}
}
}
}));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
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 org.jetbrains.annotations.NotNull;

Expand All @@ -38,13 +41,26 @@ public class WilderNetworking {
public static final ResourceLocation TERMITE_PARTICLE_PACKET = WilderSharedConstants.id("termite_particle_packet");
public static final ResourceLocation SENSOR_HICCUP_PACKET = WilderSharedConstants.id("sensor_hiccup_packet");
public static final ResourceLocation JELLY_STING_PACKET = WilderSharedConstants.id("jelly_sting_packet");
public static final ResourceLocation LIGHTNING_STRIKE_PACKET = WilderSharedConstants.id("lightning_strike_packet");

public static void sendJellySting(ServerPlayer player, boolean baby) {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
byteBuf.writeBoolean(baby);
ServerPlayNetworking.send(player, JELLY_STING_PACKET, byteBuf);
}

public static void sendLightningStrikeToAll(Entity entity, BlockState blockState, @NotNull Vec3 pos, double tickCount) {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
byteBuf.writeInt(Block.getId(blockState));
byteBuf.writeDouble(pos.x());
byteBuf.writeDouble(pos.y());
byteBuf.writeDouble(pos.z());
byteBuf.writeDouble(tickCount);
for (ServerPlayer player : PlayerLookup.tracking(entity)) {
ServerPlayNetworking.send(player, LIGHTNING_STRIKE_PACKET, byteBuf);
}
}

public static class EasySeedPacket {
public static void createParticle(@NotNull Level level, Vec3 pos, int count, boolean isMilkweed) {
if (level.isClientSide)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,8 @@ public PalmFoliagePlacer(@NotNull IntProvider radius, @NotNull IntProvider offse
@Contract("_ -> new")
protected static <P extends PalmFoliagePlacer> Products.@NotNull P4<RecordCodecBuilder.Mu<P>, IntProvider, IntProvider, IntProvider, BlockStateProvider> palmCodec(RecordCodecBuilder.Instance<P> builder) {
return foliagePlacerParts(builder)
.and(
IntProvider.codec(0, 16).fieldOf("frond_count").forGetter(placer -> placer.frondCount)
).and(
BlockStateProvider.CODEC.fieldOf("crown_state").forGetter(placer -> placer.crownState)
);
.and(IntProvider.codec(0, 16).fieldOf("frond_count").forGetter(placer -> placer.frondCount))
.and(BlockStateProvider.CODEC.fieldOf("crown_state").forGetter(placer -> placer.crownState));
}

public static void placeLeavesAtPos(@NotNull LevelSimulatedReader level, @NotNull FoliageSetter blockSetter, @NotNull RandomSource random, @NotNull TreeConfiguration config, @NotNull BlockPos pos, double offX, double offY, double offZ) {
Expand Down Expand Up @@ -107,15 +104,15 @@ protected void createFoliage(@NotNull LevelSimulatedReader level, @NotNull Folia
double radius = minRadius + ((this.radius.getMaxValue() - minRadius) * random.nextDouble());
double minus = (Math.PI * radius) / (radius * radius);
int fronds = this.frondCount.sample(random);
double rotAngle = 360 / (double) fronds;
double angle = random.nextDouble() * 360;
double rotAngle = 360D / (double) fronds;
double angle = random.nextDouble() * 360D;

for (int a = 0; a < fronds; a++) {
Vec3 offsetPos = AdvancedMath.rotateAboutXZ(origin, 1, angle + (((random.nextDouble() * rotAngle) * 0.35) * (random.nextBoolean() ? 1 : -1)));
Vec3 offsetPos = AdvancedMath.rotateAboutXZ(origin, 1D, angle + (((random.nextDouble() * rotAngle) * 0.35D) * (random.nextBoolean() ? 1D : -1D)));
double dirX = offsetPos.x - origin.x;
double dirZ = offsetPos.z - origin.z;
for (double r = 0; r < radius; r += 0.2) {
double yOffset = (2 * (Math.sin((Math.PI * (r - 0.1)) / radius) - minus)) + (4.2 * (minus * 0.4));
for (double r = 0D; r < radius; r += 0.2D) {
double yOffset = (2D * (Math.sin((Math.PI * (r - 0.1D)) / radius) - minus)) + (4.2D * (minus * 0.4D));
placeLeavesAtPos(level, blockSetter, random, config, blockPos, (dirX * r), yOffset, (dirZ * r));
}
angle += rotAngle;
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/wilderwild/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@
"option.wilderwild.leashed_tumbleweed.false": "§cDisabled",
"option.wilderwild.leashed_tumbleweed.true": "§aEnabled",
"option.wilderwild.unpassable_rail": "Unpassable Rail",
"option.wilderwild.lightning_particles": "Lightning Particles",
"option.wilderwild.warden": "Warden",
"option.wilderwild.warden_attacks_immediately": "Warden Attacks Immediately",
"option.wilderwild.warden_custom_tendrils": "Warden Tendril Animation",
Expand Down Expand Up @@ -595,6 +596,7 @@
"tooltip.wilderwild.tumbleweed_destroys_crops": "Whether or not Tumbleweed can destroy crops.",
"tooltip.wilderwild.tumbleweed_rotates_to_look_direction": "When enabled, Tumbleweed will rotate in the direction\nit's moving instead of spinning towards it.",
"tooltip.wilderwild.unpassable_rail": "Allows all mob entities to walk over rails instead of being unable to pass it.",
"tooltip.wilderwild.lightning_particles": "Whether or not Lightning Bolts should spawn a stream of block particles upon striking.",
"tooltip.wilderwild.warden": "Contains options for the Warden.",
"tooltip.wilderwild.warden_attacks_immediately": "Whether or not the Warden should attack entities on collision.",
"tooltip.wilderwild.warden_custom_tendrils": "Vanilla: Warden's tendrils only rotate about a single axis.\nImproved: Warden's tendrils rotate about all axes, improving visibility from all angles.",
Expand Down
34 changes: 17 additions & 17 deletions src/main/resources/wilderwild.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@
"block.mesoglea.SoulSandBlockMixin",
"block.palm_fronds.BlockStatePropertiesMixin",
"block.reinforced_deepslate.BlocksMixin",
"block.sculk.CalibratedSculkSensorBlockEntityMixin",
"block.sculk.CalibratedSculkSensorBlockMixin",
"block.sculk.SculkBlockMixin",
"block.sculk.SculkSensorBlockEntityMixin",
"block.sculk.SculkSensorBlockEntityMixin$VibrationUserMixin",
"block.sculk.SculkSensorBlockMixin",
"block.sculk.SculkShriekerBlockEntityMixin",
"block.sculk.SculkShriekerBlockEntityMixin$VibrationUserMixin",
"block.sculk.SculkShriekerBlockMixin",
"block.sculk.SculkSpreaderChargeCursorMixin",
"block.sculk.SculkVeinBlockMixin",
"block.sculk.SculkVeinSpreaderConfigMixin",
"block.spawner.BaseSpawnerMixin",
"block.termite.RotatedPillarBlockMixin",
"entity.ai.MobMixin",
Expand All @@ -53,6 +65,11 @@
"entity.tumbleweed.BlockBehaviourMixin",
"entity.tumbleweed.EntityMixin",
"entity.turtle.TurtleMixin",
"entity.warden.LivingEntityMixin",
"entity.warden.SonicBoomMixin",
"entity.warden.WardenMixin",
"entity.warden.WardenMixin$VibrationUserMixin",
"entity.warden.WardenSwimMixin",
"item.axe.AxeItemMixin",
"item.brush.BrushItemMixin",
"item.instrument.InstrumentItemMixin",
Expand All @@ -64,23 +81,6 @@
"projectile.ThrownEnderpearlMixin",
"projectile.ThrownExperienceBottleMixin",
"projectile.ThrownPotionMixin",
"block.sculk.CalibratedSculkSensorBlockEntityMixin",
"block.sculk.CalibratedSculkSensorBlockMixin",
"block.sculk.SculkBlockMixin",
"block.sculk.SculkSensorBlockEntityMixin",
"block.sculk.SculkSensorBlockEntityMixin$VibrationUserMixin",
"block.sculk.SculkSensorBlockMixin",
"block.sculk.SculkShriekerBlockEntityMixin",
"block.sculk.SculkShriekerBlockEntityMixin$VibrationUserMixin",
"block.sculk.SculkShriekerBlockMixin",
"block.sculk.SculkSpreaderChargeCursorMixin",
"block.sculk.SculkVeinBlockMixin",
"block.sculk.SculkVeinSpreaderConfigMixin",
"entity.warden.LivingEntityMixin",
"entity.warden.SonicBoomMixin",
"entity.warden.WardenMixin",
"entity.warden.WardenMixin$VibrationUserMixin",
"entity.warden.WardenSwimMixin",
"worldgen.biome.OverworldBiomeBuilderMixin",
"worldgen.structure.SwampHutPieceMixin",
"worldgen.tree.AbstractTreeGrowerMixin",
Expand Down

0 comments on commit c2a981c

Please sign in to comment.