diff --git a/ansible/files/paper-config/plugins/SimpleAdminHacks/config.yml b/ansible/files/paper-config/plugins/SimpleAdminHacks/config.yml index ebd8563ff..db9d3cbbc 100644 --- a/ansible/files/paper-config/plugins/SimpleAdminHacks/config.yml +++ b/ansible/files/paper-config/plugins/SimpleAdminHacks/config.yml @@ -582,16 +582,24 @@ hacks: materials: COBBLESTONE: 8 COPPER_BLOCK: 29 + WAXED_COPPER_BLOCK: 29 EXPOSED_COPPER: 23 + WAXED_EXPOSED_COPPER: 23 WEATHERED_COPPER: 18 + WAXED_WEATHERED_COPPER: 18 OXIDIZED_COPPER: 14 + WAXED_OXIDIZED_COPPER: 14 skyBase: 10 skyMaterials: COBBLESTONE: 8 COPPER_BLOCK: 30 + WAXED_COPPER_BLOCK: 30 EXPOSED_COPPER: 24 + WAXED_EXPOSED_COPPER: 24 WEATHERED_COPPER: 19 + WAXED_WEATHERED_COPPER: 19 OXIDIZED_COPPER: 15 + WAXED_OXIDIZED_COPPER: 15 CopperRail: enabled: true deoxidise: true diff --git a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/CopperRail.java b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/CopperRail.java index bb0d1a912..3a8dda302 100644 --- a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/CopperRail.java +++ b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/CopperRail.java @@ -5,9 +5,7 @@ import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack; import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig; import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.AutoLoad; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.block.WeatheringCopper; -import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Location; import org.bukkit.Material; @@ -15,10 +13,6 @@ import org.bukkit.SoundCategory; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.block.CraftBlock; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.entity.Entity; import org.bukkit.entity.Minecart; import org.bukkit.entity.Player; @@ -30,7 +24,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; public class CopperRail extends BasicHack { @@ -47,6 +40,57 @@ public CopperRail(SimpleAdminHacks plugin, BasicHackConfig config) { super(plugin, config); } + private enum CopperStage { + UNAFFECTED(Material.COPPER_BLOCK, Material.WAXED_COPPER_BLOCK, .75f), + EXPOSED(Material.EXPOSED_COPPER, Material.WAXED_EXPOSED_COPPER, 1.0f), + WEATHERED(Material.WEATHERED_COPPER, Material.WAXED_WEATHERED_COPPER, 1.0f), + OXIDIZED(Material.OXIDIZED_COPPER, Material.WAXED_OXIDIZED_COPPER, 0.0f); + + private final Material unwaxed; + private final Material waxed; + private final float chance; + + CopperStage(Material unwaxed, Material waxed, float chance) { + this.unwaxed = unwaxed; + this.waxed = waxed; + this.chance = chance; + } + + public static CopperStage from(Material mat) { + for (CopperStage stage : values()) { + if (stage.unwaxed == mat || stage.waxed == mat) return stage; + } + return null; + } + } + + private boolean isWaxed(Material material) { + CopperStage stage = CopperStage.from(material); + return stage != null && stage.waxed == material; + } + + private Material getNextStage(Material material) { + CopperStage current = CopperStage.from(material); + if (current == null) return null; + + int nextIndex = current.ordinal() + 1; + if (nextIndex >= CopperStage.values().length) return null; + + CopperStage nextStage = CopperStage.values()[nextIndex]; + return isWaxed(material) ? nextStage.waxed : nextStage.unwaxed; + } + + private Material getPreviousStage(Material material) { + CopperStage current = CopperStage.from(material); + if (current == null) return null; + + int prevIndex = current.ordinal() - 1; + if (prevIndex < 0) return null; + + CopperStage prevStage = CopperStage.values()[prevIndex]; + return isWaxed(material) ? prevStage.waxed : prevStage.unwaxed; + } + @EventHandler public void on(VehicleMoveEvent event) { if (this.damage <= 0 || !(event.getVehicle() instanceof Minecart minecart)) { @@ -84,35 +128,41 @@ public void on(VehicleMoveEvent event) { } Location location = new Location(minecart.getWorld(), x, from.getY(), z); Block topCopperBlock = location.getBlock().getRelative(BlockFace.DOWN); - Optional next = WeatheringCopper.getNext(((CraftBlock) topCopperBlock).getNMS().getBlock()); - if (next.isPresent()) { + if (getNextStage(topCopperBlock.getType()) != null) { copperBlocks.add(topCopperBlock); } Block belowCopperBlock = topCopperBlock.getRelative(BlockFace.DOWN); - next = WeatheringCopper.getNext(((CraftBlock) belowCopperBlock).getNMS().getBlock()); - if (next.isPresent()) { + if (getNextStage(belowCopperBlock.getType()) != null) { copperBlocks.add(belowCopperBlock); } } } for (Block copperBlock : copperBlocks) { - CraftBlock craftBlock = (CraftBlock) copperBlock; - BlockState state = craftBlock.getNMS(); - ServerLevel level = ((CraftWorld) copperBlock.getWorld()).getHandle(); - // We damage the copper directly instead of using random ticking, as random ticking is easy to cheese - // by placing waxed copper next to the rail, entirely preventing the rest of the rail from oxidising. - WeatheringCopper copper = (WeatheringCopper) state.getBlock(); - float chanceModifier = copper.getChanceModifier(); + Material currentMaterial = copperBlock.getType(); + Material nextMaterial = getNextStage(currentMaterial); + + if (nextMaterial == null) { + continue; + } + + CopperStage stage = CopperStage.from(currentMaterial); + float chanceModifier = (stage != null) ? stage.chance : 0.0f; + if (this.damage * chanceModifier > ThreadLocalRandom.current().nextFloat()) { - copper.getNext(state).ifPresent((iblockdata2) -> { - try { - formingBlock = true; - CraftEventFactory.handleBlockFormEvent(level, craftBlock.getPosition(), iblockdata2, 3); - } finally { - formingBlock = false; + org.bukkit.block.BlockState newState = copperBlock.getState(); + newState.setType(nextMaterial); + BlockFormEvent formEvent = new BlockFormEvent(copperBlock, newState); + + try { + formingBlock = true; + Bukkit.getPluginManager().callEvent(formEvent); + if (!formEvent.isCancelled()) { + newState.update(true); } - }); + } finally { + formingBlock = false; + } } } } @@ -133,29 +183,29 @@ public void on(PlayerInteractEvent event) { return; } - Block copperBlock = block.getRelative(BlockFace.DOWN); - Optional previous = WeatheringCopper.getPrevious(((CraftBlock) copperBlock).getNMS()); - boolean damaged = false; - CraftPlayer player = (CraftPlayer) event.getPlayer(); + Player player = event.getPlayer(); - while (previous.isPresent() && event.getItem().getType() != Material.AIR) { - copperBlock.setType(previous.get().getBukkitMaterial()); - damaged = true; + // First copper block directly underneath the rail + Block topCopperBlock = block.getRelative(BlockFace.DOWN); + Material previousTop = getPreviousStage(topCopperBlock.getType()); + while (previousTop != null && item.getType() != Material.AIR) { + topCopperBlock.setType(previousTop); + damaged = true; item.damage(1, player); - previous = WeatheringCopper.getPrevious(((CraftBlock) copperBlock).getNMS()); + previousTop = getPreviousStage(topCopperBlock.getType()); } - copperBlock = copperBlock.getRelative(BlockFace.DOWN); - previous = WeatheringCopper.getPrevious(((CraftBlock) copperBlock).getNMS()); + // Second copper block two spaces underneath the rail + Block belowCopperBlock = topCopperBlock.getRelative(BlockFace.DOWN); + Material previousBelow = getPreviousStage(belowCopperBlock.getType()); - while (previous.isPresent() && event.getItem().getType() != Material.AIR) { - copperBlock.setType(previous.get().getBukkitMaterial()); + while (previousBelow != null && item.getType() != Material.AIR) { + belowCopperBlock.setType(previousBelow); damaged = true; - item.damage(1, player); - previous = WeatheringCopper.getPrevious(((CraftBlock) copperBlock).getNMS()); + previousBelow = getPreviousStage(belowCopperBlock.getType()); } if (!damaged) { @@ -177,9 +227,7 @@ public void on(BlockFormEvent event) { } Block block = event.getBlock(); - - Optional next = WeatheringCopper.getNext(((CraftBlock) block).getNMS().getBlock()); - if (next.isEmpty()) { + if (getNextStage(block.getType()) == null) { return; } @@ -194,4 +242,4 @@ public void on(BlockFormEvent event) { event.setCancelled(true); } -} +} \ No newline at end of file