From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik <40902469+Samsuik@users.noreply.github.com> Date: Wed, 15 Nov 2023 23:18:38 +0000 Subject: [PATCH] Explosion Durable Blocks diff --git a/src/main/java/me/samsuik/sakura/explosion/durable/DurableBlockManager.java b/src/main/java/me/samsuik/sakura/explosion/durable/DurableBlockManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e52cae27c2bbf4fa02d49d1c69d8e1240fddfb81 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/explosion/durable/DurableBlockManager.java @@ -0,0 +1,43 @@ +package me.samsuik.sakura.explosion.durable; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import net.minecraft.core.BlockPos; + +import java.util.concurrent.TimeUnit; + +public final class DurableBlockManager { + private final Cache durableBlocks = CacheBuilder.newBuilder() + .expireAfterAccess(1, TimeUnit.MINUTES) + .maximumSize(65534) + .build(); + + public boolean damage(BlockPos pos, DurableMaterial material) { + DurableBlock block = this.durableBlocks.getIfPresent(pos); + if (block == null) { + this.durableBlocks.put(pos, block = new DurableBlock(material.durability())); + } + return block.damage(); + } + + public int durability(BlockPos pos, DurableMaterial material) { + final DurableBlock block = this.durableBlocks.getIfPresent(pos); + return block != null ? block.durability() : material.durability(); + } + + private static final class DurableBlock { + private int durability; + + public DurableBlock(int durability) { + this.durability = durability; + } + + public int durability() { + return this.durability; + } + + public boolean damage() { + return --this.durability <= 0; + } + } +} diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java index c816c935ecc74a811ffdffbe6ded73c06e92324a..4da4efe7114d4fcea5e79bcab292dc4b3c782de9 100644 --- a/src/main/java/net/minecraft/world/item/BlockItem.java +++ b/src/main/java/net/minecraft/world/item/BlockItem.java @@ -47,8 +47,32 @@ public class BlockItem extends Item { this.block = block; } + // Sakura start - explosion durable blocks + private void sendBlockDurabilityToPlayer(UseOnContext context) { + Player player = context.getPlayer(); + BlockState state = context.getLevel().getBlockState(context.getClickedPos()); + Block block = state.getBlock(); + me.samsuik.sakura.explosion.durable.DurableMaterial material = context.getLevel().localConfig().config(context.getClickedPos()).durableMaterials.get(block); + + if (material != null) { + int remaining = context.getLevel().durabilityManager.durability(context.getClickedPos(), material); + int durability = material.durability(); + + player.getBukkitEntity().sendRichMessage( + me.samsuik.sakura.configuration.GlobalConfiguration.get().messages.durableBlockInteraction, + net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.unparsed("remaining", String.valueOf(remaining)), + net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.unparsed("durability", String.valueOf(durability)) + ); + } + } + @Override public InteractionResult useOn(UseOnContext context) { + if (this.getBlock() == net.minecraft.world.level.block.Blocks.POTATOES && context.getPlayer() != null) { + this.sendBlockDurabilityToPlayer(context); + } + // Sakura end - explosion durable blocks + InteractionResult enuminteractionresult = this.place(new BlockPlaceContext(context)); return !enuminteractionresult.consumesAction() && context.getItemInHand().has(DataComponents.CONSUMABLE) ? super.use(context.getLevel(), context.getPlayer(), context.getHand()) : enuminteractionresult; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 2d5783a6ff7a9ce6dcb6f2895ff80928e62f0cd2..0ae2d83055252146e346b06cc8360eef56d39f5c 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -843,6 +843,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // Paper end - optimise random ticking public final me.samsuik.sakura.entity.merge.EntityMergeHandler mergeHandler = new me.samsuik.sakura.entity.merge.EntityMergeHandler(); // Sakura - merge cannon entities public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(); // Sakura - explosion density cache + public final me.samsuik.sakura.explosion.durable.DurableBlockManager durabilityManager = new me.samsuik.sakura.explosion.durable.DurableBlockManager(); // Sakura - explosion durable blocks protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.function.Supplier sakuraWorldConfigCreator, java.util.concurrent.Executor executor) { // Sakura - sakura configuration files // Paper - create paper world config & Anti-Xray // Paper start - getblock optimisations - cache world height/sections diff --git a/src/main/java/net/minecraft/world/level/ServerExplosion.java b/src/main/java/net/minecraft/world/level/ServerExplosion.java index 11b12c1c4eff015bc40c7e7e965badb3f3fd272e..8268f8df624a73eaf0b8baad9aa16bab2ed0f0bc 100644 --- a/src/main/java/net/minecraft/world/level/ServerExplosion.java +++ b/src/main/java/net/minecraft/world/level/ServerExplosion.java @@ -134,7 +134,7 @@ public class ServerExplosion implements Explosion { BlockState blockState = ((ca.spottedleaf.moonrise.patches.getblock.GetBlockChunk)chunk).moonrise$getBlock(x, y, z); FluidState fluidState = blockState.getFluidState(); - Optional resistance = !calculateResistance ? Optional.empty() : this.damageCalculator.getBlockExplosionResistance((Explosion)(Object)this, this.level, pos, blockState, fluidState); + Optional resistance = !calculateResistance ? Optional.empty() : this.calculateBlockResistance(blockState, fluidState, pos); // Sakura - explosion durable blocks ret = new ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache( key, pos, blockState, fluidState, @@ -393,6 +393,20 @@ public class ServerExplosion implements Explosion { // Paper end - collision optimisations } // Sakura end - specialised explosions + // Sakura start - explosion durable blocks + private Optional calculateBlockResistance(BlockState blockState, FluidState fluidState, BlockPos pos) { + if (!blockState.isAir()) { + Block block = blockState.getBlock(); + me.samsuik.sakura.explosion.durable.DurableMaterial material = this.level.localConfig().config(pos).durableMaterials.get(block); + + if (material != null && material.resistance() >= 0.0f && (this.level.sakuraConfig().cannons.explosion.allowNonTntBreakingDurableBlocks || this.source instanceof net.minecraft.world.entity.item.PrimedTnt)) { + return Optional.of(material.resistance()); + } + } + + return this.damageCalculator.getBlockExplosionResistance(this, this.level, pos, blockState, fluidState); + } + // Sakura end - explosion durable blocks public ServerExplosion(ServerLevel world, @Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, Vec3 pos, float power, boolean createFire, Explosion.BlockInteraction destructionType) { this.level = world; @@ -780,6 +794,16 @@ public class ServerExplosion implements Explosion { } } // CraftBukkit end + // Sakura start - explosion durable blocks + if (this.level.sakuraConfig().cannons.explosion.allowNonTntBreakingDurableBlocks || this.source instanceof net.minecraft.world.entity.item.PrimedTnt) { + me.samsuik.sakura.explosion.durable.DurableMaterial material = this.level.localConfig().config(blockposition).durableMaterials.get(block); + + if (material != null && material.durability() >= 0 && !this.level.durabilityManager.damage(blockposition, material)) { + iterator.remove(); + continue; + } + } + // Sakura end - explosion durable blocks this.level.getBlockState(blockposition).onExplosionHit(this.level, blockposition, this, (itemstack, blockposition1) -> { ServerExplosion.addOrAppendStack(list1, itemstack, blockposition1);