mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 12:29:15 +00:00
完善门音效
This commit is contained in:
@@ -39,6 +39,8 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.sound.Sounds;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
@@ -53,6 +55,10 @@ import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class BukkitBlockManager extends AbstractBlockManager {
|
||||
private static BukkitBlockManager instance;
|
||||
@@ -74,6 +80,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
private Map<Key, Integer> registeredRealBlockSlots;
|
||||
// A set of blocks that sounds have been removed
|
||||
private Set<Object> affectedSoundBlocks;
|
||||
private Map<Object, Pair<SoundData, SoundData>> affectedOpenableBlockSounds;
|
||||
private Map<Key, Key> soundMapper;
|
||||
// A list to record the order of registration
|
||||
private List<Key> blockRegisterOrder = new ObjectArrayList<>();
|
||||
@@ -285,7 +292,8 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
ImmutableMap.Builder<Key, Integer> builder1 = ImmutableMap.builder();
|
||||
ImmutableMap.Builder<Integer, Object> builder2 = ImmutableMap.builder();
|
||||
ImmutableMap.Builder<Key, List<Integer>> builder3 = ImmutableMap.builder();
|
||||
Set<Object> affectedSounds = new HashSet<>();
|
||||
Set<Object> affectedBlockSounds = new HashSet<>();
|
||||
Map<Object, Pair<SoundData, SoundData>> affectedDoors = new IdentityHashMap<>();
|
||||
Set<Object> affectedBlocks = new HashSet<>();
|
||||
List<Key> order = new ArrayList<>();
|
||||
|
||||
@@ -293,7 +301,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
|
||||
int counter = 0;
|
||||
for (Map.Entry<Key, Integer> baseBlockAndItsCount : this.registeredRealBlockSlots.entrySet()) {
|
||||
counter = registerBlockVariants(baseBlockAndItsCount, counter, builder1, builder2, builder3, affectedSounds, order);
|
||||
counter = registerBlockVariants(baseBlockAndItsCount, counter, builder1, builder2, builder3, affectedBlockSounds, order);
|
||||
}
|
||||
|
||||
freezeRegistry();
|
||||
@@ -306,7 +314,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
|
||||
for (Object block : (Iterable<Object>) MBuiltInRegistries.BLOCK) {
|
||||
Object soundType = CoreReflections.field$BlockBehaviour$soundType.get(block);
|
||||
if (affectedSounds.contains(soundType)) {
|
||||
if (affectedBlockSounds.contains(soundType)) {
|
||||
Object state = getOnlyBlockState(block);
|
||||
if (BlockStateUtils.isVanillaBlock(state)) {
|
||||
affectedBlocks.add(block);
|
||||
@@ -320,7 +328,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
this.affectedSoundBlocks = ImmutableSet.copyOf(affectedBlocks);
|
||||
|
||||
ImmutableMap.Builder<Key, Key> soundMapperBuilder = ImmutableMap.builder();
|
||||
for (Object soundType : affectedSounds) {
|
||||
for (Object soundType : affectedBlockSounds) {
|
||||
for (Field field : List.of(CoreReflections.field$SoundType$placeSound, CoreReflections.field$SoundType$fallSound, CoreReflections.field$SoundType$hitSound, CoreReflections.field$SoundType$stepSound, CoreReflections.field$SoundType$breakSound)) {
|
||||
Object soundEvent = field.get(soundType);
|
||||
Key previousId = Key.of(FastNMS.INSTANCE.field$SoundEvent$location(soundEvent).toString());
|
||||
@@ -328,12 +336,53 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
}
|
||||
|
||||
Predicate<Key> predicate = it -> this.realBlockArranger.containsKey(it);
|
||||
Consumer<Key> soundCallback = s -> soundMapperBuilder.put(s, Key.of("replaced." + s.value()));
|
||||
BiConsumer<Object, Pair<SoundData, SoundData>> affectedBlockCallback = affectedDoors::put;
|
||||
Function<Key, SoundData> soundMapper = (k) -> SoundData.of(k, SoundData.SoundValue.FIXED_1, SoundData.SoundValue.ranged(0.9f, 1f));
|
||||
collectDoorSounds(predicate, Sounds.WOODEN_TRAPDOOR_OPEN, Sounds.WOODEN_TRAPDOOR_CLOSE, Sounds.WOODEN_TRAPDOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.NETHER_WOOD_TRAPDOOR_OPEN, Sounds.NETHER_WOOD_TRAPDOOR_CLOSE, Sounds.NETHER_TRAPDOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.BAMBOO_WOOD_TRAPDOOR_OPEN, Sounds.BAMBOO_WOOD_TRAPDOOR_CLOSE, Sounds.BAMBOO_TRAPDOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.CHERRY_WOOD_TRAPDOOR_OPEN, Sounds.CHERRY_WOOD_TRAPDOOR_CLOSE, Sounds.CHERRY_TRAPDOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.COPPER_TRAPDOOR_OPEN, Sounds.COPPER_TRAPDOOR_CLOSE, Sounds.COPPER_TRAPDOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.WOODEN_DOOR_OPEN, Sounds.WOODEN_DOOR_CLOSE, Sounds.WOODEN_DOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.NETHER_WOOD_DOOR_OPEN, Sounds.NETHER_WOOD_DOOR_CLOSE, Sounds.NETHER_DOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.BAMBOO_WOOD_DOOR_OPEN, Sounds.BAMBOO_WOOD_DOOR_CLOSE, Sounds.BAMBOO_DOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.CHERRY_WOOD_DOOR_OPEN, Sounds.CHERRY_WOOD_DOOR_CLOSE, Sounds.CHERRY_DOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.COPPER_DOOR_OPEN, Sounds.COPPER_DOOR_CLOSE, Sounds.COPPER_DOORS, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.WOODEN_FENCE_GATE_OPEN, Sounds.WOODEN_FENCE_GATE_CLOSE, Sounds.WOODEN_FENCE_GATES, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.NETHER_WOOD_FENCE_GATE_OPEN, Sounds.NETHER_WOOD_FENCE_GATE_CLOSE, Sounds.NETHER_FENCE_GATES, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.BAMBOO_WOOD_FENCE_GATE_OPEN, Sounds.BAMBOO_WOOD_FENCE_GATE_CLOSE, Sounds.BAMBOO_FENCE_GATES, soundMapper, soundCallback, affectedBlockCallback);
|
||||
collectDoorSounds(predicate, Sounds.CHERRY_WOOD_FENCE_GATE_OPEN, Sounds.CHERRY_WOOD_FENCE_GATE_CLOSE, Sounds.CHERRY_FENCE_GATES, soundMapper, soundCallback, affectedBlockCallback);
|
||||
this.affectedOpenableBlockSounds = ImmutableMap.copyOf(affectedDoors);
|
||||
this.soundMapper = soundMapperBuilder.buildKeepingLast();
|
||||
} catch (Throwable e) {
|
||||
plugin.logger().warn("Failed to inject blocks.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void collectDoorSounds(Predicate<Key> isUsedForCustomBlock,
|
||||
Key openSound,
|
||||
Key closeSound,
|
||||
List<Key> doors,
|
||||
Function<Key, SoundData> soundMapper,
|
||||
Consumer<Key> soundCallback,
|
||||
BiConsumer<Object, Pair<SoundData, SoundData>> affectedBlockCallback) {
|
||||
for (Key d : doors) {
|
||||
if (isUsedForCustomBlock.test(d)) {
|
||||
soundCallback.accept(openSound);
|
||||
soundCallback.accept(closeSound);
|
||||
for (Key door : doors) {
|
||||
Object block = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(door));
|
||||
if (block != null) {
|
||||
affectedBlockCallback.accept(block, Pair.of(soundMapper.apply(Key.of("replaced." + openSound.value())), soundMapper.apply(Key.of("replaced." + closeSound.value()))));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockParser implements ConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[]{"blocks", "block"};
|
||||
|
||||
@@ -598,6 +647,14 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
return this.affectedSoundBlocks.contains(block);
|
||||
}
|
||||
|
||||
public boolean isOpenableBlockSoundRemoved(Object block) {
|
||||
return this.affectedOpenableBlockSounds.containsKey(block);
|
||||
}
|
||||
|
||||
public SoundData getRemovedOpenableBlockSound(Object block, boolean open) {
|
||||
return open ? this.affectedOpenableBlockSounds.get(block).left() : this.affectedOpenableBlockSounds.get(block).right();
|
||||
}
|
||||
|
||||
private Map<String, String> loadBlockStateMappings(YamlDocument mappings) {
|
||||
Map<String, String> blockStateMappings = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> entry : mappings.getStringRouteMappedValues(false).entrySet()) {
|
||||
|
||||
@@ -238,15 +238,8 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
if (!this.canOpenWithHand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
if (context.getItem() == null) {
|
||||
setOpen(context.getPlayer(), context.getLevel().serverWorld(), state, context.getClickedPos(), !state.get(this.openProperty));
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!context.getPlayer().isSecondaryUseActive()) {
|
||||
setOpen(context.getPlayer(), context.getLevel().serverWorld(), state, context.getClickedPos(), !state.get(this.openProperty));
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
setOpen(context.getPlayer(), context.getLevel().serverWorld(), state, context.getClickedPos(), !state.get(this.openProperty));
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,6 @@ import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -49,6 +49,7 @@ public class StrippableBlockBehavior extends BukkitBlockBehavior {
|
||||
return this.stripped;
|
||||
}
|
||||
|
||||
// TODO 转移到 axe_item里
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) {
|
||||
|
||||
@@ -108,19 +108,12 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) {
|
||||
public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) {
|
||||
if (!this.canOpenWithHand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
if (context.getItem() == null) {
|
||||
playerToggle(context, state);
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!context.getPlayer().isSecondaryUseActive()) {
|
||||
playerToggle(context, state);
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
playerToggle(context, state);
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -20,18 +20,23 @@ import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.item.setting.FoodData;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Openable;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
@@ -167,17 +172,45 @@ public class ItemEventListener implements Listener {
|
||||
|
||||
if (hitResult != null) {
|
||||
UseOnContext useOnContext = new UseOnContext(serverPlayer, hand, itemInHand, hitResult);
|
||||
if (immutableBlockState.behavior() instanceof AbstractBlockBehavior behavior) {
|
||||
InteractionResult result = behavior.useOnBlock(useOnContext, immutableBlockState);
|
||||
if (result.success()) {
|
||||
serverPlayer.updateLastSuccessfulInteractionTick(serverPlayer.gameTicks());
|
||||
boolean hasItem = player.getInventory().getItemInMainHand().getType() != Material.AIR || player.getInventory().getItemInOffHand().getType() != Material.AIR;
|
||||
boolean flag = player.isSneaking() && hasItem;
|
||||
if (!flag) {
|
||||
if (immutableBlockState.behavior() instanceof AbstractBlockBehavior behavior) {
|
||||
InteractionResult result = behavior.useOnBlock(useOnContext, immutableBlockState);
|
||||
if (result.success()) {
|
||||
serverPlayer.updateLastSuccessfulInteractionTick(serverPlayer.gameTicks());
|
||||
if (result == InteractionResult.SUCCESS_AND_CANCEL) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (result == InteractionResult.TRY_EMPTY_HAND && hand == InteractionHand.MAIN_HAND) {
|
||||
result = behavior.useWithoutItem(useOnContext, immutableBlockState);
|
||||
if (result.success()) {
|
||||
serverPlayer.updateLastSuccessfulInteractionTick(serverPlayer.gameTicks());
|
||||
if (result == InteractionResult.SUCCESS_AND_CANCEL) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (result == InteractionResult.FAIL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (result == InteractionResult.SUCCESS_AND_CANCEL) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (result != InteractionResult.PASS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Config.enableSoundSystem() && hitResult != null) {
|
||||
Object blockOwner = FastNMS.INSTANCE.method$BlockState$getBlock(blockState);
|
||||
if (this.plugin.blockManager().isOpenableBlockSoundRemoved(blockOwner)) {
|
||||
boolean hasItem = player.getInventory().getItemInMainHand().getType() != Material.AIR || player.getInventory().getItemInOffHand().getType() != Material.AIR;
|
||||
boolean flag = player.isSneaking() && hasItem;
|
||||
if (!flag) {
|
||||
if (blockData instanceof Openable openable) {
|
||||
SoundData soundData = this.plugin.blockManager().getRemovedOpenableBlockSound(blockOwner, !openable.isOpen());
|
||||
serverPlayer.playSound(soundData.id(), SoundSource.BLOCK, soundData.volume().get(), soundData.pitch().get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user