From 53fca580f3ff3cf9208eb871b5ccb43bf485776c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sun, 12 Oct 2025 23:04:05 +0200 Subject: [PATCH 1/3] added IronGolemAnimation --- .../IronGolemAnimation.java | 113 ++++++++++++++++++ .../NaturalIronGolemSpawnEvent.java | 15 +++ 2 files changed, 128 insertions(+) create mode 100644 craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java create mode 100644 craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java new file mode 100644 index 0000000..02e197a --- /dev/null +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java @@ -0,0 +1,113 @@ +package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.ironGolemAnimation; + +import eu.mhsl.craftattack.spawn.core.Main; +import eu.mhsl.craftattack.spawn.core.appliance.Appliance; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public class IronGolemAnimation extends Appliance { + record BlockChange(Block original, BlockData fakeBlock) {} + + public void onGolemSpawn(IronGolem golem) { + this.modifyGolem(golem, false); + Location golemLocation = golem.getLocation(); + + BlockData bodyBlockData = Bukkit.createBlockData(Material.IRON_BLOCK); + BlockData headBlockData = Bukkit.createBlockData( + Material.CARVED_PUMPKIN, + blockData -> ((Directional) blockData).setFacing(golem.getFacing()) + ); + Vector facingVector = golem.getFacing().getDirection().rotateAroundY(Math.toRadians(90)); + Block golemCenterBlock = golemLocation.getBlock().getRelative(BlockFace.UP); + + List buildBlocks = List.of( + new BlockChange(golemCenterBlock.getRelative(BlockFace.DOWN), bodyBlockData), + new BlockChange(golemCenterBlock, bodyBlockData), + new BlockChange(golemCenterBlock.getLocation().add(facingVector).getBlock(), bodyBlockData), + new BlockChange(golemCenterBlock.getLocation().add(facingVector.multiply(-1)).getBlock(), bodyBlockData), + new BlockChange(golemCenterBlock.getRelative(BlockFace.UP), headBlockData) + ); + + Collection viewers = golemLocation.getNearbyPlayers(golemLocation.getWorld().getViewDistance()); + BiConsumer changeBlockForViewers = (location, blockData) -> { + viewers.forEach(player -> player.sendBlockChange(location, blockData)); + golem.getWorld().playSound( + location, + blockData.getSoundGroup().getPlaceSound(), + SoundCategory.BLOCKS, + 1f, + 1f + ); + }; + for(int i = 0; i < buildBlocks.size(); i++) { + BlockChange blockChange = buildBlocks.get(i); + Bukkit.getScheduler().runTaskLater( + Main.instance(), + () -> changeBlockForViewers.accept(blockChange.original.getLocation(), blockChange.fakeBlock), + 6L * i + ); + } + + Consumer> restoreBlockChanges = (blocks) -> { + buildBlocks.forEach((blockChange) -> changeBlockForViewers.accept( + blockChange.original().getLocation(), + blockChange.original.getBlockData() + )); + + this.modifyGolem(golem, true); + this.spawnEffect(buildBlocks); + }; + Bukkit.getScheduler().runTaskLater( + Main.instance(), + () -> restoreBlockChanges.accept(buildBlocks), + 6L * buildBlocks.size() + 2 + ); + } + + private void spawnEffect(List buildBlocks) { + buildBlocks.forEach((blockChange) -> { + World world = blockChange.original.getLocation().getWorld(); + world.spawnParticle( + Particle.BLOCK, + blockChange.original.getLocation().add(0.5, 0.5, 0.5), + 50, + blockChange.fakeBlock + ); + world.playSound( + blockChange.original.getLocation(), + blockChange.fakeBlock.getSoundGroup().getBreakSound(), + SoundCategory.BLOCKS, + 1f, + 1f + ); + }); + } + + public void modifyGolem(IronGolem golem, boolean setVisible) { + golem.setInvisible(!setVisible); + golem.setInvulnerable(!setVisible); + golem.setAI(setVisible); + golem.setGravity(setVisible); + golem.setCollidable(setVisible); + } + + @Override + protected @NotNull List listeners() { + return List.of( + new NaturalIronGolemSpawnEvent() + ); + } +} diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java new file mode 100644 index 0000000..192dc4d --- /dev/null +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java @@ -0,0 +1,15 @@ +package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.ironGolemAnimation; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import org.bukkit.entity.IronGolem; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.CreatureSpawnEvent; + +class NaturalIronGolemSpawnEvent extends ApplianceListener { + @EventHandler + public void onGolemSpawn(CreatureSpawnEvent event) { + if(!(event.getEntity() instanceof IronGolem golem)) return; +// if(event.getSpawnReason() != CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE) return; + this.getAppliance().onGolemSpawn(golem); + } +} -- 2.30.2 From 4be3e528b176cd2008f23504b47f7b61da327a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sun, 12 Oct 2025 23:05:19 +0200 Subject: [PATCH 2/3] fixed spawn reason check for Iron Golem spawning logic in NaturalIronGolemSpawnEvent --- .../gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java index 192dc4d..ca6b733 100644 --- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/NaturalIronGolemSpawnEvent.java @@ -9,7 +9,7 @@ class NaturalIronGolemSpawnEvent extends ApplianceListener { @EventHandler public void onGolemSpawn(CreatureSpawnEvent event) { if(!(event.getEntity() instanceof IronGolem golem)) return; -// if(event.getSpawnReason() != CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE) return; + if(event.getSpawnReason() != CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE) return; this.getAppliance().onGolemSpawn(golem); } } -- 2.30.2 From 713561bf07cb2e3aa98e68e67d76c5d9f952931b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sun, 12 Oct 2025 23:07:09 +0200 Subject: [PATCH 3/3] adjusted Iron Golem animation viewer calculation to account for block distance --- .../gameplay/ironGolemAnimation/IronGolemAnimation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java index 02e197a..59495f2 100644 --- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/ironGolemAnimation/IronGolemAnimation.java @@ -41,7 +41,7 @@ public class IronGolemAnimation extends Appliance { new BlockChange(golemCenterBlock.getRelative(BlockFace.UP), headBlockData) ); - Collection viewers = golemLocation.getNearbyPlayers(golemLocation.getWorld().getViewDistance()); + Collection viewers = golemLocation.getNearbyPlayers(golemLocation.getWorld().getViewDistance() * 16); BiConsumer changeBlockForViewers = (location, blockData) -> { viewers.forEach(player -> player.sendBlockChange(location, blockData)); golem.getWorld().playSound( -- 2.30.2