mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-29 11:59:11 +00:00
Implement Strippable Block
This commit is contained in:
@@ -54,7 +54,7 @@ blocks:
|
||||
loot:
|
||||
template: loot_table:normal
|
||||
arguments:
|
||||
item: default:palm_log
|
||||
item: default:stripped_palm_log
|
||||
settings:
|
||||
template: block_settings:log
|
||||
overrides:
|
||||
@@ -107,7 +107,7 @@ blocks:
|
||||
loot:
|
||||
template: loot_table:normal
|
||||
arguments:
|
||||
item: default:palm_wood
|
||||
item: default:stripped_palm_wood
|
||||
settings:
|
||||
template: block_settings:log
|
||||
overrides:
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.momirealms.craftengine.core.item.modifier.ItemModifier;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -70,7 +71,7 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemBehavior behavior() {
|
||||
public @NotNull ItemBehavior behavior() {
|
||||
return this.behavior;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
@@ -7,6 +8,7 @@ import net.momirealms.craftengine.bukkit.util.MaterialUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.*;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviors;
|
||||
import net.momirealms.craftengine.core.item.modifier.CustomModelDataModifier;
|
||||
import net.momirealms.craftengine.core.item.modifier.IdModifier;
|
||||
@@ -35,12 +37,25 @@ import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
private static final Map<Key, ItemBehavior> VANILLA_ITEM_EXTRA_BEHAVIORS = new HashMap<>();
|
||||
|
||||
static {
|
||||
registerVanillaItemExtraBehavior(AxeItemBehavior.INSTANCE, ItemKeys.WOODEN_AXE, ItemKeys.STONE_AXE, ItemKeys.IRON_AXE, ItemKeys.GOLDEN_AXE, ItemKeys.DIAMOND_AXE, ItemKeys.NETHERITE_AXE);
|
||||
}
|
||||
|
||||
private static void registerVanillaItemExtraBehavior(ItemBehavior behavior, Key... items) {
|
||||
for (Key key : items) {
|
||||
VANILLA_ITEM_EXTRA_BEHAVIORS.put(key, behavior);
|
||||
}
|
||||
}
|
||||
|
||||
private static BukkitItemManager instance;
|
||||
private final BukkitItemFactory factory;
|
||||
private final Map<Key, TreeSet<LegacyOverridesModel>> legacyOverrides;
|
||||
private final Map<Key, TreeMap<Integer, ItemModel>> modernOverrides;
|
||||
private final BukkitCraftEngine plugin;
|
||||
private final ItemEventListener itemEventListener;
|
||||
private final DebugStickListener debugStickListener;
|
||||
private final Map<Key, List<Holder<Key>>> vanillaItemTags;
|
||||
private final Map<Key, List<Holder<Key>>> customItemTags;
|
||||
private final Map<Key, Map<Integer, Key>> cmdConflictChecker;
|
||||
@@ -55,6 +70,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
this.customItemTags = new HashMap<>();
|
||||
this.cmdConflictChecker = new HashMap<>();
|
||||
this.itemEventListener = new ItemEventListener(plugin);
|
||||
this.debugStickListener = new DebugStickListener(plugin);
|
||||
this.registerAllVanillaItems();
|
||||
instance = this;
|
||||
}
|
||||
@@ -100,6 +116,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
public void load() {
|
||||
super.load();
|
||||
Bukkit.getPluginManager().registerEvents(this.itemEventListener, plugin.bootstrap());
|
||||
Bukkit.getPluginManager().registerEvents(this.debugStickListener, plugin.bootstrap());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,6 +126,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
this.modernOverrides.clear();
|
||||
this.customItemTags.clear();
|
||||
HandlerList.unregisterAll(this.itemEventListener);
|
||||
HandlerList.unregisterAll(this.debugStickListener);
|
||||
this.cmdConflictChecker.clear();
|
||||
}
|
||||
|
||||
@@ -168,6 +186,28 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
return wrapped.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<ItemBehavior>> getItemBehavior(Key key) {
|
||||
Optional<CustomItem<ItemStack>> customItemOptional = getCustomItem(key);
|
||||
if (customItemOptional.isPresent()) {
|
||||
CustomItem<ItemStack> customItem = customItemOptional.get();
|
||||
Key vanillaMaterial = customItem.material();
|
||||
ItemBehavior behavior = VANILLA_ITEM_EXTRA_BEHAVIORS.get(vanillaMaterial);
|
||||
if (behavior != null) {
|
||||
return Optional.of(List.of(behavior, customItem.behavior()));
|
||||
} else {
|
||||
return Optional.of(List.of(customItem.behavior()));
|
||||
}
|
||||
} else {
|
||||
ItemBehavior behavior = VANILLA_ITEM_EXTRA_BEHAVIORS.get(key);
|
||||
if (behavior != null) {
|
||||
return Optional.of(List.of(behavior));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Key> items() {
|
||||
return new ArrayList<>(customItems.keySet());
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DebugStickListener implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
|
||||
public DebugStickListener(BukkitCraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onUseDebugStick(PlayerInteractEvent event) {
|
||||
Block clickedBlock = event.getClickedBlock();
|
||||
if (clickedBlock == null) return;
|
||||
ItemStack itemInHand = event.getItem();
|
||||
if (itemInHand == null) return;
|
||||
Material material = itemInHand.getType();
|
||||
if (material != Material.DEBUG_STICK) return;
|
||||
Player bukkitPlayer = event.getPlayer();
|
||||
BukkitServerPlayer player = this.plugin.adapt(bukkitPlayer);
|
||||
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {
|
||||
return;
|
||||
}
|
||||
if (event.getHand() == EquipmentSlot.OFF_HAND) {
|
||||
int currentTicks = player.gameTicks();
|
||||
if (!player.updateLastSuccessfulInteractionTick(currentTicks)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(clickedBlock.getBlockData());
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
if (!BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
event.setCancelled(true);
|
||||
boolean update = event.getAction() == Action.RIGHT_CLICK_BLOCK;
|
||||
ImmutableBlockState clickedCustomBlock = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
||||
CustomBlock block = clickedCustomBlock.owner().value();
|
||||
Collection<Property<?>> properties = block.properties();
|
||||
String blockId = block.id().toString();
|
||||
try {
|
||||
if (properties.isEmpty()) {
|
||||
Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
} else {
|
||||
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(itemInHand);
|
||||
Object storedData = wrapped.getTag("craftengine:debug_stick_state");
|
||||
if (storedData == null) storedData = new HashMap<>();
|
||||
if (storedData instanceof Map<?,?> map) {
|
||||
Map<String, Object> data = MiscUtils.castToMap(map, false);
|
||||
String currentPropertyName = (String) data.get(blockId);
|
||||
Property<?> currentProperty = block.getProperty(currentPropertyName);
|
||||
if (currentProperty == null) {
|
||||
currentProperty = properties.iterator().next();
|
||||
}
|
||||
if (update) {
|
||||
ImmutableBlockState nextState = cycleState(clickedCustomBlock, currentProperty, player.isSecondaryUseActive());
|
||||
CraftEngineBlocks.place(clickedBlock.getLocation(), nextState, new UpdateOption.Builder().updateClients().updateKnownShape().build());
|
||||
Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.update")
|
||||
.arguments(
|
||||
Component.text(currentProperty.name()),
|
||||
Component.text(getNameHelper(nextState, currentProperty))
|
||||
)), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
} else {
|
||||
currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive());
|
||||
data.put(blockId, currentProperty.name());
|
||||
wrapped.setTag(data, "craftengine:debug_stick_state");
|
||||
wrapped.load();
|
||||
Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select")
|
||||
.arguments(
|
||||
Component.text(currentProperty.name()),
|
||||
Component.text(getNameHelper(clickedCustomBlock, currentProperty))
|
||||
)), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to send system chat packet", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> ImmutableBlockState cycleState(ImmutableBlockState state, Property<T> property, boolean inverse) {
|
||||
return state.with(property, getRelative(property.possibleValues(), state.get(property), inverse));
|
||||
}
|
||||
|
||||
private static <T> T getRelative(Iterable<T> elements, @Nullable T current, boolean inverse) {
|
||||
return inverse ? MCUtils.findPreviousInIterable(elements, current) : MCUtils.findNextInIterable(elements, current);
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> String getNameHelper(ImmutableBlockState state, Property<T> property) {
|
||||
return property.valueName(state.get(property));
|
||||
}
|
||||
}
|
||||
@@ -2,31 +2,25 @@ package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
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.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
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.entity.Player;
|
||||
@@ -39,7 +33,6 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
public class ItemEventListener implements Listener {
|
||||
@@ -62,26 +55,28 @@ public class ItemEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
// it's breaking the block
|
||||
if (action == Action.LEFT_CLICK_BLOCK && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomBlockInteractEvent interactEvent = new CustomBlockInteractEvent(
|
||||
event.getPlayer(),
|
||||
block.getLocation(),
|
||||
event.getInteractionPoint(),
|
||||
BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId),
|
||||
hand,
|
||||
event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND,
|
||||
action == Action.RIGHT_CLICK_BLOCK ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK
|
||||
);
|
||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onInteractAtBlock(PlayerInteractEvent event) {
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
if (event.useItemInHand() == Event.Result.DENY) return;
|
||||
if (event.useInteractedBlock() == Event.Result.DENY) return;
|
||||
if (event.useItemInHand() == Event.Result.DENY || event.useInteractedBlock() == Event.Result.DENY) return;
|
||||
Location interactionPoint = event.getInteractionPoint();
|
||||
if (interactionPoint == null) return;
|
||||
Player bukkitPlayer = event.getPlayer();
|
||||
@@ -90,49 +85,58 @@ public class ItemEventListener implements Listener {
|
||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
if (hand == InteractionHand.OFF_HAND) {
|
||||
int currentTicks = player.gameTicks();
|
||||
// The client will send multiple packets to the server if the client thinks it should
|
||||
// However, if the main hand item interaction is successful, the off-hand item should be blocked.
|
||||
if (!player.updateLastSuccessfulInteractionTick(currentTicks)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the item in hand
|
||||
Item<ItemStack> itemInHand = player.getItemInHand(hand);
|
||||
if (itemInHand == null) return;
|
||||
Optional<CustomItem<ItemStack>> customItem = itemInHand.getCustomItem();
|
||||
Optional<List<ItemBehavior>> optionalItemBehaviors = itemInHand.getItemBehavior();
|
||||
|
||||
Material material = itemInHand.getItem().getType();
|
||||
// is custom item
|
||||
if (customItem.isPresent()) {
|
||||
if (material.isBlock()) {
|
||||
// has custom item behavior
|
||||
if (optionalItemBehaviors.isPresent()) {
|
||||
// do not allow to place block if it's a vanilla block
|
||||
if (itemInHand.isBlockItem() && itemInHand.isCustomItem()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
CustomItem<ItemStack> item = customItem.get();
|
||||
BlockPos pos = LocationUtils.toBlockPos(clickedBlock.getLocation());
|
||||
Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ());
|
||||
Direction direction = DirectionUtils.toDirection(event.getBlockFace());
|
||||
BlockHitResult hitResult = new BlockHitResult(vec3d, direction, pos, false);
|
||||
if (!player.isSecondaryUseActive()) {
|
||||
if (InteractUtils.isInteractable(BlockStateUtils.getRealBlockId(clickedBlock), bukkitPlayer, clickedBlock.getBlockData(), hitResult, itemInHand)) return;
|
||||
for (ItemBehavior itemBehavior : optionalItemBehaviors.get()) {
|
||||
BlockPos pos = LocationUtils.toBlockPos(clickedBlock.getLocation());
|
||||
Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ());
|
||||
Direction direction = DirectionUtils.toDirection(event.getBlockFace());
|
||||
BlockHitResult hitResult = new BlockHitResult(vec3d, direction, pos, false);
|
||||
if (!player.isSecondaryUseActive()) {
|
||||
// if it's interactable on server, cancel the behaviors
|
||||
if (InteractUtils.isInteractable(BlockStateUtils.getBlockOwnerId(clickedBlock), bukkitPlayer, clickedBlock.getBlockData(), hitResult, itemInHand)) return;
|
||||
}
|
||||
InteractionResult result = itemBehavior.useOnBlock(new UseOnContext(player, hand, hitResult));
|
||||
int maxY = player.level().worldHeight().getMaxBuildHeight() - 1;
|
||||
if (direction == Direction.UP
|
||||
&& result != InteractionResult.SUCCESS
|
||||
&& pos.y() >= maxY
|
||||
&& itemBehavior instanceof BlockItemBehavior
|
||||
) {
|
||||
player.sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED));
|
||||
}
|
||||
if (result != InteractionResult.PASS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
InteractionResult result = item.behavior().useOnBlock(new UseOnContext(player, hand, hitResult));
|
||||
int maxY = player.level().worldHeight().getMaxBuildHeight() - 1;
|
||||
if (direction == Direction.UP
|
||||
&& result != InteractionResult.SUCCESS
|
||||
&& pos.y() >= maxY
|
||||
&& item.behavior() instanceof BlockItemBehavior
|
||||
) {
|
||||
player.sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED));
|
||||
}
|
||||
} else if (material.isBlock()) {
|
||||
// vanilla item
|
||||
return;
|
||||
}
|
||||
|
||||
// it's a vanilla block
|
||||
if (itemInHand.isBlockItem() && !itemInHand.isCustomItem()) {
|
||||
// client won't have sounds if the fake block is interactable
|
||||
// so we should check and resend sounds on interact
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(clickedBlock.getBlockData());
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
if (BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
return;
|
||||
}
|
||||
ImmutableBlockState againCustomBlock = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
||||
if (againCustomBlock.isEmpty()) {
|
||||
ImmutableBlockState againCustomBlock = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (againCustomBlock == null || againCustomBlock.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
BlockPos pos = LocationUtils.toBlockPos(clickedBlock.getLocation());
|
||||
@@ -140,7 +144,7 @@ public class ItemEventListener implements Listener {
|
||||
Direction direction = DirectionUtils.toDirection(event.getBlockFace());
|
||||
BlockHitResult hitResult = new BlockHitResult(vec3d, direction, pos, false);
|
||||
try {
|
||||
BlockData craftBlockData = (BlockData) Reflections.method$CraftBlockData$createData.invoke(null, againCustomBlock.vanillaBlockState().handle());
|
||||
BlockData craftBlockData = BlockStateUtils.createBlockData(againCustomBlock.vanillaBlockState().handle());
|
||||
if (InteractUtils.isInteractable(Key.of(clickedBlock.getType().getKey().asString()), bukkitPlayer, craftBlockData, hitResult, itemInHand)) {
|
||||
if (!player.isSecondaryUseActive()) {
|
||||
player.setResendSound();
|
||||
@@ -155,92 +159,4 @@ public class ItemEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onUseDebugStick(PlayerInteractEvent event) {
|
||||
Block clickedBlock = event.getClickedBlock();
|
||||
if (clickedBlock == null) return;
|
||||
ItemStack itemInHand = event.getItem();
|
||||
if (itemInHand == null) return;
|
||||
Material material = itemInHand.getType();
|
||||
if (material != Material.DEBUG_STICK) return;
|
||||
Player bukkitPlayer = event.getPlayer();
|
||||
BukkitServerPlayer player = this.plugin.adapt(bukkitPlayer);
|
||||
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {
|
||||
return;
|
||||
}
|
||||
if (event.getHand() == EquipmentSlot.OFF_HAND) {
|
||||
int currentTicks = player.gameTicks();
|
||||
if (!player.updateLastSuccessfulInteractionTick(currentTicks)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(clickedBlock.getBlockData());
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
if (!BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
event.setCancelled(true);
|
||||
boolean update = event.getAction() == Action.RIGHT_CLICK_BLOCK;
|
||||
ImmutableBlockState clickedCustomBlock = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
||||
CustomBlock block = clickedCustomBlock.owner().value();
|
||||
Collection<Property<?>> properties = block.properties();
|
||||
String blockId = block.id().toString();
|
||||
try {
|
||||
if (properties.isEmpty()) {
|
||||
Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
} else {
|
||||
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(itemInHand);
|
||||
Object storedData = wrapped.getTag("craftengine:debug_stick_state");
|
||||
if (storedData == null) storedData = new HashMap<>();
|
||||
if (storedData instanceof Map<?,?> map) {
|
||||
Map<String, Object> data = MiscUtils.castToMap(map, false);
|
||||
String currentPropertyName = (String) data.get(blockId);
|
||||
Property<?> currentProperty = block.getProperty(currentPropertyName);
|
||||
if (currentProperty == null) {
|
||||
currentProperty = properties.iterator().next();
|
||||
}
|
||||
if (update) {
|
||||
ImmutableBlockState nextState = cycleState(clickedCustomBlock, currentProperty, player.isSecondaryUseActive());
|
||||
CraftEngineBlocks.place(clickedBlock.getLocation(), nextState, new UpdateOption.Builder().updateClients().updateKnownShape().build());
|
||||
Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.update")
|
||||
.arguments(
|
||||
Component.text(currentProperty.name()),
|
||||
Component.text(getNameHelper(nextState, currentProperty))
|
||||
)), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
} else {
|
||||
currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive());
|
||||
data.put(blockId, currentProperty.name());
|
||||
wrapped.setTag(data, "craftengine:debug_stick_state");
|
||||
wrapped.load();
|
||||
Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select")
|
||||
.arguments(
|
||||
Component.text(currentProperty.name()),
|
||||
Component.text(getNameHelper(clickedCustomBlock, currentProperty))
|
||||
)), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to send system chat packet", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> ImmutableBlockState cycleState(ImmutableBlockState state, Property<T> property, boolean inverse) {
|
||||
return state.with(property, getRelative(property.possibleValues(), state.get(property), inverse));
|
||||
}
|
||||
|
||||
private static <T> T getRelative(Iterable<T> elements, @Nullable T current, boolean inverse) {
|
||||
return inverse ? MCUtils.findPreviousInIterable(elements, current) : MCUtils.findNextInIterable(elements, current);
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> String getNameHelper(ImmutableBlockState state, Property<T> property) {
|
||||
return property.valueName(state.get(property));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.StrippableBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.MaterialUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import org.bukkit.GameEvent;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class AxeItemBehavior extends ItemBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public static final AxeItemBehavior INSTANCE = new AxeItemBehavior();
|
||||
private static final Key AXE_STRIP_SOUND = Key.of("minecraft:item.axe.strip");
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
BukkitWorldBlock clicked = (BukkitWorldBlock) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
Block block = clicked.block();
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
|
||||
if (state == null || state.isEmpty()) return InteractionResult.PASS;
|
||||
|
||||
if (!(state.behavior() instanceof StrippableBlockBehavior blockBehavior)) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
Player player = context.getPlayer();
|
||||
@SuppressWarnings("unchecked")
|
||||
Item<ItemStack> offHandItem = (Item<ItemStack>) player.getItemInHand(InteractionHand.OFF_HAND);
|
||||
// is using a shield
|
||||
if (context.getHand() == InteractionHand.MAIN_HAND && offHandItem != null && offHandItem.vanillaId().equals(ItemKeys.SHIELD) && !player.isSecondaryUseActive()) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
Optional<CustomBlock> optionalNewCustomBlock = BukkitBlockManager.instance().getBlock(blockBehavior.stripped());
|
||||
if (optionalNewCustomBlock.isEmpty()) {
|
||||
CraftEngine.instance().logger().warn("stripped block " + blockBehavior.stripped() + " does not exist");
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
CustomBlock newCustomBlock = optionalNewCustomBlock.get();
|
||||
CompoundTag compoundTag = state.propertiesNbt();
|
||||
ImmutableBlockState newState = newCustomBlock.getBlockState(compoundTag);
|
||||
|
||||
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()));
|
||||
if (EventUtils.fireAndCheckCancel(event)) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
BlockPos pos = context.getClickedPos();
|
||||
context.getLevel().playBlockSound(Vec3d.atCenterOf(pos), AXE_STRIP_SOUND, 1, 1);
|
||||
CraftEngineBlocks.place(block.getLocation(), newState, UpdateOption.UPDATE_ALL_IMMEDIATE);
|
||||
block.getWorld().sendGameEvent(bukkitPlayer, GameEvent.BLOCK_CHANGE, new Vector(pos.x(), pos.y(), pos.z()));
|
||||
Item<?> item = context.getItem();
|
||||
Material material = MaterialUtils.getMaterial(item.vanillaId());
|
||||
bukkitPlayer.setStatistic(Statistic.USE_ITEM, material, bukkitPlayer.getStatistic(Statistic.USE_ITEM, material) + 1);
|
||||
|
||||
ItemStack itemStack = (ItemStack) item.getItem();
|
||||
itemStack.damage(1, bukkitPlayer);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public ItemBehavior create(Key id, Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,12 @@ public class BukkitItemBehaviors extends ItemBehaviors {
|
||||
public static final Key EMPTY = Key.from("craftengine:empty");
|
||||
public static final Key BLOCK_ITEM = Key.from("craftengine:block_item");
|
||||
public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item");
|
||||
public static final Key AXE_ITEM = Key.from("craftengine:axe_item");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (args, id) -> EmptyItemBehavior.INSTANCE);
|
||||
register(BLOCK_ITEM, BlockItemBehavior.FACTORY);
|
||||
register(FURNITURE_ITEM, FurnitureItemBehavior.FACTORY);
|
||||
register(AXE_ITEM, AxeItemBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ public abstract class BukkitItemFactory extends ItemFactory<CraftEngine, RTagIte
|
||||
return Optional.of(Key.of(id.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isBlockItem(ItemWrapper<ItemStack> item) {
|
||||
return item.getItem().getType().isBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Key vanillaId(ItemWrapper<ItemStack> item) {
|
||||
return Key.of(item.getItem().getType().getKey().asString());
|
||||
|
||||
@@ -316,7 +316,7 @@ public class PacketConsumers {
|
||||
Key itemId = state.settings().itemId();
|
||||
// no item available
|
||||
if (itemId == null) return;
|
||||
BlockData data = (BlockData) Reflections.method$CraftBlockData$createData.invoke(null, state.vanillaBlockState().handle());
|
||||
BlockData data = BlockStateUtils.createBlockData(state.vanillaBlockState().handle());
|
||||
// compare item
|
||||
if (data == null || !data.getMaterial().equals(item.getType())) return;
|
||||
ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, (BukkitServerPlayer) user);
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -360,7 +361,7 @@ public class BukkitServerPlayer extends Player {
|
||||
if (canInstabuild() && (itemMaterial == Material.DEBUG_STICK
|
||||
|| itemMaterial == Material.TRIDENT
|
||||
|| (VersionHelper.isVersionNewerThan1_20_5() && itemMaterial == MaterialUtils.MACE)
|
||||
|| item.is(Key.of("minecraft:swords")))) {
|
||||
|| item.is(ItemTags.SWORDS))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -482,6 +483,7 @@ public class BukkitServerPlayer extends Player {
|
||||
return DirectionUtils.toDirection(platformPlayer().getFacing());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Item<ItemStack> getItemInHand(InteractionHand hand) {
|
||||
PlayerInventory inventory = platformPlayer().getInventory();
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.IdentityHashMap;
|
||||
|
||||
public class BlockStateUtils {
|
||||
@@ -23,6 +24,14 @@ public class BlockStateUtils {
|
||||
hasInit = true;
|
||||
}
|
||||
|
||||
public static BlockData createBlockData(Object blockState) {
|
||||
try {
|
||||
return (BlockData) Reflections.method$CraftBlockData$createData.invoke(null, blockState);
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static int blockDataToId(BlockData blockData) {
|
||||
try {
|
||||
Object blockState = Reflections.field$CraftBlockData$data.get(blockData);
|
||||
@@ -32,13 +41,13 @@ public class BlockStateUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static Key getRealBlockId(Block block) {
|
||||
public static Key getBlockOwnerId(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
Object blockState = blockDataToBlockState(data);
|
||||
return getRealBlockIdFromState(blockState);
|
||||
return getBlockOwnerIdFromState(blockState);
|
||||
}
|
||||
|
||||
public static Key getRealBlockIdFromState(Object blockState) {
|
||||
public static Key getBlockOwnerIdFromState(Object blockState) {
|
||||
String id = blockState.toString();
|
||||
int first = id.indexOf('{');
|
||||
int last = id.indexOf('}');
|
||||
|
||||
@@ -8,6 +8,9 @@ import java.util.Map;
|
||||
public class ItemTags {
|
||||
private static final Map<Key, Object> CACHE = new HashMap<>();
|
||||
|
||||
public static final Key AXES = Key.of("minecraft:axes");
|
||||
public static final Key SWORDS = Key.of("minecraft:swords");
|
||||
|
||||
public static Object getOrCreate(Key key) {
|
||||
Object value = CACHE.get(key);
|
||||
if (value == null) {
|
||||
|
||||
@@ -2689,6 +2689,42 @@ public class Reflections {
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$EquipmentSlot = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.entity.EquipmentSlot"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.entity.EnumItemSlot")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$EquipmentSlot$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$EquipmentSlot, clazz$EquipmentSlot.arrayType()
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$EquipmentSlot$MAINHAND;
|
||||
public static final Object instance$EquipmentSlot$OFFHAND;
|
||||
public static final Object instance$EquipmentSlot$FEET;
|
||||
public static final Object instance$EquipmentSlot$LEGS;
|
||||
public static final Object instance$EquipmentSlot$CHEST;
|
||||
public static final Object instance$EquipmentSlot$HEAD;
|
||||
// public static final Object instance$EquipmentSlot$BODY;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$EquipmentSlot$values.invoke(null);
|
||||
instance$EquipmentSlot$MAINHAND = values[0];
|
||||
instance$EquipmentSlot$OFFHAND = values[1];
|
||||
instance$EquipmentSlot$FEET = values[2];
|
||||
instance$EquipmentSlot$LEGS = values[3];
|
||||
instance$EquipmentSlot$CHEST = values[4];
|
||||
instance$EquipmentSlot$HEAD = values[5];
|
||||
// instance$EquipmentSlot$BODY = values[6];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Block$defaultBlockState = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Block, clazz$BlockState
|
||||
@@ -4124,4 +4160,11 @@ public class Reflections {
|
||||
clazz$CraftInventoryCrafting, clazz$Container, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$LivingEntity = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.entity.LivingEntity"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.entity.EntityLiving")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class ImmutableBlockState extends BlockStateHolder {
|
||||
this.vanillaBlockState = vanillaBlockState;
|
||||
}
|
||||
|
||||
private CompoundTag propertiesNbt() {
|
||||
public CompoundTag propertiesNbt() {
|
||||
CompoundTag properties = new CompoundTag();
|
||||
for (Property<?> property : getProperties()) {
|
||||
Comparable<?> value = get(property);
|
||||
|
||||
@@ -5,11 +5,13 @@ import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class Player extends Entity implements NetWorkUser {
|
||||
|
||||
public abstract boolean isSecondaryUseActive();
|
||||
|
||||
@Nullable
|
||||
public abstract Item<?> getItemInHand(InteractionHand hand);
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
@@ -42,6 +43,21 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
|
||||
return ((ItemManager<I>) factory.plugin.itemManager()).getCustomItem(id());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<ItemBehavior>> getItemBehavior() {
|
||||
return factory.plugin.itemManager().getItemBehavior(id());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomItem() {
|
||||
return factory.plugin.itemManager().getCustomItem(id()).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockItem() {
|
||||
return factory.isBlockItem(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key id() {
|
||||
return this.factory.id(this.item);
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemModifier;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -23,6 +24,7 @@ public interface CustomItem<I> extends BuildableItem<I> {
|
||||
|
||||
Item<I> buildItem(Player player);
|
||||
|
||||
@NotNull
|
||||
ItemBehavior behavior();
|
||||
|
||||
interface Builder<I> {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
@@ -16,6 +17,12 @@ public interface Item<I> {
|
||||
|
||||
Optional<CustomItem<I>> getCustomItem();
|
||||
|
||||
Optional<List<ItemBehavior>> getItemBehavior();
|
||||
|
||||
boolean isCustomItem();
|
||||
|
||||
boolean isBlockItem();
|
||||
|
||||
Key id();
|
||||
|
||||
Key vanillaId();
|
||||
|
||||
@@ -102,4 +102,6 @@ public abstract class ItemFactory<P extends Plugin, W extends ItemWrapper<I>, I>
|
||||
protected abstract void maxStackSize(ItemWrapper<I> item, Integer maxStackSize);
|
||||
|
||||
protected abstract boolean is(ItemWrapper<I> item, Key itemTag);
|
||||
|
||||
protected abstract boolean isBlockItem(ItemWrapper<I> item);
|
||||
}
|
||||
|
||||
@@ -11,4 +11,10 @@ public class ItemKeys {
|
||||
public static final Key FISHING_ROD = Key.of("minecraft:fishing_rod");
|
||||
public static final Key ELYTRA = Key.of("minecraft:elytra");
|
||||
public static final Key GOAT_HORN = Key.of("minecraft:goat_horn");
|
||||
public static final Key WOODEN_AXE = Key.of("minecraft:wooden_axe");
|
||||
public static final Key STONE_AXE = Key.of("minecraft:stone_axe");
|
||||
public static final Key IRON_AXE = Key.of("minecraft:iron_axe");
|
||||
public static final Key GOLDEN_AXE = Key.of("minecraft:golden_axe");
|
||||
public static final Key DIAMOND_AXE = Key.of("minecraft:diamond_axe");
|
||||
public static final Key NETHERITE_AXE = Key.of("minecraft:netherite_axe");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.pack.LegacyOverridesModel;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.generator.ModelGenerator;
|
||||
@@ -42,6 +43,8 @@ public interface ItemManager<T> extends Reloadable, ModelGenerator, ConfigSectio
|
||||
|
||||
Optional<CustomItem<T>> getCustomItem(Key key);
|
||||
|
||||
Optional<List<ItemBehavior>> getItemBehavior(Key key);
|
||||
|
||||
Optional<? extends BuildableItem<T>> getVanillaItem(Key key);
|
||||
|
||||
default Optional<? extends BuildableItem<T>> getBuildableItem(Key key) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
public abstract class ItemBehavior {
|
||||
|
||||
@@ -12,7 +12,7 @@ public abstract class ItemBehavior {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
public InteractionResult use(CEWorld context, Player player, InteractionHand hand) {
|
||||
public InteractionResult use(World world, Player player, InteractionHand hand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user