mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-06 15:52:03 +00:00
Custom Fuel
This commit is contained in:
@@ -151,6 +151,8 @@ items:
|
||||
default:palm_log:
|
||||
material: paper
|
||||
custom-model-data: 1000
|
||||
settings:
|
||||
fuel-time: 300
|
||||
tags:
|
||||
- "default:palm_logs"
|
||||
- "minecraft:logs"
|
||||
@@ -168,6 +170,8 @@ items:
|
||||
default:stripped_palm_log:
|
||||
material: paper
|
||||
custom-model-data: 1001
|
||||
settings:
|
||||
fuel-time: 300
|
||||
tags:
|
||||
- "default:palm_logs"
|
||||
- "minecraft:logs"
|
||||
@@ -185,6 +189,8 @@ items:
|
||||
default:palm_wood:
|
||||
material: paper
|
||||
custom-model-data: 1002
|
||||
settings:
|
||||
fuel-time: 300
|
||||
tags:
|
||||
- "default:palm_logs"
|
||||
- "minecraft:logs"
|
||||
@@ -202,6 +208,8 @@ items:
|
||||
default:stripped_palm_wood:
|
||||
material: paper
|
||||
custom-model-data: 1003
|
||||
settings:
|
||||
fuel-time: 300
|
||||
tags:
|
||||
- "default:palm_logs"
|
||||
- "minecraft:logs"
|
||||
@@ -219,6 +227,8 @@ items:
|
||||
default:palm_planks:
|
||||
material: paper
|
||||
custom-model-data: 1004
|
||||
settings:
|
||||
fuel-time: 300
|
||||
tags:
|
||||
- "minecraft:planks"
|
||||
- "minecraft:wooden_tool_materials"
|
||||
@@ -235,6 +245,8 @@ items:
|
||||
default:palm_sapling:
|
||||
material: paper
|
||||
custom-model-data: 1005
|
||||
settings:
|
||||
fuel-time: 100
|
||||
data:
|
||||
display-name: "<!i>Palm Sapling"
|
||||
model:
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.momirealms.craftengine.bukkit.util.MaterialUtils;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemSettings;
|
||||
import net.momirealms.craftengine.core.item.behavior.EmptyItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemModifier;
|
||||
@@ -22,13 +23,15 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
|
||||
private final Material material;
|
||||
private final List<ItemModifier<ItemStack>> modifiers;
|
||||
private final ItemBehavior behavior;
|
||||
private final ItemSettings settings;
|
||||
|
||||
public BukkitCustomItem(Key id, Key materialKey, Material material, List<ItemModifier<ItemStack>> modifiers, ItemBehavior behavior) {
|
||||
public BukkitCustomItem(Key id, Key materialKey, Material material, List<ItemModifier<ItemStack>> modifiers, ItemBehavior behavior, ItemSettings settings) {
|
||||
this.id = id;
|
||||
this.material = material;
|
||||
this.modifiers = modifiers;
|
||||
this.behavior = behavior;
|
||||
this.materialKey = materialKey;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,6 +63,11 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
|
||||
return wrapped.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemSettings settings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> buildItem(Player player) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
@@ -84,6 +92,7 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
|
||||
private Material material;
|
||||
private Key materialKey;
|
||||
private ItemBehavior behavior = EmptyItemBehavior.INSTANCE;
|
||||
private ItemSettings settings = ItemSettings.of();
|
||||
private final List<ItemModifier<ItemStack>> modifiers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
@@ -117,9 +126,15 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ItemStack> settings(ItemSettings settings) {
|
||||
this.settings = settings;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomItem<ItemStack> build() {
|
||||
return new BukkitCustomItem(id, materialKey, material, modifiers, behavior);
|
||||
return new BukkitCustomItem(id, materialKey, material, modifiers, behavior, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,18 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
return this.customItemTags.getOrDefault(tag, List.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fuelTime(ItemStack itemStack) {
|
||||
if (ItemUtils.isEmpty(itemStack)) return 0;
|
||||
Optional<CustomItem<ItemStack>> customItem = wrap(itemStack).getCustomItem();
|
||||
return customItem.map(it -> it.settings().fuelTime()).orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fuelTime(Key id) {
|
||||
return getCustomItem(id).map(it -> it.settings().fuelTime()).orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
@@ -255,6 +267,12 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
}, () -> plugin.logger().warn(path, dataEntry.getKey() + " is not a valid data type"));
|
||||
}
|
||||
}
|
||||
|
||||
if (section.containsKey("settings")) {
|
||||
Map<String, Object> settings = MiscUtils.castToMap(section.get("settings"), false);
|
||||
itemBuilder.settings(ItemSettings.fromMap(settings));
|
||||
}
|
||||
|
||||
this.customItems.put(id, itemBuilder.build());
|
||||
|
||||
List<String> tags = MiscUtils.getAsStringList(section.get("tags"));
|
||||
|
||||
@@ -27,9 +27,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent;
|
||||
import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.*;
|
||||
|
||||
@@ -49,6 +47,207 @@ public class RecipeEventListener implements Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onClickInventoryWithFuel(InventoryClickEvent event) {
|
||||
Inventory inventory = event.getInventory();
|
||||
if (!(inventory instanceof FurnaceInventory furnaceInventory)) return;
|
||||
ItemStack fuelStack = furnaceInventory.getFuel();
|
||||
Inventory clickedInventory = event.getClickedInventory();
|
||||
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if (clickedInventory == player.getInventory()) {
|
||||
if (event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT) {
|
||||
ItemStack item = event.getCurrentItem();
|
||||
if (ItemUtils.isEmpty(item)) return;
|
||||
if (fuelStack == null || fuelStack.getType() == Material.AIR) {
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(item);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) return;
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), item));
|
||||
Key recipeType;
|
||||
if (furnaceInventory.getType() == InventoryType.FURNACE) {
|
||||
recipeType = RecipeTypes.SMELTING;
|
||||
} else if (furnaceInventory.getType() == InventoryType.BLAST_FURNACE) {
|
||||
recipeType = RecipeTypes.BLASTING;
|
||||
} else {
|
||||
recipeType = RecipeTypes.SMOKING;
|
||||
}
|
||||
|
||||
Recipe<ItemStack> ceRecipe = recipeManager.getRecipe(recipeType, input);
|
||||
// The item is an ingredient, we should never consider it as fuel firstly
|
||||
if (ceRecipe != null) return;
|
||||
|
||||
int fuelTime = this.itemManager.fuelTime(item);
|
||||
if (fuelTime == 0) {
|
||||
if (ItemUtils.isCustomItem(item) && item.getType().isFuel()) {
|
||||
event.setCancelled(true);
|
||||
ItemStack smelting = furnaceInventory.getSmelting();
|
||||
if (ItemUtils.isEmpty(smelting)) {
|
||||
furnaceInventory.setSmelting(item.clone());
|
||||
item.setAmount(0);
|
||||
} else if (smelting.isSimilar(item)) {
|
||||
int maxStackSize = smelting.getMaxStackSize();
|
||||
int canGiveMaxCount = item.getAmount();
|
||||
if (maxStackSize > smelting.getAmount()) {
|
||||
if (canGiveMaxCount + smelting.getAmount() >= maxStackSize) {
|
||||
int givenCount = maxStackSize - smelting.getAmount();
|
||||
smelting.setAmount(maxStackSize);
|
||||
item.setAmount(item.getAmount() - givenCount);
|
||||
} else {
|
||||
smelting.setAmount(smelting.getAmount() + canGiveMaxCount);
|
||||
item.setAmount(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
player.updateInventory();
|
||||
}
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
furnaceInventory.setFuel(item.clone());
|
||||
item.setAmount(0);
|
||||
player.updateInventory();
|
||||
} else {
|
||||
if (fuelStack.isSimilar(item)) {
|
||||
event.setCancelled(true);
|
||||
int maxStackSize = fuelStack.getMaxStackSize();
|
||||
int canGiveMaxCount = item.getAmount();
|
||||
if (maxStackSize > fuelStack.getAmount()) {
|
||||
if (canGiveMaxCount + fuelStack.getAmount() >= maxStackSize) {
|
||||
int givenCount = maxStackSize - fuelStack.getAmount();
|
||||
fuelStack.setAmount(maxStackSize);
|
||||
item.setAmount(item.getAmount() - givenCount);
|
||||
} else {
|
||||
fuelStack.setAmount(fuelStack.getAmount() + canGiveMaxCount);
|
||||
item.setAmount(0);
|
||||
}
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// click the furnace inventory
|
||||
int slot = event.getSlot();
|
||||
// click the fuel slot
|
||||
if (slot != 1) {
|
||||
return;
|
||||
}
|
||||
ClickType clickType = event.getClick();
|
||||
switch (clickType) {
|
||||
case SWAP_OFFHAND, NUMBER_KEY -> {
|
||||
ItemStack item;
|
||||
int hotBarSlot = event.getHotbarButton();
|
||||
if (clickType == ClickType.SWAP_OFFHAND) {
|
||||
item = player.getInventory().getItemInOffHand();
|
||||
} else {
|
||||
item = player.getInventory().getItem(hotBarSlot);
|
||||
}
|
||||
if (item == null) return;
|
||||
int fuelTime = this.plugin.itemManager().fuelTime(item);
|
||||
// only handle custom items
|
||||
if (fuelTime == 0) {
|
||||
if (ItemUtils.isCustomItem(item) && item.getType().isFuel()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
if (fuelStack == null || fuelStack.getType() == Material.AIR) {
|
||||
furnaceInventory.setFuel(item.clone());
|
||||
item.setAmount(0);
|
||||
} else {
|
||||
if (clickType == ClickType.SWAP_OFFHAND) {
|
||||
player.getInventory().setItemInOffHand(fuelStack);
|
||||
} else {
|
||||
player.getInventory().setItem(hotBarSlot, fuelStack);
|
||||
}
|
||||
furnaceInventory.setFuel(item.clone());
|
||||
}
|
||||
player.updateInventory();
|
||||
}
|
||||
case LEFT, RIGHT -> {
|
||||
ItemStack itemOnCursor = event.getCursor();
|
||||
// pick item
|
||||
if (ItemUtils.isEmpty(itemOnCursor)) return;
|
||||
int fuelTime = this.plugin.itemManager().fuelTime(itemOnCursor);
|
||||
// only handle custom items
|
||||
if (fuelTime == 0) {
|
||||
if (ItemUtils.isCustomItem(itemOnCursor) && itemOnCursor.getType().isFuel()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
// The slot is empty
|
||||
if (fuelStack == null || fuelStack.getType() == Material.AIR) {
|
||||
if (clickType == ClickType.LEFT) {
|
||||
furnaceInventory.setFuel(itemOnCursor.clone());
|
||||
itemOnCursor.setAmount(0);
|
||||
player.updateInventory();
|
||||
} else {
|
||||
ItemStack cloned = itemOnCursor.clone();
|
||||
cloned.setAmount(1);
|
||||
furnaceInventory.setFuel(cloned);
|
||||
itemOnCursor.setAmount(itemOnCursor.getAmount() - 1);
|
||||
player.updateInventory();
|
||||
}
|
||||
} else {
|
||||
boolean isSimilar = itemOnCursor.isSimilar(fuelStack);
|
||||
if (clickType == ClickType.LEFT) {
|
||||
if (isSimilar) {
|
||||
int maxStackSize = fuelStack.getMaxStackSize();
|
||||
int canGiveMaxCount = itemOnCursor.getAmount();
|
||||
if (maxStackSize > fuelStack.getAmount()) {
|
||||
if (canGiveMaxCount + fuelStack.getAmount() >= maxStackSize) {
|
||||
int givenCount = maxStackSize - fuelStack.getAmount();
|
||||
fuelStack.setAmount(maxStackSize);
|
||||
itemOnCursor.setAmount(itemOnCursor.getAmount() - givenCount);
|
||||
} else {
|
||||
fuelStack.setAmount(fuelStack.getAmount() + canGiveMaxCount);
|
||||
itemOnCursor.setAmount(0);
|
||||
}
|
||||
player.updateInventory();
|
||||
}
|
||||
} else {
|
||||
// swap item
|
||||
event.setCursor(fuelStack);
|
||||
furnaceInventory.setFuel(itemOnCursor.clone());
|
||||
player.updateInventory();
|
||||
}
|
||||
} else {
|
||||
if (isSimilar) {
|
||||
int maxStackSize = fuelStack.getMaxStackSize();
|
||||
if (maxStackSize > fuelStack.getAmount()) {
|
||||
fuelStack.setAmount(fuelStack.getAmount() + 1);
|
||||
itemOnCursor.setAmount(itemOnCursor.getAmount() - 1);
|
||||
player.updateInventory();
|
||||
}
|
||||
} else {
|
||||
// swap item
|
||||
event.setCursor(fuelStack);
|
||||
furnaceInventory.setFuel(itemOnCursor.clone());
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
|
||||
public void onFurnaceBurn(FurnaceBurnEvent event) {
|
||||
ItemStack fuel = event.getFuel();
|
||||
int fuelTime = this.itemManager.fuelTime(fuel);
|
||||
if (fuelTime != 0) {
|
||||
event.setBurnTime(fuelTime);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onFurnaceInventoryOpen(InventoryOpenEvent event) {
|
||||
if (!(event.getInventory() instanceof FurnaceInventory furnaceInventory)) {
|
||||
@@ -59,7 +258,7 @@ public class RecipeEventListener implements Listener {
|
||||
Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(furnace);
|
||||
BukkitInjector.injectCookingBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
this.plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ public class BlockSettings {
|
||||
newSettings.isRedstoneConductor = settings.isRedstoneConductor;
|
||||
newSettings.isSuffocating = settings.isSuffocating;
|
||||
newSettings.isViewBlocking = settings.isViewBlocking;
|
||||
newSettings.correctTools = settings.correctTools;
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ public interface CustomItem<I> extends BuildableItem<I> {
|
||||
|
||||
I buildItemStack(Player player, int count);
|
||||
|
||||
ItemSettings settings();
|
||||
|
||||
Item<I> buildItem(Player player);
|
||||
|
||||
@NotNull
|
||||
@@ -38,6 +40,8 @@ public interface CustomItem<I> extends BuildableItem<I> {
|
||||
|
||||
Builder<I> behavior(ItemBehavior behavior);
|
||||
|
||||
Builder<I> settings(ItemSettings settings);
|
||||
|
||||
CustomItem<I> build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,10 @@ public interface ItemManager<T> extends Reloadable, ModelGenerator, ConfigSectio
|
||||
|
||||
List<Holder<Key>> tagToCustomItems(Key tag);
|
||||
|
||||
int fuelTime(T itemStack);
|
||||
|
||||
int fuelTime(Key id);
|
||||
|
||||
default int loadingSequence() {
|
||||
return LoadingSequence.ITEM;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemSettings {
|
||||
int fuelTime;
|
||||
|
||||
private ItemSettings() {}
|
||||
|
||||
public static ItemSettings of() {
|
||||
return new ItemSettings();
|
||||
}
|
||||
|
||||
public static ItemSettings fromMap(Map<String, Object> map) {
|
||||
return applyModifiers(ItemSettings.of(), map);
|
||||
}
|
||||
|
||||
public static ItemSettings ofFullCopy(ItemSettings settings) {
|
||||
ItemSettings newSettings = of();
|
||||
newSettings.fuelTime = settings.fuelTime;
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
public static ItemSettings applyModifiers(ItemSettings settings, Map<String, Object> map) {
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
ItemSettings.Modifier.Factory factory = ItemSettings.Modifiers.FACTORIES.get(entry.getKey());
|
||||
if (factory != null) {
|
||||
factory.createModifier(entry.getValue()).apply(settings);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown item settings key: " + entry.getKey());
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
public int fuelTime() {
|
||||
return fuelTime;
|
||||
}
|
||||
|
||||
public ItemSettings fuelTime(int fuelTime) {
|
||||
this.fuelTime = fuelTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public interface Modifier {
|
||||
|
||||
void apply(ItemSettings settings);
|
||||
|
||||
interface Factory {
|
||||
|
||||
ItemSettings.Modifier createModifier(Object value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Modifiers {
|
||||
private static final Map<String, ItemSettings.Modifier.Factory> FACTORIES = new HashMap<>();
|
||||
|
||||
static {
|
||||
registerFactory("fuel-time", (value -> {
|
||||
int intValue = MiscUtils.getAsInt(value);
|
||||
return settings -> settings.fuelTime(intValue);
|
||||
}));
|
||||
}
|
||||
|
||||
private static void registerFactory(String id, ItemSettings.Modifier.Factory factory) {
|
||||
FACTORIES.put(id, factory);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user