mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-29 03:49:15 +00:00
0.0.36
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.block;
|
||||
|
||||
import io.papermc.paper.event.block.BlockBreakBlockEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
@@ -11,6 +12,7 @@ import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
@@ -88,11 +90,12 @@ public class BlockEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) // I forget why it's LOW before
|
||||
public void onPlayerBreak(BlockBreakEvent event) {
|
||||
org.bukkit.block.Block block = event.getBlock();
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData());
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
Player player = event.getPlayer();
|
||||
if (!BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
ImmutableBlockState state = manager.getImmutableBlockStateUnsafe(stateId);
|
||||
if (!state.isEmpty()) {
|
||||
@@ -119,13 +122,11 @@ public class BlockEventListener implements Listener {
|
||||
// play sound
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
world.playBlockSound(vec3d, state.sounds().breakSound(), 1f, 0.8f);
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (player.getGameMode() == GameMode.CREATIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
BukkitServerPlayer serverPlayer = plugin.adapt(player);
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
Key itemId = Optional.ofNullable(itemInHand).map(Item::id).orElse(ItemKeys.AIR);
|
||||
// do not drop if it's not the correct tool
|
||||
@@ -136,26 +137,83 @@ public class BlockEventListener implements Listener {
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.PLAYER, plugin.adapt(player));
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withParameter(LootParameters.TOOL, itemInHand);
|
||||
for (Item<Object> item : state.getDrops(builder, world)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
} else if (ConfigManager.enableSoundSystem()) {
|
||||
Object ownerBlock = BlockStateUtils.getBlockOwner(blockState);
|
||||
if (manager.isBlockSoundRemoved(ownerBlock)) {
|
||||
try {
|
||||
Object soundType = Reflections.field$BlockBehaviour$soundType.get(ownerBlock);
|
||||
Object breakSound = Reflections.field$SoundType$breakSound.get(soundType);
|
||||
block.getWorld().playSound(block.getLocation(), Reflections.field$SoundEvent$location.get(breakSound).toString(), SoundCategory.BLOCKS, 1f, 0.8f);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to get sound type", e);
|
||||
} else {
|
||||
// override vanilla block loots
|
||||
if (player.getGameMode() != GameMode.CREATIVE) {
|
||||
this.plugin.vanillaLootManager().getBlockLoot(stateId).ifPresent(it -> {
|
||||
if (it.override()) {
|
||||
event.setDropItems(false);
|
||||
event.setExpToDrop(0);
|
||||
}
|
||||
Location location = block.getLocation();
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(player.getWorld());
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withParameter(LootParameters.TOOL, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
ContextHolder contextHolder = builder.build();
|
||||
for (LootTable<?> lootTable : it.lootTables()) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// sound system
|
||||
if (ConfigManager.enableSoundSystem()) {
|
||||
Object ownerBlock = BlockStateUtils.getBlockOwner(blockState);
|
||||
if (this.manager.isBlockSoundRemoved(ownerBlock)) {
|
||||
try {
|
||||
Object soundType = Reflections.field$BlockBehaviour$soundType.get(ownerBlock);
|
||||
Object breakSound = Reflections.field$SoundType$breakSound.get(soundType);
|
||||
block.getWorld().playSound(block.getLocation(), Reflections.field$SoundEvent$location.get(breakSound).toString(), SoundCategory.BLOCKS, 1f, 0.8f);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to get sound type", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// override vanilla block loots
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onBlockBreakBlock(BlockBreakBlockEvent event) {
|
||||
Block block = event.getBlock();
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData());
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
if (!BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
return;
|
||||
}
|
||||
this.plugin.vanillaLootManager().getBlockLoot(stateId).ifPresent(it -> {
|
||||
if (it.override()) {
|
||||
event.getDrops().clear();
|
||||
event.setExpToDrop(0);
|
||||
}
|
||||
|
||||
Location location = block.getLocation();
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(location.getWorld());
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
ContextHolder contextHolder = builder.build();
|
||||
for (LootTable<?> lootTable : it.lootTables()) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onStep(GenericGameEvent event) {
|
||||
if (event.getEvent() != GameEvent.STEP) return;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import com.saicone.rtag.data.ComponentType;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BoneMealBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior;
|
||||
|
||||
@@ -193,7 +193,7 @@ public class ItemEventListener implements Listener {
|
||||
Direction direction = DirectionUtils.toDirection(event.getBlockFace());
|
||||
BlockHitResult hitResult = new BlockHitResult(vec3d, direction, pos, false);
|
||||
try {
|
||||
BlockData craftBlockData = BlockStateUtils.createBlockData(againCustomBlock.vanillaBlockState().handle());
|
||||
BlockData craftBlockData = BlockStateUtils.fromBlockData(againCustomBlock.vanillaBlockState().handle());
|
||||
if (InteractUtils.isInteractable(Key.of(clickedBlock.getType().getKey().asString()), bukkitPlayer, craftBlockData, hitResult, itemInHand)) {
|
||||
if (!player.isSecondaryUseActive()) {
|
||||
player.setResendSound();
|
||||
|
||||
@@ -71,7 +71,7 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
|
||||
org.bukkit.entity.Player bukkitPlayer = ((org.bukkit.entity.Player) player.platformPlayer());
|
||||
// Call bukkit event
|
||||
EntityChangeBlockEvent event = new EntityChangeBlockEvent(bukkitPlayer, block, BlockStateUtils.createBlockData(newState.customBlockState().handle()));
|
||||
EntityChangeBlockEvent event = new EntityChangeBlockEvent(bukkitPlayer, block, BlockStateUtils.fromBlockData(newState.customBlockState().handle()));
|
||||
if (EventUtils.fireAndCheckCancel(event)) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class WaterBucketItemBehavior extends ItemBehavior {
|
||||
|
||||
// TODO Refactor all of this because it's playing a trick with the server
|
||||
ImmutableBlockState nextState = state.with(waterlogged, true);
|
||||
block.setBlockData(BlockStateUtils.createBlockData(nextState.vanillaBlockState().handle()), false);
|
||||
block.setBlockData(BlockStateUtils.fromBlockData(nextState.vanillaBlockState().handle()), false);
|
||||
// actually we should broadcast this change
|
||||
context.getPlayer().sendPacket(BlockStateUtils.createBlockUpdatePacket(pos, state), true);
|
||||
BukkitCraftEngine.instance().scheduler().sync().runDelayed(() ->
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package net.momirealms.craftengine.bukkit.loot;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.loot.VanillaLoot;
|
||||
import net.momirealms.craftengine.core.loot.VanillaLootManager;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.PreConditions;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class BukkitVanillaLootManager implements VanillaLootManager {
|
||||
private final CraftEngine plugin;
|
||||
private final Map<Integer, VanillaLoot> blockLoots;
|
||||
|
||||
public BukkitVanillaLootManager(CraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
this.blockLoots = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
this.blockLoots.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<VanillaLoot> getBlockLoot(int vanillaBlockState) {
|
||||
return Optional.ofNullable(this.blockLoots.get(vanillaBlockState));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
String type = (String) section.get("type");
|
||||
if (PreConditions.isNull(type, () -> this.plugin.logger().warn(path, "`type` option is required for vanilla-loot " + id))) {
|
||||
return;
|
||||
}
|
||||
VanillaLoot.Type typeEnum = VanillaLoot.Type.valueOf(type.toUpperCase(Locale.ENGLISH));
|
||||
boolean override = (boolean) section.getOrDefault("override", false);
|
||||
List<String> targets = MiscUtils.getAsStringList(section.getOrDefault("target", List.of()));
|
||||
LootTable<?> lootTable = LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), false));
|
||||
switch (typeEnum) {
|
||||
case BLOCK -> {
|
||||
for (String target : targets) {
|
||||
if (target.endsWith("]") && target.contains("[")) {
|
||||
java.lang.Object blockState = BlockStateUtils.blockDataToBlockState(Bukkit.createBlockData(target));
|
||||
if (blockState == Reflections.instance$Blocks$AIR$defaultState) {
|
||||
this.plugin.logger().warn(path, "Failed to load " + id + ". Invalid target " + target);
|
||||
return;
|
||||
}
|
||||
VanillaLoot vanillaLoot = this.blockLoots.computeIfAbsent(BlockStateUtils.blockStateToId(blockState), k -> new VanillaLoot(VanillaLoot.Type.BLOCK));
|
||||
vanillaLoot.addLootTable(lootTable);
|
||||
} else {
|
||||
for (Object blockState : BlockStateUtils.getAllBlockStates(Key.of(target))) {
|
||||
if (blockState == Reflections.instance$Blocks$AIR$defaultState) {
|
||||
this.plugin.logger().warn(path, "Failed to load " + id + ". Invalid target " + target);
|
||||
return;
|
||||
}
|
||||
VanillaLoot vanillaLoot = this.blockLoots.computeIfAbsent(BlockStateUtils.blockStateToId(blockState), k -> new VanillaLoot(VanillaLoot.Type.BLOCK));
|
||||
if (override) vanillaLoot.override(true);
|
||||
vanillaLoot.addLootTable(lootTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
||||
import net.momirealms.craftengine.bukkit.loot.BukkitVanillaLootManager;
|
||||
import net.momirealms.craftengine.bukkit.pack.BukkitPackManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitSenderFactory;
|
||||
@@ -136,6 +137,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
super.guiManager = new BukkitGuiManager(this);
|
||||
super.worldManager = new BukkitWorldManager(this);
|
||||
super.soundManager = new BukkitSoundManager(this);
|
||||
super.vanillaLootManager = new BukkitVanillaLootManager(this);
|
||||
super.enable();
|
||||
// tick task
|
||||
if (VersionHelper.isFolia()) {
|
||||
@@ -204,6 +206,8 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
// register sound parser
|
||||
this.packManager.registerConfigSectionParser(this.soundManager);
|
||||
this.packManager.registerConfigSectionParser(this.soundManager.jukeboxSongManager());
|
||||
// register vanilla loot parser
|
||||
this.packManager.registerConfigSectionParser(this.vanillaLootManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -376,7 +376,7 @@ public class PacketConsumers {
|
||||
Key itemId = state.settings().itemId();
|
||||
// no item available
|
||||
if (itemId == null) return;
|
||||
BlockData data = BlockStateUtils.createBlockData(state.vanillaBlockState().handle());
|
||||
BlockData data = BlockStateUtils.fromBlockData(state.vanillaBlockState().handle());
|
||||
// compare item
|
||||
if (data == null || !data.getMaterial().equals(item.getType())) return;
|
||||
ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, player);
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockStateUtils {
|
||||
public static final IdentityHashMap<Object, Object> CLIENT_SIDE_NOTE_BLOCKS = new IdentityHashMap<>();
|
||||
@@ -26,6 +27,17 @@ public class BlockStateUtils {
|
||||
hasInit = true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Object> getAllBlockStates(Key block) {
|
||||
try {
|
||||
Object blockIns = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$BLOCK, Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, block.namespace(), block.value()));
|
||||
Object definition = Reflections.field$Block$StateDefinition.get(blockIns);
|
||||
return (List<Object>) Reflections.field$StateDefinition$states.get(definition);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to get all block states for " + block, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object createBlockUpdatePacket(BlockPos pos, ImmutableBlockState state) {
|
||||
try {
|
||||
return Reflections.constructor$ClientboundBlockUpdatePacket.newInstance(LocationUtils.toBlockPos(pos), state.customBlockState().handle());
|
||||
|
||||
Reference in New Issue
Block a user